mirror of
https://github.com/python/cpython.git
synced 2025-08-25 11:15:02 +00:00
gh-128563: A new tail-calling interpreter (GH-128718)
Co-authored-by: Garrett Gu <garrettgu777@gmail.com> Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com> Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
This commit is contained in:
parent
555dc50c81
commit
cb640b659e
16 changed files with 3883 additions and 623 deletions
|
@ -70,12 +70,41 @@
|
|||
#define INSTRUCTION_STATS(op) ((void)0)
|
||||
#endif
|
||||
|
||||
#if USE_COMPUTED_GOTOS
|
||||
#define TAIL_CALL_PARAMS _PyInterpreterFrame *frame, _PyStackRef *stack_pointer, PyThreadState *tstate, _Py_CODEUNIT *next_instr, int oparg
|
||||
#define TAIL_CALL_ARGS frame, stack_pointer, tstate, next_instr, oparg
|
||||
|
||||
#ifdef Py_TAIL_CALL_INTERP
|
||||
// Note: [[clang::musttail]] works for GCC 15, but not __attribute__((musttail)) at the moment.
|
||||
# define Py_MUSTTAIL [[clang::musttail]]
|
||||
# define Py_PRESERVE_NONE_CC __attribute__((preserve_none))
|
||||
Py_PRESERVE_NONE_CC typedef PyObject* (*py_tail_call_funcptr)(TAIL_CALL_PARAMS);
|
||||
|
||||
# define TARGET(op) Py_PRESERVE_NONE_CC PyObject *_TAIL_CALL_##op(TAIL_CALL_PARAMS)
|
||||
# define DISPATCH_GOTO() \
|
||||
do { \
|
||||
Py_MUSTTAIL return (INSTRUCTION_TABLE[opcode])(TAIL_CALL_ARGS); \
|
||||
} while (0)
|
||||
# define JUMP_TO_LABEL(name) \
|
||||
do { \
|
||||
Py_MUSTTAIL return (_TAIL_CALL_##name)(TAIL_CALL_ARGS); \
|
||||
} while (0)
|
||||
# define JUMP_TO_PREDICTED(name) \
|
||||
do { \
|
||||
Py_MUSTTAIL return (_TAIL_CALL_##name)(frame, stack_pointer, tstate, this_instr, oparg); \
|
||||
} while (0)
|
||||
# define LABEL(name) TARGET(name)
|
||||
#elif USE_COMPUTED_GOTOS
|
||||
# define TARGET(op) TARGET_##op:
|
||||
# define DISPATCH_GOTO() goto *opcode_targets[opcode]
|
||||
# define JUMP_TO_LABEL(name) goto name;
|
||||
# define JUMP_TO_PREDICTED(name) goto PREDICTED_##name;
|
||||
# define LABEL(name) name:
|
||||
#else
|
||||
# define TARGET(op) case op: TARGET_##op:
|
||||
# define DISPATCH_GOTO() goto dispatch_opcode
|
||||
# define JUMP_TO_LABEL(name) goto name;
|
||||
# define JUMP_TO_PREDICTED(name) goto PREDICTED_##name;
|
||||
# define LABEL(name) name:
|
||||
#endif
|
||||
|
||||
/* PRE_DISPATCH_GOTO() does lltrace if enabled. Normally a no-op */
|
||||
|
@ -92,7 +121,7 @@ do { \
|
|||
int lltrace = maybe_lltrace_resume_frame(frame, GLOBALS()); \
|
||||
frame->lltrace = lltrace; \
|
||||
if (lltrace < 0) { \
|
||||
goto exit_unwind; \
|
||||
JUMP_TO_LABEL(exit_unwind); \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
|
@ -129,11 +158,11 @@ do { \
|
|||
assert((NEW_FRAME)->previous == frame); \
|
||||
frame = tstate->current_frame = (NEW_FRAME); \
|
||||
CALL_STAT_INC(inlined_py_calls); \
|
||||
goto start_frame; \
|
||||
JUMP_TO_LABEL(start_frame); \
|
||||
} while (0)
|
||||
|
||||
// Use this instead of 'goto error' so Tier 2 can go to a different label
|
||||
#define GOTO_ERROR(LABEL) goto LABEL
|
||||
#define GOTO_ERROR(LABEL) JUMP_TO_LABEL(LABEL)
|
||||
|
||||
/* Tuple access macros */
|
||||
|
||||
|
@ -236,14 +265,6 @@ GETITEM(PyObject *v, Py_ssize_t i) {
|
|||
#define UPDATE_MISS_STATS(INSTNAME) ((void)0)
|
||||
#endif
|
||||
|
||||
#define DEOPT_IF(COND, INSTNAME) \
|
||||
if ((COND)) { \
|
||||
/* This is only a single jump on release builds! */ \
|
||||
UPDATE_MISS_STATS((INSTNAME)); \
|
||||
assert(_PyOpcode_Deopt[opcode] == (INSTNAME)); \
|
||||
goto PREDICTED_##INSTNAME; \
|
||||
}
|
||||
|
||||
|
||||
// Try to lock an object in the free threading build, if it's not already
|
||||
// locked. Use with a DEOPT_IF() to deopt if the object is already locked.
|
||||
|
@ -328,7 +349,7 @@ do { \
|
|||
stack_pointer = _PyFrame_GetStackPointer(frame); \
|
||||
if (next_instr == NULL) { \
|
||||
next_instr = (dest)+1; \
|
||||
goto error; \
|
||||
JUMP_TO_LABEL(error); \
|
||||
} \
|
||||
} \
|
||||
} while (0);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue