summaryrefslogtreecommitdiffstats
path: root/Python/bytecodes.c
diff options
context:
space:
mode:
authorMark Shannon <mark@hotpy.org>2022-11-10 12:34:57 (GMT)
committerGitHub <noreply@github.com>2022-11-10 12:34:57 (GMT)
commit1e197e63e21f77b102ff2601a549dda4b6439455 (patch)
tree5d8524091404607c838bb9a0ea168c8d9c28fd6a /Python/bytecodes.c
parentdbf2faf579b4094387d65ee41f049456ca67c446 (diff)
downloadcpython-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.c141
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