Skip to content

Commit

Permalink
sorta working
Browse files Browse the repository at this point in the history
  • Loading branch information
Fidget-Spinner committed Jan 5, 2025
1 parent 2443f21 commit fb72fcd
Show file tree
Hide file tree
Showing 6 changed files with 34,157 additions and 62 deletions.
10 changes: 5 additions & 5 deletions Python/bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -1018,7 +1018,7 @@ dummy_func(
}

tier1 inst(INTERPRETER_EXIT, (retval --)) {
assert(frame == &entry_frame);
assert(frame == entry_frame);
assert(_PyFrame_IsIncomplete(frame));
/* Restore previous frame and return. */
tstate->current_frame = frame->previous;
Expand All @@ -1034,7 +1034,7 @@ dummy_func(
// is pushed to a different frame, the callers' frame.
inst(RETURN_VALUE, (retval -- res)) {
#if TIER_ONE
assert(frame != &entry_frame);
assert(frame != entry_frame);
#endif
_PyStackRef temp = retval;
DEAD(retval);
Expand Down Expand Up @@ -1133,7 +1133,7 @@ dummy_func(
PyObject *receiver_o = PyStackRef_AsPyObjectBorrow(receiver);

PyObject *retval_o;
assert(frame != &entry_frame);
assert(frame != entry_frame);
if ((tstate->interp->eval_frame == NULL) &&
(Py_TYPE(receiver_o) == &PyGen_Type || Py_TYPE(receiver_o) == &PyCoro_Type) &&
((PyGenObject *)receiver_o)->gi_frame_state < FRAME_EXECUTING)
Expand Down Expand Up @@ -1207,7 +1207,7 @@ dummy_func(
// The compiler treats any exception raised here as a failed close()
// or throw() call.
#if TIER_ONE
assert(frame != &entry_frame);
assert(frame != entry_frame);
#endif
frame->instr_ptr++;
PyGenObject *gen = _PyGen_GetGeneratorFromFrame(frame);
Expand Down Expand Up @@ -1303,7 +1303,7 @@ dummy_func(

tier1 inst(CLEANUP_THROW, (sub_iter_st, last_sent_val_st, exc_value_st -- none, value)) {
PyObject *exc_value = PyStackRef_AsPyObjectBorrow(exc_value_st);
assert(throwflag);
// assert(throwflag);
assert(exc_value && PyExceptionInstance_Check(exc_value));

int matches = PyErr_GivenExceptionMatches(exc_value, PyExc_StopIteration);
Expand Down
82 changes: 60 additions & 22 deletions Python/ceval.c
Original file line number Diff line number Diff line change
Expand Up @@ -781,13 +781,33 @@ _PyObjectArray_Free(PyObject **array, PyObject **scratch)
/* This setting is reversed below following _PyEval_EvalFrameDefault */
#endif

#ifdef Py_TAIL_CALL_INTERP
#include "generated_cases_tail_call.c.h"
#endif

#ifdef LLTRACE
PyObject *
_TAIL_CALL_shim(_PyInterpreterFrame *frame, _PyStackRef *stack_pointer,
PyThreadState *tstate, _Py_CODEUNIT *next_instr, int oparg, _PyInterpreterFrame* entry_frame, int lltrace)
{
return (INSTRUCTION_TABLE[next_instr->op.code])(frame, stack_pointer, tstate, next_instr, next_instr->op.arg, entry_frame, lltrace);
}
#else
PyObject *
_TAIL_CALL_shim(_PyInterpreterFrame *frame, _PyStackRef *stack_pointer,
PyThreadState *tstate, _Py_CODEUNIT *next_instr, int oparg, _PyInterpreterFrame* entry_frame)
{
return (INSTRUCTION_TABLE[next_instr->op.code])(frame, stack_pointer, tstate, next_instr, next_instr->op.arg, entry_frame);
}
#endif

PyObject* _Py_HOT_FUNCTION
_PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int throwflag)
{
_Py_EnsureTstateNotNULL(tstate);
CALL_STAT_INC(pyeval_calls);

#if USE_COMPUTED_GOTOS
#if USE_COMPUTED_GOTOS && !defined(Py_TAIL_CALL_INTERP)
/* Import the static jump table */
#include "opcode_targets.h"
#endif
Expand All @@ -801,27 +821,28 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
int lltrace = 0;
#endif

_PyInterpreterFrame entry_frame;
_PyInterpreterFrame e;
_PyInterpreterFrame *entry_frame = &e;



#if defined(Py_DEBUG) && !defined(Py_STACKREF_DEBUG)
/* Set these to invalid but identifiable values for debugging. */
entry_frame.f_funcobj = (_PyStackRef){.bits = 0xaaa0};
entry_frame.f_locals = (PyObject*)0xaaa1;
entry_frame.frame_obj = (PyFrameObject*)0xaaa2;
entry_frame.f_globals = (PyObject*)0xaaa3;
entry_frame.f_builtins = (PyObject*)0xaaa4;
e.f_funcobj = (_PyStackRef){.bits = 0xaaa0};
e.f_locals = (PyObject*)0xaaa1;
e.frame_obj = (PyFrameObject*)0xaaa2;
e.f_globals = (PyObject*)0xaaa3;
e.f_builtins = (PyObject*)0xaaa4;
#endif
entry_frame.f_executable = PyStackRef_None;
entry_frame.instr_ptr = (_Py_CODEUNIT *)_Py_INTERPRETER_TRAMPOLINE_INSTRUCTIONS + 1;
entry_frame.stackpointer = entry_frame.localsplus;
entry_frame.owner = FRAME_OWNED_BY_CSTACK;
entry_frame.visited = 0;
entry_frame.return_offset = 0;
e.f_executable = PyStackRef_None;
e.instr_ptr = (_Py_CODEUNIT *)_Py_INTERPRETER_TRAMPOLINE_INSTRUCTIONS + 1;
e.stackpointer = e.localsplus;
e.owner = FRAME_OWNED_BY_CSTACK;
e.visited = 0;
e.return_offset = 0;
/* Push frame */
entry_frame.previous = tstate->current_frame;
frame->previous = &entry_frame;
e.previous = tstate->current_frame;
frame->previous = entry_frame;
tstate->current_frame = frame;

tstate->c_recursion_remaining -= (PY_EVAL_C_STACK_UNITS - 1);
Expand Down Expand Up @@ -878,7 +899,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
stack_pointer = _PyFrame_GetStackPointer(frame);

#ifdef LLTRACE
lltrace = maybe_lltrace_resume_frame(frame, &entry_frame, GLOBALS());
lltrace = maybe_lltrace_resume_frame(frame, entry_frame, GLOBALS());
if (lltrace < 0) {
goto exit_unwind;
}
Expand All @@ -891,18 +912,26 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
assert(!_PyErr_Occurred(tstate));
#endif

#ifdef Py_TAIL_CALL_INTERP
#ifdef LLTRACE
return _TAIL_CALL_shim(frame, stack_pointer, tstate, next_instr, 0, entry_frame, lltrace);
#else
return _TAIL_CALL_shim(frame, stack_pointer, tstate, next_instr, 0, entry_frame);
#endif
#else
DISPATCH();
#endif

{
/* Start instructions */
#if !USE_COMPUTED_GOTOS
#if !USE_COMPUTED_GOTOS && !defined(Py_TAIL_CALL_INTERP)
dispatch_opcode:
switch (opcode)
#endif
{

#ifndef Py_TAIL_CALL_INTERP
#include "generated_cases.c.h"

#endif

#if USE_COMPUTED_GOTOS
_unknown_opcode:
Expand Down Expand Up @@ -945,7 +974,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
#endif

/* Log traceback info. */
assert(frame != &entry_frame);
assert(frame != entry_frame);
if (!_PyFrame_IsIncomplete(frame)) {
PyFrameObject *f = _PyFrame_GetFrameObject(frame);
if (f != NULL) {
Expand Down Expand Up @@ -1004,20 +1033,29 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
lltrace_resume_frame(frame);
}
#endif

#ifdef Py_TAIL_CALL_INTERP
#ifdef LLTRACE
return _TAIL_CALL_shim(frame, stack_pointer, tstate, next_instr, 0, entry_frame, lltrace);
#else
return _TAIL_CALL_shim(frame, stack_pointer, tstate, next_instr, 0, entry_frame);
#endif
#else
DISPATCH();
#endif
}
}

exit_unwind:
assert(_PyErr_Occurred(tstate));
_Py_LeaveRecursiveCallPy(tstate);
assert(frame != &entry_frame);
assert(frame != entry_frame);
// GH-99729: We need to unlink the frame *before* clearing it:
_PyInterpreterFrame *dying = frame;
frame = tstate->current_frame = dying->previous;
_PyEval_FrameClearAndPop(tstate, dying);
frame->return_offset = 0;
if (frame == &entry_frame) {
if (frame == entry_frame) {
/* Restore previous frame and exit */
tstate->current_frame = frame->previous;
tstate->c_recursion_remaining += PY_EVAL_C_STACK_UNITS;
Expand Down
81 changes: 77 additions & 4 deletions Python/ceval_macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,26 @@
#define INSTRUCTION_STATS(op) ((void)0)
#endif

#if USE_COMPUTED_GOTOS
#ifdef Py_TAIL_CALL_INTERP
#ifdef LLTRACE
__attribute__((preserve_none))
typedef PyObject* (*py_tail_call_funcptr)(_PyInterpreterFrame *, _PyStackRef *, PyThreadState *tstate, _Py_CODEUNIT *, int, _PyInterpreterFrame *, int);
#else
__attribute__((preserve_none))
typedef PyObject* (*py_tail_call_funcptr)(_PyInterpreterFrame *, _PyStackRef *, PyThreadState *tstate, _Py_CODEUNIT *, int, _PyInterpreterFrame *);
#endif
#ifdef LLTRACE
#define DISPATCH_GOTO() do { \
__attribute__((musttail)) \
return (INSTRUCTION_TABLE[opcode])(frame, stack_pointer, tstate, next_instr, oparg, entry_frame, lltrace); \
} while (0)
#else
#define DISPATCH_GOTO() do { \
__attribute__((musttail)) \
return (INSTRUCTION_TABLE[opcode])(frame, stack_pointer, tstate, next_instr, entry_frame, oparg); \
} while (0)
#endif
#elif USE_COMPUTED_GOTOS
# define TARGET(op) TARGET_##op:
# define DISPATCH_GOTO() goto *opcode_targets[opcode]
#else
Expand All @@ -89,7 +108,7 @@
#if LLTRACE
#define LLTRACE_RESUME_FRAME() \
do { \
lltrace = maybe_lltrace_resume_frame(frame, &entry_frame, GLOBALS()); \
lltrace = maybe_lltrace_resume_frame(frame, entry_frame, GLOBALS()); \
if (lltrace < 0) { \
goto exit_unwind; \
} \
Expand Down Expand Up @@ -121,6 +140,46 @@ do { \
DISPATCH_GOTO(); \
}

#ifdef Py_TAIL_CALL_INTERP
#ifdef LLTRACE
#define DISPATCH_INLINED(NEW_FRAME) \
do { \
assert(tstate->interp->eval_frame == NULL); \
_PyFrame_SetStackPointer(frame, stack_pointer); \
assert((NEW_FRAME)->previous == frame); \
frame = tstate->current_frame = (NEW_FRAME); \
CALL_STAT_INC(inlined_py_calls); \
if (_Py_EnterRecursivePy(tstate)) {\
goto exit_unwind;\
} \
next_instr = frame->instr_ptr; \
stack_pointer = _PyFrame_GetStackPointer(frame); \
lltrace = maybe_lltrace_resume_frame(frame, entry_frame, GLOBALS()); \
if (lltrace < 0) { \
goto exit_unwind; \
} \
NEXTOPARG(); \
__attribute__((musttail)) \
return (INSTRUCTION_TABLE[opcode])(frame, stack_pointer, tstate, next_instr, oparg, entry_frame, lltrace); \
} while (0)
#else
do { \
assert(tstate->interp->eval_frame == NULL); \
_PyFrame_SetStackPointer(frame, stack_pointer); \
assert((NEW_FRAME)->previous == frame); \
frame = tstate->current_frame = (NEW_FRAME); \
CALL_STAT_INC(inlined_py_calls); \
if (_Py_EnterRecursivePy(tstate)) {\
goto exit_unwind;\
} \
next_instr = frame->instr_ptr; \
stack_pointer = _PyFrame_GetStackPointer(frame); \
NEXTOPARG(); \
__attribute__((musttail)) \
return (INSTRUCTION_TABLE[opcode])(frame, stack_pointer, tstate, next_instr, oparg, entry_frame, lltrace); \
} while (0)
#endif
#else
#define DISPATCH_INLINED(NEW_FRAME) \
do { \
assert(tstate->interp->eval_frame == NULL); \
Expand All @@ -130,6 +189,7 @@ do { \
CALL_STAT_INC(inlined_py_calls); \
goto start_frame; \
} while (0)
#endif

// Use this instead of 'goto error' so Tier 2 can go to a different label
#define GOTO_ERROR(LABEL) goto LABEL
Expand Down Expand Up @@ -238,7 +298,7 @@ GETITEM(PyObject *v, Py_ssize_t i) {
#endif

#define WITHIN_STACK_BOUNDS() \
(frame == &entry_frame || (STACK_LEVEL() >= 0 && STACK_LEVEL() <= STACK_SIZE()))
(frame == entry_frame || (STACK_LEVEL() >= 0 && STACK_LEVEL() <= STACK_SIZE()))

/* Data access macros */
#define FRAME_CO_CONSTS (_PyFrame_GetCode(frame)->co_consts)
Expand All @@ -258,8 +318,21 @@ GETITEM(PyObject *v, Py_ssize_t i) {
#define SETLOCAL(i, value) do { _PyStackRef tmp = GETLOCAL(i); \
GETLOCAL(i) = value; \
PyStackRef_XCLOSE(tmp); } while (0)

#ifdef Py_TAIL_CALL_INTERP
#ifdef LLTRACE
#define GO_TO_INSTRUCTION(op) do { \
__attribute__((musttail)) \
return (INSTRUCTION_TABLE[op])(frame, stack_pointer, tstate, next_instr - 1 - _PyOpcode_Caches[_PyOpcode_Deopt[op]], oparg, entry_frame, lltrace); \
} while (0)
#else
#define GO_TO_INSTRUCTION(op) do { \
__attribute__((musttail)) \
return (INSTRUCTION_TABLE[op])(frame, stack_pointer, tstate, next_instr - 1 - _PyOpcode_Caches[_PyOpcode_Deopt[op]], oparg, entry_frame); \
} while (0)
#endif
#else
#define GO_TO_INSTRUCTION(op) goto PREDICT_ID(op)
#endif

#ifdef Py_STATS
#define UPDATE_MISS_STATS(INSTNAME) \
Expand Down
Loading

0 comments on commit fb72fcd

Please sign in to comment.