Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Rip out the generator and class cleanup code
  • Loading branch information
brandtbucher committed Oct 31, 2022
commit 661ccd814a4ffaff9ffcbf0c8d705fc1f4192a0c
4 changes: 1 addition & 3 deletions Include/internal/pycore_frame.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,7 @@ enum _frameowner {
enum _frame_cleanup {
FRAME_CLEANUP_INVALID = 0,
FRAME_CLEANUP_ENTRY = 1,
FRAME_CLEANUP_INLINED_CLASS = 2,
FRAME_CLEANUP_INLINED_FUNCTION = 3,
FRAME_CLEANUP_INLINED_GENERATOR = 4,
FRAME_CLEANUP_INLINED_FUNCTION = 2,
};

typedef struct _PyInterpreterFrame {
Expand Down
89 changes: 0 additions & 89 deletions Python/ceval.c
Original file line number Diff line number Diff line change
Expand Up @@ -5208,55 +5208,13 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
assert(retval == NULL);
return NULL;

case FRAME_CLEANUP_INLINED_CLASS:
case FRAME_CLEANUP_INLINED_FUNCTION:
frame = cframe.current_frame = pop_frame(tstate, frame);
_Py_LeaveRecursiveCallPy(tstate);
assert(_PyErr_Occurred(tstate));
assert(retval == NULL);
goto resume_with_error;

// XXX: This is not actually used!
case FRAME_CLEANUP_INLINED_GENERATOR:
frame = cframe.current_frame = pop_frame(tstate, frame);
// XXX: Most of this is just copy-pasted from genobject.c. Refactor
// to share a single implementation.
PyGenObject *gen = _PyFrame_GetGenerator(frame);
if (gen->gi_frame_state == FRAME_EXECUTING) {
gen->gi_frame_state = FRAME_COMPLETED;
}
tstate->exc_info = gen->gi_exc_state.previous_item;
gen->gi_exc_state.previous_item = NULL;
assert(tstate->cframe->current_frame == frame->previous);
// Don't keep the reference to previous any longer than necessary.
// It may keep a chain of frames alive or create a reference cycle:
frame->previous = NULL;
if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
const char *e = "generator raised StopIteration";
if (PyCoro_CheckExact(gen)) {
e = "coroutine raised StopIteration";
}
else if (PyAsyncGen_CheckExact(gen)) {
e = "async generator raised StopIteration";
}
_PyErr_FormatFromCause(PyExc_RuntimeError, "%s", e);
}
else if (PyAsyncGen_CheckExact(gen) &&
PyErr_ExceptionMatches(PyExc_StopAsyncIteration))
{
const char *e = "async generator raised StopAsyncIteration";
_PyErr_FormatFromCause(PyExc_RuntimeError, "%s", e);
}
// Generator can't be rerun, so release the frame. First, clean the
// reference cycle through the stored exception traceback:
_PyErr_ClearExcState(&gen->gi_exc_state);
gen->gi_frame_state = FRAME_CLEARED;
_PyFrame_Clear(frame);
_Py_LeaveRecursiveCallPy(tstate);
assert(_PyErr_Occurred(tstate));
assert(retval == NULL);
goto resume_with_error;

}
Py_UNREACHABLE();

Expand All @@ -5277,23 +5235,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
assert(retval);
return retval;

// XXX: This is not actually used yet!
case FRAME_CLEANUP_INLINED_CLASS:
if (!Py_IsNone(retval)) {
const char *e = "__init__() should return None, not '%.200s'";
PyErr_Format(PyExc_TypeError, e, Py_TYPE(retval)->tp_name);
Py_CLEAR(retval);
goto exit_unwind;
}
Py_DECREF(retval);
frame = cframe.current_frame = pop_frame(tstate, frame);
// frame's stack already has the new instance pushed:
assert(frame->f_code->co_nlocalsplus < frame->stacktop);
_Py_LeaveRecursiveCallPy(tstate);
assert(!_PyErr_Occurred(tstate));
assert(retval);
goto resume_frame;

case FRAME_CLEANUP_INLINED_FUNCTION:
frame = cframe.current_frame = pop_frame(tstate, frame);
_PyFrame_StackPush(frame, retval);
Expand All @@ -5302,36 +5243,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
assert(retval);
goto resume_frame;

// XXX: This is not actually used yet!
case FRAME_CLEANUP_INLINED_GENERATOR:
frame = cframe.current_frame = pop_frame(tstate, frame);
// XXX: Most of this is just copy-pasted from genobject.c. Refactor
// to share a single implementation:
PyGenObject *gen = _PyFrame_GetGenerator(frame);
if (gen->gi_frame_state == FRAME_EXECUTING) {
gen->gi_frame_state = FRAME_COMPLETED;
}
tstate->exc_info = gen->gi_exc_state.previous_item;
gen->gi_exc_state.previous_item = NULL;
assert(tstate->cframe->current_frame == frame->previous);
// Don't keep the reference to previous any longer than necessary.
// It may keep a chain of frames alive or create a reference cycle:
frame->previous = NULL;
if (gen->gi_frame_state == FRAME_SUSPENDED) {
_PyFrame_StackPush(frame, retval);
}
else {
PyObject *iterator = _PyFrame_StackPop(frame);
assert(iterator == (PyObject *)gen);
Py_DECREF(iterator);
_PyFrame_StackPush(frame, retval);
// XXX: Jump out of whatever loop we're in!
}
_Py_LeaveRecursiveCallPy(tstate);
assert(!_PyErr_Occurred(tstate));
assert(retval);
goto resume_frame;

}
Py_UNREACHABLE();
}
Expand Down