aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Python/executor_cases.c.h
diff options
context:
space:
mode:
Diffstat (limited to 'Python/executor_cases.c.h')
-rw-r--r--Python/executor_cases.c.h149
1 files changed, 147 insertions, 2 deletions
diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h
index d0b794c61ef..5f15f673242 100644
--- a/Python/executor_cases.c.h
+++ b/Python/executor_cases.c.h
@@ -3032,6 +3032,153 @@
break;
}
+ case _PY_FRAME_GENERAL: {
+ PyObject **args;
+ PyObject *self_or_null;
+ PyObject *callable;
+ _PyInterpreterFrame *new_frame;
+ oparg = CURRENT_OPARG();
+ args = &stack_pointer[-oparg];
+ self_or_null = stack_pointer[-1 - oparg];
+ callable = stack_pointer[-2 - oparg];
+ // oparg counts all of the args, but *not* self:
+ int total_args = oparg;
+ if (self_or_null != NULL) {
+ args--;
+ total_args++;
+ }
+ assert(Py_TYPE(callable) == &PyFunction_Type);
+ int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable))->co_flags;
+ PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable));
+ new_frame = _PyEvalFramePushAndInit(
+ tstate, (PyFunctionObject *)callable, locals,
+ args, total_args, NULL
+ );
+ // The frame has stolen all the arguments from the stack,
+ // so there is no need to clean them up.
+ stack_pointer += -2 - oparg;
+ if (new_frame == NULL) {
+ JUMP_TO_ERROR();
+ }
+ stack_pointer[0] = (PyObject *)new_frame;
+ stack_pointer += 1;
+ break;
+ }
+
+ case _CHECK_FUNCTION_VERSION: {
+ PyObject *callable;
+ oparg = CURRENT_OPARG();
+ callable = stack_pointer[-2 - oparg];
+ uint32_t func_version = (uint32_t)CURRENT_OPERAND();
+ if (!PyFunction_Check(callable)) {
+ UOP_STAT_INC(uopcode, miss);
+ JUMP_TO_JUMP_TARGET();
+ }
+ PyFunctionObject *func = (PyFunctionObject *)callable;
+ if (func->func_version != func_version) {
+ UOP_STAT_INC(uopcode, miss);
+ JUMP_TO_JUMP_TARGET();
+ }
+ break;
+ }
+
+ case _CHECK_METHOD_VERSION: {
+ PyObject *null;
+ PyObject *callable;
+ oparg = CURRENT_OPARG();
+ null = stack_pointer[-1 - oparg];
+ callable = stack_pointer[-2 - oparg];
+ uint32_t func_version = (uint32_t)CURRENT_OPERAND();
+ if (Py_TYPE(callable) != &PyMethod_Type) {
+ UOP_STAT_INC(uopcode, miss);
+ JUMP_TO_JUMP_TARGET();
+ }
+ PyObject *func = ((PyMethodObject *)callable)->im_func;
+ if (!PyFunction_Check(func)) {
+ UOP_STAT_INC(uopcode, miss);
+ JUMP_TO_JUMP_TARGET();
+ }
+ if (((PyFunctionObject *)func)->func_version != func_version) {
+ UOP_STAT_INC(uopcode, miss);
+ JUMP_TO_JUMP_TARGET();
+ }
+ if (null != NULL) {
+ UOP_STAT_INC(uopcode, miss);
+ JUMP_TO_JUMP_TARGET();
+ }
+ break;
+ }
+
+ case _EXPAND_METHOD: {
+ PyObject *null;
+ PyObject *callable;
+ PyObject *method;
+ PyObject *self;
+ oparg = CURRENT_OPARG();
+ null = stack_pointer[-1 - oparg];
+ callable = stack_pointer[-2 - oparg];
+ assert(null == NULL);
+ assert(Py_TYPE(callable) == &PyMethod_Type);
+ self = ((PyMethodObject *)callable)->im_self;
+ Py_INCREF(self);
+ stack_pointer[-1 - oparg] = self; // Patch stack as it is used by _PY_FRAME_GENERAL
+ method = ((PyMethodObject *)callable)->im_func;
+ assert(PyFunction_Check(method));
+ Py_INCREF(method);
+ Py_DECREF(callable);
+ stack_pointer[-2 - oparg] = method;
+ stack_pointer[-1 - oparg] = self;
+ break;
+ }
+
+ case _CHECK_IS_NOT_PY_CALLABLE: {
+ PyObject *callable;
+ oparg = CURRENT_OPARG();
+ callable = stack_pointer[-2 - oparg];
+ if (PyFunction_Check(callable)) {
+ UOP_STAT_INC(uopcode, miss);
+ JUMP_TO_JUMP_TARGET();
+ }
+ if (Py_TYPE(callable) == &PyMethod_Type) {
+ UOP_STAT_INC(uopcode, miss);
+ JUMP_TO_JUMP_TARGET();
+ }
+ break;
+ }
+
+ case _CALL_NON_PY_GENERAL: {
+ PyObject **args;
+ PyObject *self_or_null;
+ PyObject *callable;
+ PyObject *res;
+ oparg = CURRENT_OPARG();
+ args = &stack_pointer[-oparg];
+ self_or_null = stack_pointer[-1 - oparg];
+ callable = stack_pointer[-2 - oparg];
+ #if TIER_ONE
+ assert(opcode != INSTRUMENTED_CALL);
+ #endif
+ int total_args = oparg;
+ if (self_or_null != NULL) {
+ args--;
+ total_args++;
+ }
+ /* Callable is not a normal Python function */
+ res = PyObject_Vectorcall(
+ callable, args,
+ total_args | PY_VECTORCALL_ARGUMENTS_OFFSET,
+ NULL);
+ assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
+ Py_DECREF(callable);
+ for (int i = 0; i < total_args; i++) {
+ Py_DECREF(args[i]);
+ }
+ if (res == NULL) JUMP_TO_ERROR();
+ stack_pointer[-2 - oparg] = res;
+ stack_pointer += -1 - oparg;
+ break;
+ }
+
case _CHECK_CALL_BOUND_METHOD_EXACT_ARGS: {
PyObject *null;
PyObject *callable;
@@ -3276,8 +3423,6 @@
break;
}
- /* _CALL_PY_WITH_DEFAULTS is not a viable micro-op for tier 2 because it uses the 'this_instr' variable */
-
case _CALL_TYPE_1: {
PyObject *arg;
PyObject *null;