GH-131498: Replace single-element arrays with scalars in bytecodes.c (GH-132615)

This commit is contained in:
Brandt Bucher 2025-04-18 07:16:28 -07:00 committed by GitHub
parent a594008d9e
commit 40ae88988c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 911 additions and 826 deletions

View file

@ -1067,7 +1067,7 @@ int _PyUop_num_popped(int opcode, int oparg)
case _CALL_METHOD_DESCRIPTOR_FAST:
return 2 + oparg;
case _MAYBE_EXPAND_METHOD_KW:
return 1;
return 0;
case _PY_FRAME_KW:
return 3 + oparg;
case _CHECK_FUNCTION_VERSION_KW:

View file

@ -425,7 +425,6 @@ dummy_func(
}
pure inst(END_SEND, (receiver, value -- val)) {
(void)receiver;
val = value;
DEAD(value);
PyStackRef_CLOSE(receiver);
@ -3636,11 +3635,11 @@ dummy_func(
CALL_NON_PY_GENERAL,
};
specializing op(_SPECIALIZE_CALL, (counter/1, callable[1], self_or_null[1], args[oparg] -- callable[1], self_or_null[1], args[oparg])) {
specializing op(_SPECIALIZE_CALL, (counter/1, callable, self_or_null, unused[oparg] -- callable, self_or_null, unused[oparg])) {
#if ENABLE_SPECIALIZATION_FT
if (ADAPTIVE_COUNTER_TRIGGERS(counter)) {
next_instr = this_instr;
_Py_Specialize_Call(callable[0], next_instr, oparg + !PyStackRef_IsNull(self_or_null[0]));
_Py_Specialize_Call(callable, next_instr, oparg + !PyStackRef_IsNull(self_or_null));
DISPATCH_SAME_OPARG();
}
OPCODE_DEFERRED_INC(CALL);
@ -3648,27 +3647,26 @@ dummy_func(
#endif /* ENABLE_SPECIALIZATION_FT */
}
op(_MAYBE_EXPAND_METHOD, (callable[1], self_or_null[1], args[oparg] -- callable[1], self_or_null[1], args[oparg])) {
(void)args;
if (PyStackRef_TYPE(callable[0]) == &PyMethod_Type && PyStackRef_IsNull(self_or_null[0])) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]);
op(_MAYBE_EXPAND_METHOD, (callable, self_or_null, unused[oparg] -- callable, self_or_null, unused[oparg])) {
if (PyStackRef_TYPE(callable) == &PyMethod_Type && PyStackRef_IsNull(self_or_null)) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
PyObject *self = ((PyMethodObject *)callable_o)->im_self;
self_or_null[0] = PyStackRef_FromPyObjectNew(self);
self_or_null = PyStackRef_FromPyObjectNew(self);
PyObject *method = ((PyMethodObject *)callable_o)->im_func;
_PyStackRef temp = callable[0];
callable[0] = PyStackRef_FromPyObjectNew(method);
_PyStackRef temp = callable;
callable = PyStackRef_FromPyObjectNew(method);
PyStackRef_CLOSE(temp);
}
}
// When calling Python, inline the call using DISPATCH_INLINED().
op(_DO_CALL, (callable[1], self_or_null[1], args[oparg] -- res)) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]);
op(_DO_CALL, (callable, self_or_null, args[oparg] -- res)) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
// oparg counts all of the args, but *not* self:
int total_args = oparg;
_PyStackRef *arguments = args;
if (!PyStackRef_IsNull(self_or_null[0])) {
if (!PyStackRef_IsNull(self_or_null)) {
arguments--;
total_args++;
}
@ -3680,7 +3678,7 @@ dummy_func(
int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable_o))->co_flags;
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable_o));
_PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit(
tstate, callable[0], locals,
tstate, callable, locals,
arguments, total_args, NULL, frame
);
DEAD(args);
@ -3730,12 +3728,12 @@ dummy_func(
res = PyStackRef_FromPyObjectSteal(res_o);
}
op(_MONITOR_CALL, (func[1], maybe_self[1], args[oparg] -- func[1], maybe_self[1], args[oparg])) {
int is_meth = !PyStackRef_IsNull(maybe_self[0]);
PyObject *function = PyStackRef_AsPyObjectBorrow(func[0]);
op(_MONITOR_CALL, (func, maybe_self, args[oparg] -- func, maybe_self, args[oparg])) {
int is_meth = !PyStackRef_IsNull(maybe_self);
PyObject *function = PyStackRef_AsPyObjectBorrow(func);
PyObject *arg0;
if (is_meth) {
arg0 = PyStackRef_AsPyObjectBorrow(maybe_self[0]);
arg0 = PyStackRef_AsPyObjectBorrow(maybe_self);
}
else if (oparg) {
arg0 = PyStackRef_AsPyObjectBorrow(args[0]);
@ -3754,12 +3752,12 @@ dummy_func(
macro(CALL) = _SPECIALIZE_CALL + unused/2 + _MAYBE_EXPAND_METHOD + _DO_CALL + _CHECK_PERIODIC;
macro(INSTRUMENTED_CALL) = unused/3 + _MAYBE_EXPAND_METHOD + _MONITOR_CALL + _DO_CALL + _CHECK_PERIODIC;
op(_PY_FRAME_GENERAL, (callable[1], self_or_null[1], args[oparg] -- new_frame: _PyInterpreterFrame*)) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]);
op(_PY_FRAME_GENERAL, (callable, self_or_null, args[oparg] -- new_frame: _PyInterpreterFrame*)) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
// oparg counts all of the args, but *not* self:
int total_args = oparg;
if (!PyStackRef_IsNull(self_or_null[0])) {
if (!PyStackRef_IsNull(self_or_null)) {
args--;
total_args++;
}
@ -3767,7 +3765,7 @@ dummy_func(
int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable_o))->co_flags;
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable_o));
_PyInterpreterFrame *temp = _PyEvalFramePushAndInit(
tstate, callable[0], locals,
tstate, callable, locals,
args, total_args, NULL, frame
);
// The frame has stolen all the arguments from the stack.
@ -3779,8 +3777,8 @@ dummy_func(
new_frame = temp;
}
op(_CHECK_FUNCTION_VERSION, (func_version/2, callable[1], self_or_null[1], unused[oparg] -- callable[1], self_or_null[1], unused[oparg])) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]);
op(_CHECK_FUNCTION_VERSION, (func_version/2, callable, unused, unused[oparg] -- callable, unused, unused[oparg])) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
EXIT_IF(!PyFunction_Check(callable_o));
PyFunctionObject *func = (PyFunctionObject *)callable_o;
EXIT_IF(func->func_version != func_version);
@ -3800,24 +3798,24 @@ dummy_func(
_SAVE_RETURN_OFFSET +
_PUSH_FRAME;
op(_CHECK_METHOD_VERSION, (func_version/2, callable[1], null[1], unused[oparg] -- callable[1], null[1], unused[oparg])) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]);
op(_CHECK_METHOD_VERSION, (func_version/2, callable, null, unused[oparg] -- callable, null, unused[oparg])) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
EXIT_IF(Py_TYPE(callable_o) != &PyMethod_Type);
PyObject *func = ((PyMethodObject *)callable_o)->im_func;
EXIT_IF(!PyFunction_Check(func));
EXIT_IF(((PyFunctionObject *)func)->func_version != func_version);
EXIT_IF(!PyStackRef_IsNull(null[0]));
EXIT_IF(!PyStackRef_IsNull(null));
}
op(_EXPAND_METHOD, (callable[1], self_or_null[1], unused[oparg] -- callable[1], self_or_null[1], unused[oparg])) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]);
assert(PyStackRef_IsNull(self_or_null[0]));
op(_EXPAND_METHOD, (callable, self_or_null, unused[oparg] -- callable, self_or_null, unused[oparg])) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
assert(PyStackRef_IsNull(self_or_null));
assert(Py_TYPE(callable_o) == &PyMethod_Type);
self_or_null[0] = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_self);
_PyStackRef temp = callable[0];
callable[0] = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_func);
assert(PyStackRef_FunctionCheck(callable[0]));
self_or_null = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_self);
_PyStackRef temp = callable;
callable = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_func);
assert(PyStackRef_FunctionCheck(callable));
PyStackRef_CLOSE(temp);
}
@ -3831,21 +3829,21 @@ dummy_func(
_SAVE_RETURN_OFFSET +
_PUSH_FRAME;
op(_CHECK_IS_NOT_PY_CALLABLE, (callable[1], unused[1], unused[oparg] -- callable[1], unused[1], unused[oparg])) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]);
op(_CHECK_IS_NOT_PY_CALLABLE, (callable, unused, unused[oparg] -- callable, unused, unused[oparg])) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
EXIT_IF(PyFunction_Check(callable_o));
EXIT_IF(Py_TYPE(callable_o) == &PyMethod_Type);
}
op(_CALL_NON_PY_GENERAL, (callable[1], self_or_null[1], args[oparg] -- res)) {
op(_CALL_NON_PY_GENERAL, (callable, self_or_null, args[oparg] -- res)) {
#if TIER_ONE
assert(opcode != INSTRUMENTED_CALL);
#endif
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]);
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
int total_args = oparg;
_PyStackRef *arguments = args;
if (!PyStackRef_IsNull(self_or_null[0])) {
if (!PyStackRef_IsNull(self_or_null)) {
arguments--;
total_args++;
}
@ -3873,18 +3871,18 @@ dummy_func(
_CALL_NON_PY_GENERAL +
_CHECK_PERIODIC;
op(_CHECK_CALL_BOUND_METHOD_EXACT_ARGS, (callable[1], null[1], unused[oparg] -- callable[1], null[1], unused[oparg])) {
EXIT_IF(!PyStackRef_IsNull(null[0]));
EXIT_IF(Py_TYPE(PyStackRef_AsPyObjectBorrow(callable[0])) != &PyMethod_Type);
op(_CHECK_CALL_BOUND_METHOD_EXACT_ARGS, (callable, null, unused[oparg] -- callable, null, unused[oparg])) {
EXIT_IF(!PyStackRef_IsNull(null));
EXIT_IF(Py_TYPE(PyStackRef_AsPyObjectBorrow(callable)) != &PyMethod_Type);
}
op(_INIT_CALL_BOUND_METHOD_EXACT_ARGS, (callable[1], self_or_null[1], unused[oparg] -- callable[1], self_or_null[1], unused[oparg])) {
assert(PyStackRef_IsNull(self_or_null[0]));
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]);
op(_INIT_CALL_BOUND_METHOD_EXACT_ARGS, (callable, self_or_null, unused[oparg] -- callable, self_or_null, unused[oparg])) {
assert(PyStackRef_IsNull(self_or_null));
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
STAT_INC(CALL, hit);
self_or_null[0] = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_self);
_PyStackRef temp = callable[0];
callable[0] = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_func);
self_or_null = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_self);
_PyStackRef temp = callable;
callable = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_func);
PyStackRef_CLOSE(temp);
}
@ -3892,28 +3890,28 @@ dummy_func(
DEOPT_IF(tstate->interp->eval_frame);
}
op(_CHECK_FUNCTION_EXACT_ARGS, (callable[1], self_or_null[1], unused[oparg] -- callable[1], self_or_null[1], unused[oparg])) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]);
op(_CHECK_FUNCTION_EXACT_ARGS, (callable, self_or_null, unused[oparg] -- callable, self_or_null, unused[oparg])) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
assert(PyFunction_Check(callable_o));
PyFunctionObject *func = (PyFunctionObject *)callable_o;
PyCodeObject *code = (PyCodeObject *)func->func_code;
EXIT_IF(code->co_argcount != oparg + (!PyStackRef_IsNull(self_or_null[0])));
EXIT_IF(code->co_argcount != oparg + (!PyStackRef_IsNull(self_or_null)));
}
op(_CHECK_STACK_SPACE, (callable[1], self_or_null[1], unused[oparg] -- callable[1], self_or_null[1], unused[oparg])) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]);
op(_CHECK_STACK_SPACE, (callable, unused, unused[oparg] -- callable, unused, unused[oparg])) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
PyFunctionObject *func = (PyFunctionObject *)callable_o;
PyCodeObject *code = (PyCodeObject *)func->func_code;
DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize));
DEOPT_IF(tstate->py_recursion_remaining <= 1);
}
replicate(5) pure op(_INIT_CALL_PY_EXACT_ARGS, (callable[1], self_or_null[1], args[oparg] -- new_frame: _PyInterpreterFrame*)) {
int has_self = !PyStackRef_IsNull(self_or_null[0]);
replicate(5) pure op(_INIT_CALL_PY_EXACT_ARGS, (callable, self_or_null, args[oparg] -- new_frame: _PyInterpreterFrame*)) {
int has_self = !PyStackRef_IsNull(self_or_null);
STAT_INC(CALL, hit);
new_frame = _PyFrame_PushUnchecked(tstate, callable[0], oparg + has_self, frame);
new_frame = _PyFrame_PushUnchecked(tstate, callable, oparg + has_self, frame);
_PyStackRef *first_non_self_local = new_frame->localsplus + has_self;
new_frame->localsplus[0] = self_or_null[0];
new_frame->localsplus[0] = self_or_null;
for (int i = 0; i < oparg; i++) {
first_non_self_local[i] = args[i];
}
@ -4018,10 +4016,9 @@ dummy_func(
_CALL_TUPLE_1 +
_CHECK_PERIODIC;
op(_CHECK_AND_ALLOCATE_OBJECT, (type_version/2, callable[1], self_or_null[1], args[oparg] -- callable[1], self_or_null[1], args[oparg])) {
(void)args;
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]);
DEOPT_IF(!PyStackRef_IsNull(self_or_null[0]));
op(_CHECK_AND_ALLOCATE_OBJECT, (type_version/2, callable, self_or_null, unused[oparg] -- callable, self_or_null, unused[oparg])) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
DEOPT_IF(!PyStackRef_IsNull(self_or_null));
DEOPT_IF(!PyType_Check(callable_o));
PyTypeObject *tp = (PyTypeObject *)callable_o;
DEOPT_IF(FT_ATOMIC_LOAD_UINT32_RELAXED(tp->tp_version_tag) != type_version);
@ -4037,21 +4034,21 @@ dummy_func(
if (self_o == NULL) {
ERROR_NO_POP();
}
self_or_null[0] = PyStackRef_FromPyObjectSteal(self_o);
_PyStackRef temp = callable[0];
callable[0] = PyStackRef_FromPyObjectNew(init_func);
self_or_null = PyStackRef_FromPyObjectSteal(self_o);
_PyStackRef temp = callable;
callable = PyStackRef_FromPyObjectNew(init_func);
PyStackRef_CLOSE(temp);
}
op(_CREATE_INIT_FRAME, (init[1], self[1], args[oparg] -- init_frame: _PyInterpreterFrame *)) {
op(_CREATE_INIT_FRAME, (init, self, args[oparg] -- init_frame: _PyInterpreterFrame *)) {
_PyInterpreterFrame *shim = _PyFrame_PushTrampolineUnchecked(
tstate, (PyCodeObject *)&_Py_InitCleanup, 1, frame);
assert(_PyFrame_GetBytecode(shim)[0].op.code == EXIT_INIT_CHECK);
assert(_PyFrame_GetBytecode(shim)[1].op.code == RETURN_VALUE);
/* Push self onto stack of shim */
shim->localsplus[0] = PyStackRef_DUP(self[0]);
shim->localsplus[0] = PyStackRef_DUP(self);
_PyInterpreterFrame *temp = _PyEvalFramePushAndInit(
tstate, init[0], NULL, args-1, oparg+1, NULL, shim);
tstate, init, NULL, args-1, oparg+1, NULL, shim);
DEAD(init);
DEAD(self);
DEAD(args);
@ -4085,13 +4082,13 @@ dummy_func(
DEAD(should_be_none);
}
op(_CALL_BUILTIN_CLASS, (callable[1], self_or_null[1], args[oparg] -- res)) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]);
op(_CALL_BUILTIN_CLASS, (callable, self_or_null, args[oparg] -- res)) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
DEOPT_IF(!PyType_Check(callable_o));
PyTypeObject *tp = (PyTypeObject *)callable_o;
int total_args = oparg;
_PyStackRef *arguments = args;
if (!PyStackRef_IsNull(self_or_null[0])) {
if (!PyStackRef_IsNull(self_or_null)) {
arguments--;
total_args++;
}
@ -4115,12 +4112,12 @@ dummy_func(
_CALL_BUILTIN_CLASS +
_CHECK_PERIODIC;
op(_CALL_BUILTIN_O, (callable[1], self_or_null[1], args[oparg] -- res)) {
op(_CALL_BUILTIN_O, (callable, self_or_null, args[oparg] -- res)) {
/* Builtin METH_O functions */
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]);
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
int total_args = oparg;
if (!PyStackRef_IsNull(self_or_null[0])) {
if (!PyStackRef_IsNull(self_or_null)) {
args--;
total_args++;
}
@ -4139,7 +4136,7 @@ dummy_func(
PyStackRef_CLOSE(arg);
DEAD(args);
DEAD(self_or_null);
PyStackRef_CLOSE(callable[0]);
PyStackRef_CLOSE(callable);
ERROR_IF(res_o == NULL, error);
res = PyStackRef_FromPyObjectSteal(res_o);
}
@ -4150,13 +4147,13 @@ dummy_func(
_CALL_BUILTIN_O +
_CHECK_PERIODIC;
op(_CALL_BUILTIN_FAST, (callable[1], self_or_null[1], args[oparg] -- res)) {
op(_CALL_BUILTIN_FAST, (callable, self_or_null, args[oparg] -- res)) {
/* Builtin METH_FASTCALL functions, without keywords */
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]);
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
int total_args = oparg;
_PyStackRef *arguments = args;
if (!PyStackRef_IsNull(self_or_null[0])) {
if (!PyStackRef_IsNull(self_or_null)) {
arguments--;
total_args++;
}
@ -4187,13 +4184,13 @@ dummy_func(
_CALL_BUILTIN_FAST +
_CHECK_PERIODIC;
op(_CALL_BUILTIN_FAST_WITH_KEYWORDS, (callable[1], self_or_null[1], args[oparg] -- res)) {
op(_CALL_BUILTIN_FAST_WITH_KEYWORDS, (callable, self_or_null, args[oparg] -- res)) {
/* Builtin METH_FASTCALL | METH_KEYWORDS functions */
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]);
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
int total_args = oparg;
_PyStackRef *arguments = args;
if (!PyStackRef_IsNull(self_or_null[0])) {
if (!PyStackRef_IsNull(self_or_null)) {
arguments--;
total_args++;
}
@ -4223,12 +4220,12 @@ dummy_func(
_CALL_BUILTIN_FAST_WITH_KEYWORDS +
_CHECK_PERIODIC;
inst(CALL_LEN, (unused/1, unused/2, callable[1], self_or_null[1], args[oparg] -- res)) {
inst(CALL_LEN, (unused/1, unused/2, callable, self_or_null, args[oparg] -- res)) {
/* len(o) */
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]);
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
int total_args = oparg;
if (!PyStackRef_IsNull(self_or_null[0])) {
if (!PyStackRef_IsNull(self_or_null)) {
args--;
total_args++;
}
@ -4250,17 +4247,17 @@ dummy_func(
PyStackRef_CLOSE(arg_stackref);
DEAD(args);
DEAD(self_or_null);
PyStackRef_CLOSE(callable[0]);
PyStackRef_CLOSE(callable);
res = PyStackRef_FromPyObjectSteal(res_o);
}
inst(CALL_ISINSTANCE, (unused/1, unused/2, callable, self_or_null[1], args[oparg] -- res)) {
inst(CALL_ISINSTANCE, (unused/1, unused/2, callable, self_or_null, args[oparg] -- res)) {
/* isinstance(o, o2) */
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
int total_args = oparg;
_PyStackRef *arguments = args;
if (!PyStackRef_IsNull(self_or_null[0])) {
if (!PyStackRef_IsNull(self_or_null)) {
arguments--;
total_args++;
}
@ -4304,12 +4301,12 @@ dummy_func(
#endif
}
op(_CALL_METHOD_DESCRIPTOR_O, (callable[1], self_or_null[1], args[oparg] -- res)) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]);
op(_CALL_METHOD_DESCRIPTOR_O, (callable, self_or_null, args[oparg] -- res)) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
int total_args = oparg;
_PyStackRef *arguments = args;
if (!PyStackRef_IsNull(self_or_null[0])) {
if (!PyStackRef_IsNull(self_or_null)) {
arguments--;
total_args++;
}
@ -4343,12 +4340,12 @@ dummy_func(
_CALL_METHOD_DESCRIPTOR_O +
_CHECK_PERIODIC;
op(_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, (callable[1], self_or_null[1], args[oparg] -- res)) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]);
op(_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, (callable, self_or_null, args[oparg] -- res)) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
int total_args = oparg;
_PyStackRef *arguments = args;
if (!PyStackRef_IsNull(self_or_null[0])) {
if (!PyStackRef_IsNull(self_or_null)) {
arguments--;
total_args++;
}
@ -4385,12 +4382,12 @@ dummy_func(
_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS +
_CHECK_PERIODIC;
op(_CALL_METHOD_DESCRIPTOR_NOARGS, (callable[1], self_or_null[1], args[oparg] -- res)) {
op(_CALL_METHOD_DESCRIPTOR_NOARGS, (callable, self_or_null, args[oparg] -- res)) {
assert(oparg == 0 || oparg == 1);
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]);
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
int total_args = oparg;
if (!PyStackRef_IsNull(self_or_null[0])) {
if (!PyStackRef_IsNull(self_or_null)) {
args--;
total_args++;
}
@ -4412,7 +4409,7 @@ dummy_func(
PyStackRef_CLOSE(self_stackref);
DEAD(args);
DEAD(self_or_null);
PyStackRef_CLOSE(callable[0]);
PyStackRef_CLOSE(callable);
ERROR_IF(res_o == NULL, error);
res = PyStackRef_FromPyObjectSteal(res_o);
}
@ -4423,12 +4420,12 @@ dummy_func(
_CALL_METHOD_DESCRIPTOR_NOARGS +
_CHECK_PERIODIC;
op(_CALL_METHOD_DESCRIPTOR_FAST, (callable[1], self_or_null[1], args[oparg] -- res)) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]);
op(_CALL_METHOD_DESCRIPTOR_FAST, (callable, self_or_null, args[oparg] -- res)) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
int total_args = oparg;
_PyStackRef *arguments = args;
if (!PyStackRef_IsNull(self_or_null[0])) {
if (!PyStackRef_IsNull(self_or_null)) {
arguments--;
total_args++;
}
@ -4471,11 +4468,11 @@ dummy_func(
CALL_KW_NON_PY,
};
op(_MONITOR_CALL_KW, (callable[1], self_or_null[1], args[oparg], kwnames -- callable[1], self_or_null[1], args[oparg], kwnames)) {
int is_meth = !PyStackRef_IsNull(self_or_null[0]);
op(_MONITOR_CALL_KW, (callable, self_or_null, args[oparg], unused -- callable, self_or_null, args[oparg], unused)) {
int is_meth = !PyStackRef_IsNull(self_or_null);
PyObject *arg;
if (is_meth) {
arg = PyStackRef_AsPyObjectBorrow(self_or_null[0]);
arg = PyStackRef_AsPyObjectBorrow(self_or_null);
}
else if (args) {
arg = PyStackRef_AsPyObjectBorrow(args[0]);
@ -4483,36 +4480,33 @@ dummy_func(
else {
arg = &_PyInstrumentation_MISSING;
}
PyObject *function = PyStackRef_AsPyObjectBorrow(callable[0]);
PyObject *function = PyStackRef_AsPyObjectBorrow(callable);
int err = _Py_call_instrumentation_2args(
tstate, PY_MONITORING_EVENT_CALL,
frame, this_instr, function, arg);
ERROR_IF(err, error);
}
op(_MAYBE_EXPAND_METHOD_KW, (callable[1], self_or_null[1], args[oparg], kwnames_in -- callable[1], self_or_null[1], args[oparg], kwnames_out)) {
(void)args;
if (PyStackRef_TYPE(callable[0]) == &PyMethod_Type && PyStackRef_IsNull(self_or_null[0])) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]);
op(_MAYBE_EXPAND_METHOD_KW, (callable, self_or_null, unused[oparg], unused -- callable, self_or_null, unused[oparg], unused)) {
if (PyStackRef_TYPE(callable) == &PyMethod_Type && PyStackRef_IsNull(self_or_null)) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
PyObject *self = ((PyMethodObject *)callable_o)->im_self;
self_or_null[0] = PyStackRef_FromPyObjectNew(self);
self_or_null = PyStackRef_FromPyObjectNew(self);
PyObject *method = ((PyMethodObject *)callable_o)->im_func;
_PyStackRef temp = callable[0];
callable[0] = PyStackRef_FromPyObjectNew(method);
_PyStackRef temp = callable;
callable = PyStackRef_FromPyObjectNew(method);
PyStackRef_CLOSE(temp);
}
kwnames_out = kwnames_in;
DEAD(kwnames_in);
}
op(_DO_CALL_KW, (callable[1], self_or_null[1], args[oparg], kwnames -- res)) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]);
op(_DO_CALL_KW, (callable, self_or_null, args[oparg], kwnames -- res)) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
PyObject *kwnames_o = PyStackRef_AsPyObjectBorrow(kwnames);
// oparg counts all of the args, but *not* self:
int total_args = oparg;
_PyStackRef *arguments = args;
if (!PyStackRef_IsNull(self_or_null[0])) {
if (!PyStackRef_IsNull(self_or_null)) {
arguments--;
total_args++;
}
@ -4525,7 +4519,7 @@ dummy_func(
int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable_o))->co_flags;
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable_o));
_PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit(
tstate, callable[0], locals,
tstate, callable, locals,
arguments, positional_args, kwnames_o, frame
);
DEAD(args);
@ -4576,13 +4570,13 @@ dummy_func(
res = PyStackRef_FromPyObjectSteal(res_o);
}
op(_PY_FRAME_KW, (callable[1], self_or_null[1], args[oparg], kwnames -- new_frame: _PyInterpreterFrame*)) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]);
op(_PY_FRAME_KW, (callable, self_or_null, args[oparg], kwnames -- new_frame: _PyInterpreterFrame*)) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
// oparg counts all of the args, but *not* self:
int total_args = oparg;
_PyStackRef *arguments = args;
if (!PyStackRef_IsNull(self_or_null[0])) {
if (!PyStackRef_IsNull(self_or_null)) {
arguments--;
total_args++;
}
@ -4592,7 +4586,7 @@ dummy_func(
int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable_o))->co_flags;
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable_o));
_PyInterpreterFrame *temp = _PyEvalFramePushAndInit(
tstate, callable[0], locals,
tstate, callable, locals,
arguments, positional_args, kwnames_o, frame
);
PyStackRef_CLOSE(kwnames);
@ -4606,8 +4600,8 @@ dummy_func(
new_frame = temp;
}
op(_CHECK_FUNCTION_VERSION_KW, (func_version/2, callable[1], self_or_null[1], unused[oparg], kwnames -- callable[1], self_or_null[1], unused[oparg], kwnames)) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]);
op(_CHECK_FUNCTION_VERSION_KW, (func_version/2, callable, unused, unused[oparg], unused -- callable, unused, unused[oparg], unused)) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
EXIT_IF(!PyFunction_Check(callable_o));
PyFunctionObject *func = (PyFunctionObject *)callable_o;
EXIT_IF(func->func_version != func_version);
@ -4621,24 +4615,24 @@ dummy_func(
_SAVE_RETURN_OFFSET +
_PUSH_FRAME;
op(_CHECK_METHOD_VERSION_KW, (func_version/2, callable[1], null[1], unused[oparg], kwnames -- callable[1], null[1], unused[oparg], kwnames)) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]);
op(_CHECK_METHOD_VERSION_KW, (func_version/2, callable, null, unused[oparg], unused -- callable, null, unused[oparg], unused)) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
EXIT_IF(Py_TYPE(callable_o) != &PyMethod_Type);
PyObject *func = ((PyMethodObject *)callable_o)->im_func;
EXIT_IF(!PyFunction_Check(func));
EXIT_IF(((PyFunctionObject *)func)->func_version != func_version);
EXIT_IF(!PyStackRef_IsNull(null[0]));
EXIT_IF(!PyStackRef_IsNull(null));
}
op(_EXPAND_METHOD_KW, (callable[1], self_or_null[1], unused[oparg], unused -- callable[1], self_or_null[1], unused[oparg], unused)) {
assert(PyStackRef_IsNull(self_or_null[0]));
_PyStackRef callable_s = callable[0];
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable_s);
op(_EXPAND_METHOD_KW, (callable, self_or_null, unused[oparg], unused -- callable, self_or_null, unused[oparg], unused)) {
assert(PyStackRef_IsNull(self_or_null));
_PyStackRef callable_s = callable;
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
assert(Py_TYPE(callable_o) == &PyMethod_Type);
self_or_null[0] = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_self);
callable[0] = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_func);
assert(PyStackRef_FunctionCheck(callable[0]));
self_or_null = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_self);
callable = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_func);
assert(PyStackRef_FunctionCheck(callable));
PyStackRef_CLOSE(callable_s);
}
@ -4652,11 +4646,11 @@ dummy_func(
_SAVE_RETURN_OFFSET +
_PUSH_FRAME;
specializing op(_SPECIALIZE_CALL_KW, (counter/1, callable[1], self_or_null[1], args[oparg], kwnames -- callable[1], self_or_null[1], args[oparg], kwnames)) {
specializing op(_SPECIALIZE_CALL_KW, (counter/1, callable, self_or_null, unused[oparg], unused -- callable, self_or_null, unused[oparg], unused)) {
#if ENABLE_SPECIALIZATION_FT
if (ADAPTIVE_COUNTER_TRIGGERS(counter)) {
next_instr = this_instr;
_Py_Specialize_CallKw(callable[0], next_instr, oparg + !PyStackRef_IsNull(self_or_null[0]));
_Py_Specialize_CallKw(callable, next_instr, oparg + !PyStackRef_IsNull(self_or_null));
DISPATCH_SAME_OPARG();
}
OPCODE_DEFERRED_INC(CALL_KW);
@ -4677,22 +4671,22 @@ dummy_func(
_MONITOR_CALL_KW +
_DO_CALL_KW;
op(_CHECK_IS_NOT_PY_CALLABLE_KW, (callable[1], unused[1], unused[oparg], kwnames -- callable[1], unused[1], unused[oparg], kwnames)) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]);
op(_CHECK_IS_NOT_PY_CALLABLE_KW, (callable, unused, unused[oparg], unused -- callable, unused, unused[oparg], unused)) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
EXIT_IF(PyFunction_Check(callable_o));
EXIT_IF(Py_TYPE(callable_o) == &PyMethod_Type);
}
op(_CALL_KW_NON_PY, (callable[1], self_or_null[1], args[oparg], kwnames -- res)) {
op(_CALL_KW_NON_PY, (callable, self_or_null, args[oparg], kwnames -- res)) {
#if TIER_ONE
assert(opcode != INSTRUMENTED_CALL);
#endif
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]);
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
int total_args = oparg;
_PyStackRef *arguments = args;
if (!PyStackRef_IsNull(self_or_null[0])) {
if (!PyStackRef_IsNull(self_or_null)) {
arguments--;
total_args++;
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -534,10 +534,10 @@ dummy_func(void) {
top = bottom;
}
op(_SWAP, (bottom[1], unused[oparg-2], top[1] -- bottom[1], unused[oparg-2], top[1])) {
JitOptSymbol *temp = bottom[0];
bottom[0] = top[0];
top[0] = temp;
op(_SWAP, (bottom, unused[oparg-2], top -- bottom, unused[oparg-2], top)) {
JitOptSymbol *temp = bottom;
bottom = top;
top = temp;
assert(oparg >= 2);
}
@ -546,7 +546,7 @@ dummy_func(void) {
(void)offset;
}
op(_LOAD_ATTR_MODULE, (dict_version/2, owner, index/1 -- attr)) {
op(_LOAD_ATTR_MODULE, (dict_version/2, index/1, owner -- attr)) {
(void)dict_version;
(void)index;
attr = NULL;
@ -626,9 +626,9 @@ dummy_func(void) {
ctx->done = true;
}
op(_INIT_CALL_BOUND_METHOD_EXACT_ARGS, (callable[1], self_or_null[1], unused[oparg] -- callable[1], self_or_null[1], unused[oparg])) {
callable[0] = sym_new_not_null(ctx);
self_or_null[0] = sym_new_not_null(ctx);
op(_INIT_CALL_BOUND_METHOD_EXACT_ARGS, (callable, self_or_null, unused[oparg] -- callable, self_or_null, unused[oparg])) {
callable = sym_new_not_null(ctx);
self_or_null = sym_new_not_null(ctx);
}
op(_CHECK_FUNCTION_VERSION, (func_version/2, callable, self_or_null, unused[oparg] -- callable, self_or_null, unused[oparg])) {

View file

@ -1742,12 +1742,14 @@
}
case _INIT_CALL_BOUND_METHOD_EXACT_ARGS: {
JitOptSymbol **self_or_null;
JitOptSymbol **callable;
self_or_null = &stack_pointer[-1 - oparg];
callable = &stack_pointer[-2 - oparg];
callable[0] = sym_new_not_null(ctx);
self_or_null[0] = sym_new_not_null(ctx);
JitOptSymbol *self_or_null;
JitOptSymbol *callable;
self_or_null = stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg];
callable = sym_new_not_null(ctx);
self_or_null = sym_new_not_null(ctx);
stack_pointer[-2 - oparg] = callable;
stack_pointer[-1 - oparg] = self_or_null;
break;
}
@ -2003,9 +2005,6 @@
/* _MONITOR_CALL_KW is not a viable micro-op for tier 2 */
case _MAYBE_EXPAND_METHOD_KW: {
JitOptSymbol *kwnames_out;
kwnames_out = sym_new_not_null(ctx);
stack_pointer[-1] = kwnames_out;
break;
}
@ -2180,14 +2179,16 @@
}
case _SWAP: {
JitOptSymbol **top;
JitOptSymbol **bottom;
top = &stack_pointer[-1];
bottom = &stack_pointer[-2 - (oparg-2)];
JitOptSymbol *temp = bottom[0];
bottom[0] = top[0];
top[0] = temp;
JitOptSymbol *top;
JitOptSymbol *bottom;
top = stack_pointer[-1];
bottom = stack_pointer[-2 - (oparg-2)];
JitOptSymbol *temp = bottom;
bottom = top;
top = temp;
assert(oparg >= 2);
stack_pointer[-2 - (oparg-2)] = bottom;
stack_pointer[-1] = top;
break;
}

View file

@ -572,23 +572,21 @@ class Storage:
self.check_liveness, self.spilled
)
def sanity_check(self) -> None:
@staticmethod
def check_names(locals: list[Local]) -> None:
names: set[str] = set()
for var in self.inputs:
if var.name in names:
raise StackError(f"Duplicate name {var.name}")
names.add(var.name)
names = set()
for var in self.outputs:
if var.name in names:
raise StackError(f"Duplicate name {var.name}")
names.add(var.name)
names = set()
for var in self.stack.variables:
for var in locals:
if var.name == "unused":
continue
if var.name in names:
raise StackError(f"Duplicate name {var.name}")
names.add(var.name)
def sanity_check(self) -> None:
self.check_names(self.inputs)
self.check_names(self.outputs)
self.check_names(self.stack.variables)
def is_flushed(self) -> bool:
for var in self.outputs:
if var.in_local and not var.memory_offset: