diff options
author | Mark Shannon <mark@hotpy.org> | 2022-11-10 12:34:57 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-11-10 12:34:57 (GMT) |
commit | 1e197e63e21f77b102ff2601a549dda4b6439455 (patch) | |
tree | 5d8524091404607c838bb9a0ea168c8d9c28fd6a /Python/bytecodes.c | |
parent | dbf2faf579b4094387d65ee41f049456ca67c446 (diff) | |
download | cpython-1e197e63e21f77b102ff2601a549dda4b6439455.zip cpython-1e197e63e21f77b102ff2601a549dda4b6439455.tar.gz cpython-1e197e63e21f77b102ff2601a549dda4b6439455.tar.bz2 |
GH-96421: Insert shim frame on entry to interpreter (GH-96319)
* Adds EXIT_INTERPRETER instruction to exit PyEval_EvalDefault()
* Simplifies RETURN_VALUE, YIELD_VALUE and RETURN_GENERATOR instructions as they no longer need to check for entry frames.
Diffstat (limited to 'Python/bytecodes.c')
-rw-r--r-- | Python/bytecodes.c | 141 |
1 files changed, 61 insertions, 80 deletions
diff --git a/Python/bytecodes.c b/Python/bytecodes.c index c1f416e..ed12b94 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -97,8 +97,7 @@ dummy_func( PyObject *consts, _Py_CODEUNIT *next_instr, PyObject **stack_pointer, - CallShape call_shape, - _Py_CODEUNIT *first_instr, + PyObject *kwnames, int throwflag, binaryfunc binary_ops[] ) @@ -618,32 +617,34 @@ dummy_func( } // stack effect: (__0 -- ) - inst(RETURN_VALUE) { + inst(INTERPRETER_EXIT) { + assert(frame == &entry_frame); + assert(_PyFrame_IsIncomplete(frame)); PyObject *retval = POP(); assert(EMPTY()); - _PyFrame_SetStackPointer(frame, stack_pointer); - TRACE_FUNCTION_EXIT(); - DTRACE_FUNCTION_EXIT(); - _Py_LeaveRecursiveCallPy(tstate); - if (!frame->is_entry) { - frame = cframe.current_frame = pop_frame(tstate, frame); - _PyFrame_StackPush(frame, retval); - goto resume_frame; - } - _Py_LeaveRecursiveCallTstate(tstate); - if (frame->owner == FRAME_OWNED_BY_GENERATOR) { - PyGenObject *gen = _PyFrame_GetGenerator(frame); - tstate->exc_info = gen->gi_exc_state.previous_item; - gen->gi_exc_state.previous_item = NULL; - } /* Restore previous cframe and return. */ tstate->cframe = cframe.previous; tstate->cframe->use_tracing = cframe.use_tracing; assert(tstate->cframe->current_frame == frame->previous); assert(!_PyErr_Occurred(tstate)); + _Py_LeaveRecursiveCallTstate(tstate); return retval; } + // stack effect: (__0 -- ) + inst(RETURN_VALUE) { + PyObject *retval = POP(); + assert(EMPTY()); + _PyFrame_SetStackPointer(frame, stack_pointer); + TRACE_FUNCTION_EXIT(); + DTRACE_FUNCTION_EXIT(); + _Py_LeaveRecursiveCallPy(tstate); + assert(frame != &entry_frame); + frame = cframe.current_frame = pop_frame(tstate, frame); + _PyFrame_StackPush(frame, retval); + goto resume_frame; + } + // stack effect: ( -- ) inst(GET_AITER) { unaryfunc getter = NULL; @@ -775,6 +776,7 @@ dummy_func( // error: SEND stack effect depends on jump flag inst(SEND) { + assert(frame != &entry_frame); assert(STACK_LEVEL() >= 2); PyObject *v = POP(); PyObject *receiver = TOP(); @@ -839,6 +841,7 @@ dummy_func( // The compiler treats any exception raised here as a failed close() // or throw() call. assert(oparg == STACK_LEVEL()); + assert(frame != &entry_frame); PyObject *retval = POP(); PyGenObject *gen = _PyFrame_GetGenerator(frame); gen->gi_frame_state = FRAME_SUSPENDED; @@ -848,19 +851,12 @@ dummy_func( tstate->exc_info = gen->gi_exc_state.previous_item; gen->gi_exc_state.previous_item = NULL; _Py_LeaveRecursiveCallPy(tstate); - if (!frame->is_entry) { - frame = cframe.current_frame = frame->previous; - frame->prev_instr -= frame->yield_offset; - _PyFrame_StackPush(frame, retval); - goto resume_frame; - } - _Py_LeaveRecursiveCallTstate(tstate); - /* Restore previous cframe and return. */ - tstate->cframe = cframe.previous; - tstate->cframe->use_tracing = cframe.use_tracing; - assert(tstate->cframe->current_frame == frame->previous); - assert(!_PyErr_Occurred(tstate)); - return retval; + _PyInterpreterFrame *gen_frame = frame; + frame = cframe.current_frame = frame->previous; + gen_frame->previous = NULL; + frame->prev_instr -= frame->yield_offset; + _PyFrame_StackPush(frame, retval); + goto resume_frame; } // stack effect: (__0 -- ) @@ -876,7 +872,7 @@ dummy_func( if (oparg) { PyObject *lasti = PEEK(oparg + 1); if (PyLong_Check(lasti)) { - frame->prev_instr = first_instr + PyLong_AsLong(lasti); + frame->prev_instr = _PyCode_CODE(frame->f_code) + PyLong_AsLong(lasti); assert(!_PyErr_Occurred(tstate)); } else { @@ -2696,12 +2692,10 @@ dummy_func( gen->gi_exc_state.previous_item = tstate->exc_info; tstate->exc_info = &gen->gi_exc_state; gen_frame->previous = frame; - gen_frame->is_entry = false; frame = cframe.current_frame = gen_frame; goto start_frame; } - // stack effect: ( -- __0) inst(BEFORE_ASYNC_WITH) { PyObject *mgr = TOP(); @@ -2929,9 +2923,9 @@ dummy_func( // stack effect: ( -- ) inst(KW_NAMES) { - assert(call_shape.kwnames == NULL); + assert(kwnames == NULL); assert(oparg < PyTuple_GET_SIZE(consts)); - call_shape.kwnames = GETITEM(consts, oparg); + kwnames = GETITEM(consts, oparg); } // stack effect: (__0, __array[oparg] -- ) @@ -2943,7 +2937,7 @@ dummy_func( int nargs = oparg + is_meth; PyObject *callable = PEEK(nargs + 1); next_instr--; - _Py_Specialize_Call(callable, next_instr, nargs, call_shape.kwnames); + _Py_Specialize_Call(callable, next_instr, nargs, kwnames); DISPATCH_SAME_OPARG(); } STAT_INC(CALL, deferred); @@ -2972,9 +2966,9 @@ dummy_func( STACK_SHRINK(total_args); _PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit( tstate, (PyFunctionObject *)function, locals, - stack_pointer, positional_args, call_shape.kwnames + stack_pointer, positional_args, kwnames ); - call_shape.kwnames = NULL; + kwnames = NULL; STACK_SHRINK(2-is_meth); // The frame has stolen all the arguments from the stack, // so there is no need to clean them up. @@ -2994,15 +2988,15 @@ dummy_func( if (cframe.use_tracing) { res = trace_call_function( tstate, function, stack_pointer-total_args, - positional_args, call_shape.kwnames); + positional_args, kwnames); } else { res = PyObject_Vectorcall( function, stack_pointer-total_args, positional_args | PY_VECTORCALL_ARGUMENTS_OFFSET, - call_shape.kwnames); + kwnames); } - call_shape.kwnames = NULL; + kwnames = NULL; assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); Py_DECREF(function); /* Clear the stack */ @@ -3021,7 +3015,7 @@ dummy_func( // stack effect: (__0, __array[oparg] -- ) inst(CALL_PY_EXACT_ARGS) { - assert(call_shape.kwnames == NULL); + assert(kwnames == NULL); DEOPT_IF(tstate->interp->eval_frame, CALL); _PyCallCache *cache = (_PyCallCache *)next_instr; int is_meth = is_method(stack_pointer, oparg); @@ -3054,7 +3048,7 @@ dummy_func( // stack effect: (__0, __array[oparg] -- ) inst(CALL_PY_WITH_DEFAULTS) { - assert(call_shape.kwnames == NULL); + assert(kwnames == NULL); DEOPT_IF(tstate->interp->eval_frame, CALL); _PyCallCache *cache = (_PyCallCache *)next_instr; int is_meth = is_method(stack_pointer, oparg); @@ -3094,7 +3088,7 @@ dummy_func( // stack effect: (__0, __array[oparg] -- ) inst(CALL_NO_KW_TYPE_1) { - assert(call_shape.kwnames == NULL); + assert(kwnames == NULL); assert(cframe.use_tracing == 0); assert(oparg == 1); DEOPT_IF(is_method(stack_pointer, 1), CALL); @@ -3112,7 +3106,7 @@ dummy_func( // stack effect: (__0, __array[oparg] -- ) inst(CALL_NO_KW_STR_1) { - assert(call_shape.kwnames == NULL); + assert(kwnames == NULL); assert(cframe.use_tracing == 0); assert(oparg == 1); DEOPT_IF(is_method(stack_pointer, 1), CALL); @@ -3134,7 +3128,7 @@ dummy_func( // stack effect: (__0, __array[oparg] -- ) inst(CALL_NO_KW_TUPLE_1) { - assert(call_shape.kwnames == NULL); + assert(kwnames == NULL); assert(oparg == 1); DEOPT_IF(is_method(stack_pointer, 1), CALL); PyObject *callable = PEEK(2); @@ -3166,8 +3160,8 @@ dummy_func( JUMPBY(INLINE_CACHE_ENTRIES_CALL); STACK_SHRINK(total_args); PyObject *res = tp->tp_vectorcall((PyObject *)tp, stack_pointer, - total_args-kwnames_len, call_shape.kwnames); - call_shape.kwnames = NULL; + total_args-kwnames_len, kwnames); + kwnames = NULL; /* Free the arguments. */ for (int i = 0; i < total_args; i++) { Py_DECREF(stack_pointer[i]); @@ -3185,7 +3179,7 @@ dummy_func( inst(CALL_NO_KW_BUILTIN_O) { assert(cframe.use_tracing == 0); /* Builtin METH_O functions */ - assert(call_shape.kwnames == NULL); + assert(kwnames == NULL); int is_meth = is_method(stack_pointer, oparg); int total_args = oparg + is_meth; DEOPT_IF(total_args != 1, CALL); @@ -3219,7 +3213,7 @@ dummy_func( inst(CALL_NO_KW_BUILTIN_FAST) { assert(cframe.use_tracing == 0); /* Builtin METH_FASTCALL functions, without keywords */ - assert(call_shape.kwnames == NULL); + assert(kwnames == NULL); int is_meth = is_method(stack_pointer, oparg); int total_args = oparg + is_meth; PyObject *callable = PEEK(total_args + 1); @@ -3276,10 +3270,10 @@ dummy_func( PyCFunction_GET_SELF(callable), stack_pointer, total_args - KWNAMES_LEN(), - call_shape.kwnames + kwnames ); assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); - call_shape.kwnames = NULL; + kwnames = NULL; /* Free the arguments. */ for (int i = 0; i < total_args; i++) { @@ -3297,7 +3291,7 @@ dummy_func( // stack effect: (__0, __array[oparg] -- ) inst(CALL_NO_KW_LEN) { assert(cframe.use_tracing == 0); - assert(call_shape.kwnames == NULL); + assert(kwnames == NULL); /* len(o) */ int is_meth = is_method(stack_pointer, oparg); int total_args = oparg + is_meth; @@ -3327,7 +3321,7 @@ dummy_func( // stack effect: (__0, __array[oparg] -- ) inst(CALL_NO_KW_ISINSTANCE) { assert(cframe.use_tracing == 0); - assert(call_shape.kwnames == NULL); + assert(kwnames == NULL); /* isinstance(o, o2) */ int is_meth = is_method(stack_pointer, oparg); int total_args = oparg + is_meth; @@ -3360,7 +3354,7 @@ dummy_func( // stack effect: (__0, __array[oparg] -- ) inst(CALL_NO_KW_LIST_APPEND) { assert(cframe.use_tracing == 0); - assert(call_shape.kwnames == NULL); + assert(kwnames == NULL); assert(oparg == 1); PyObject *callable = PEEK(3); PyInterpreterState *interp = _PyInterpreterState_GET(); @@ -3382,7 +3376,7 @@ dummy_func( // stack effect: (__0, __array[oparg] -- ) inst(CALL_NO_KW_METHOD_DESCRIPTOR_O) { - assert(call_shape.kwnames == NULL); + assert(kwnames == NULL); int is_meth = is_method(stack_pointer, oparg); int total_args = oparg + is_meth; PyMethodDescrObject *callable = @@ -3435,9 +3429,9 @@ dummy_func( _PyCFunctionFastWithKeywords cfunc = (_PyCFunctionFastWithKeywords)(void(*)(void))meth->ml_meth; PyObject *res = cfunc(self, stack_pointer, nargs - KWNAMES_LEN(), - call_shape.kwnames); + kwnames); assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); - call_shape.kwnames = NULL; + kwnames = NULL; /* Free the arguments. */ for (int i = 0; i < nargs; i++) { @@ -3455,7 +3449,7 @@ dummy_func( // stack effect: (__0, __array[oparg] -- ) inst(CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS) { - assert(call_shape.kwnames == NULL); + assert(kwnames == NULL); assert(oparg == 0 || oparg == 1); int is_meth = is_method(stack_pointer, oparg); int total_args = oparg + is_meth; @@ -3489,7 +3483,7 @@ dummy_func( // stack effect: (__0, __array[oparg] -- ) inst(CALL_NO_KW_METHOD_DESCRIPTOR_FAST) { - assert(call_shape.kwnames == NULL); + assert(kwnames == NULL); int is_meth = is_method(stack_pointer, oparg); int total_args = oparg + is_meth; PyMethodDescrObject *callable = @@ -3606,25 +3600,12 @@ dummy_func( gen->gi_frame_state = FRAME_CREATED; gen_frame->owner = FRAME_OWNED_BY_GENERATOR; _Py_LeaveRecursiveCallPy(tstate); - if (!frame->is_entry) { - _PyInterpreterFrame *prev = frame->previous; - _PyThreadState_PopFrame(tstate, frame); - frame = cframe.current_frame = prev; - _PyFrame_StackPush(frame, (PyObject *)gen); - goto resume_frame; - } - _Py_LeaveRecursiveCallTstate(tstate); - /* Make sure that frame is in a valid state */ - frame->stacktop = 0; - frame->f_locals = NULL; - Py_INCREF(frame->f_funcobj); - Py_INCREF(frame->f_code); - /* Restore previous cframe and return. */ - tstate->cframe = cframe.previous; - tstate->cframe->use_tracing = cframe.use_tracing; - assert(tstate->cframe->current_frame == frame->previous); - assert(!_PyErr_Occurred(tstate)); - return (PyObject *)gen; + assert(frame != &entry_frame); + _PyInterpreterFrame *prev = frame->previous; + _PyThreadState_PopFrame(tstate, frame); + frame = cframe.current_frame = prev; + _PyFrame_StackPush(frame, (PyObject *)gen); + goto resume_frame; } // error: BUILD_SLICE has irregular stack effect |