aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Python/bytecodes.c
diff options
context:
space:
mode:
authorSam Gross <colesbury@gmail.com>2025-01-23 04:26:25 -0500
committerGitHub <noreply@github.com>2025-01-23 09:26:25 +0000
commita10f99375e7912df863cf101a38e9703cfcd72f1 (patch)
tree7909c7896fe256427c1149d2416fb7912ad3ba48 /Python/bytecodes.c
parentd7d066c3ab6842117f9e0fb1c9dde4bce00fa1e3 (diff)
downloadcpython-a10f99375e7912df863cf101a38e9703cfcd72f1.tar.gz
cpython-a10f99375e7912df863cf101a38e9703cfcd72f1.zip
Revert "GH-128914: Remove conditional stack effects from `bytecodes.c` and the code generators (GH-128918)" (GH-129202)
The commit introduced a ~2.5-3% regression in the free threading build. This reverts commit ab61d3f4303d14a413bc9ae6557c730ffdf7579e.
Diffstat (limited to 'Python/bytecodes.c')
-rw-r--r--Python/bytecodes.c217
1 files changed, 94 insertions, 123 deletions
diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index c78d496adcd..b70ed7f4d10 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -348,8 +348,8 @@ dummy_func(
DECREF_INPUTS();
}
- pure inst(PUSH_NULL, (-- null)) {
- null = PyStackRef_NULL;
+ pure inst(PUSH_NULL, (-- res)) {
+ res = PyStackRef_NULL;
}
no_save_ip inst(END_FOR, (value -- )) {
@@ -1654,7 +1654,7 @@ dummy_func(
specializing op(_SPECIALIZE_LOAD_GLOBAL, (counter/1 -- )) {
#if ENABLE_SPECIALIZATION_FT
if (ADAPTIVE_COUNTER_TRIGGERS(counter)) {
- PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
next_instr = this_instr;
_Py_Specialize_LoadGlobal(GLOBALS(), BUILTINS(), next_instr, name);
DISPATCH_SAME_OPARG();
@@ -1665,10 +1665,11 @@ dummy_func(
}
// res[1] because we need a pointer to res to pass it to _PyEval_LoadGlobalStackRef
- op(_LOAD_GLOBAL, ( -- res[1])) {
- PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
+ op(_LOAD_GLOBAL, ( -- res[1], null if (oparg & 1))) {
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
_PyEval_LoadGlobalStackRef(GLOBALS(), BUILTINS(), name, res);
ERROR_IF(PyStackRef_IsNull(*res), error);
+ null = PyStackRef_NULL;
}
macro(LOAD_GLOBAL) =
@@ -1706,7 +1707,7 @@ dummy_func(
assert(DK_IS_UNICODE(builtins_keys));
}
- op(_LOAD_GLOBAL_MODULE_FROM_KEYS, (index/1, globals_keys: PyDictKeysObject* -- res)) {
+ op(_LOAD_GLOBAL_MODULE_FROM_KEYS, (index/1, globals_keys: PyDictKeysObject* -- res, null if (oparg & 1))) {
PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(globals_keys);
PyObject *res_o = FT_ATOMIC_LOAD_PTR_RELAXED(entries[index].me_value);
DEAD(globals_keys);
@@ -1720,9 +1721,10 @@ dummy_func(
res = PyStackRef_FromPyObjectSteal(res_o);
#endif
STAT_INC(LOAD_GLOBAL, hit);
+ null = PyStackRef_NULL;
}
- op(_LOAD_GLOBAL_BUILTINS_FROM_KEYS, (index/1, builtins_keys: PyDictKeysObject* -- res)) {
+ op(_LOAD_GLOBAL_BUILTINS_FROM_KEYS, (index/1, builtins_keys: PyDictKeysObject* -- res, null if (oparg & 1))) {
PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(builtins_keys);
PyObject *res_o = FT_ATOMIC_LOAD_PTR_RELAXED(entries[index].me_value);
DEAD(builtins_keys);
@@ -1736,6 +1738,7 @@ dummy_func(
res = PyStackRef_FromPyObjectSteal(res_o);
#endif
STAT_INC(LOAD_GLOBAL, hit);
+ null = PyStackRef_NULL;
}
macro(LOAD_GLOBAL_MODULE) =
@@ -2009,27 +2012,17 @@ dummy_func(
GO_TO_INSTRUCTION(LOAD_SUPER_ATTR);
}
- inst(INSTRUMENTED_LOAD_SUPER_METHOD, (unused/1 -- )) {
- // cancel out the decrement that will happen in LOAD_SUPER_ATTR; we
- // don't want to specialize instrumented instructions
- PAUSE_ADAPTIVE_COUNTER(this_instr[1].counter);
- GO_TO_INSTRUCTION(LOAD_SUPER_METHOD);
- }
-
family(LOAD_SUPER_ATTR, INLINE_CACHE_ENTRIES_LOAD_SUPER_ATTR) = {
LOAD_SUPER_ATTR_ATTR,
- };
-
-
- family(LOAD_SUPER_METHOD, INLINE_CACHE_ENTRIES_LOAD_SUPER_ATTR) = {
- LOAD_SUPER_METHOD_METHOD,
+ LOAD_SUPER_ATTR_METHOD,
};
specializing op(_SPECIALIZE_LOAD_SUPER_ATTR, (counter/1, global_super_st, class_st, unused -- global_super_st, class_st, unused)) {
#if ENABLE_SPECIALIZATION_FT
+ int load_method = oparg & 1;
if (ADAPTIVE_COUNTER_TRIGGERS(counter)) {
next_instr = this_instr;
- _Py_Specialize_LoadSuperAttr(global_super_st, class_st, next_instr, 0);
+ _Py_Specialize_LoadSuperAttr(global_super_st, class_st, next_instr, load_method);
DISPATCH_SAME_OPARG();
}
OPCODE_DEFERRED_INC(LOAD_SUPER_ATTR);
@@ -2037,24 +2030,12 @@ dummy_func(
#endif /* ENABLE_SPECIALIZATION_FT */
}
- specializing op(_SPECIALIZE_LOAD_SUPER_METHOD, (counter/1, global_super_st, class_st, unused -- global_super_st, class_st, unused)) {
- #if ENABLE_SPECIALIZATION_FT
- if (ADAPTIVE_COUNTER_TRIGGERS(counter)) {
- next_instr = this_instr;
- _Py_Specialize_LoadSuperAttr(global_super_st, class_st, next_instr, 1);
- DISPATCH_SAME_OPARG();
- }
- OPCODE_DEFERRED_INC(LOAD_SUPER_METHOD);
- ADVANCE_ADAPTIVE_COUNTER(this_instr[1].counter);
- #endif /* ENABLE_SPECIALIZATION_FT */
- }
-
- tier1 op(_LOAD_SUPER_ATTR, (global_super_st, class_st, self_st -- attr)) {
+ tier1 op(_LOAD_SUPER_ATTR, (global_super_st, class_st, self_st -- attr, null if (oparg & 1))) {
PyObject *global_super = PyStackRef_AsPyObjectBorrow(global_super_st);
PyObject *class = PyStackRef_AsPyObjectBorrow(class_st);
PyObject *self = PyStackRef_AsPyObjectBorrow(self_st);
- if (opcode >= MIN_INSTRUMENTED_OPCODE) {
+ if (opcode == INSTRUMENTED_LOAD_SUPER_ATTR) {
PyObject *arg = oparg & 2 ? class : &_PyInstrumentation_MISSING;
int err = _Py_call_instrumentation_2args(
tstate, PY_MONITORING_EVENT_CALL,
@@ -2068,7 +2049,7 @@ dummy_func(
// handle any case whose performance we care about
PyObject *stack[] = {class, self};
PyObject *super = PyObject_Vectorcall(global_super, stack, oparg & 2, NULL);
- if (opcode >= MIN_INSTRUMENTED_OPCODE) {
+ if (opcode == INSTRUMENTED_LOAD_SUPER_ATTR) {
PyObject *arg = oparg & 2 ? class : &_PyInstrumentation_MISSING;
if (super == NULL) {
_Py_call_instrumentation_exc2(
@@ -2091,13 +2072,12 @@ dummy_func(
Py_DECREF(super);
ERROR_IF(attr_o == NULL, error);
attr = PyStackRef_FromPyObjectSteal(attr_o);
+ null = PyStackRef_NULL;
}
macro(LOAD_SUPER_ATTR) = _SPECIALIZE_LOAD_SUPER_ATTR + _LOAD_SUPER_ATTR;
- macro(LOAD_SUPER_METHOD) = _SPECIALIZE_LOAD_SUPER_METHOD + _LOAD_SUPER_ATTR + PUSH_NULL;
-
- inst(LOAD_SUPER_ATTR_ATTR, (unused/1, global_super_st, class_st, self_st -- attr_st)) {
+ inst(LOAD_SUPER_ATTR_ATTR, (unused/1, global_super_st, class_st, self_st -- attr_st, unused if (0))) {
PyObject *global_super = PyStackRef_AsPyObjectBorrow(global_super_st);
PyObject *class = PyStackRef_AsPyObjectBorrow(class_st);
PyObject *self = PyStackRef_AsPyObjectBorrow(self_st);
@@ -2113,7 +2093,7 @@ dummy_func(
attr_st = PyStackRef_FromPyObjectSteal(attr);
}
- inst(LOAD_SUPER_METHOD_METHOD, (unused/1, global_super_st, class_st, self_st -- attr, self_or_null)) {
+ inst(LOAD_SUPER_ATTR_METHOD, (unused/1, global_super_st, class_st, self_st -- attr, self_or_null)) {
PyObject *global_super = PyStackRef_AsPyObjectBorrow(global_super_st);
PyObject *class = PyStackRef_AsPyObjectBorrow(class_st);
PyObject *self = PyStackRef_AsPyObjectBorrow(self_st);
@@ -2152,20 +2132,17 @@ dummy_func(
LOAD_ATTR_CLASS_WITH_METACLASS_CHECK,
LOAD_ATTR_PROPERTY,
LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN,
+ LOAD_ATTR_METHOD_WITH_VALUES,
+ LOAD_ATTR_METHOD_NO_DICT,
+ LOAD_ATTR_METHOD_LAZY_DICT,
LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES,
LOAD_ATTR_NONDESCRIPTOR_NO_DICT,
};
- family(LOAD_METHOD, INLINE_CACHE_ENTRIES_LOAD_ATTR) = {
- LOAD_METHOD_WITH_VALUES,
- LOAD_METHOD_NO_DICT,
- LOAD_METHOD_LAZY_DICT,
- };
-
specializing op(_SPECIALIZE_LOAD_ATTR, (counter/1, owner -- owner)) {
#if ENABLE_SPECIALIZATION_FT
if (ADAPTIVE_COUNTER_TRIGGERS(counter)) {
- PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
next_instr = this_instr;
_Py_Specialize_LoadAttr(owner, next_instr, name);
DISPATCH_SAME_OPARG();
@@ -2175,67 +2152,50 @@ dummy_func(
#endif /* ENABLE_SPECIALIZATION_FT */
}
- specializing op(_SPECIALIZE_LOAD_METHOD, (counter/1, owner -- owner)) {
- #if ENABLE_SPECIALIZATION_FT
- if (ADAPTIVE_COUNTER_TRIGGERS(counter)) {
- PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
- next_instr = this_instr;
- _Py_Specialize_LoadMethod(owner, next_instr, name);
- DISPATCH_SAME_OPARG();
- }
- OPCODE_DEFERRED_INC(LOAD_METHOD);
- ADVANCE_ADAPTIVE_COUNTER(this_instr[1].counter);
- #endif /* ENABLE_SPECIALIZATION_FT */
- }
-
- op(_LOAD_METHOD, (owner -- attr, self_or_null)) {
- PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
+ op(_LOAD_ATTR, (owner -- attr, self_or_null if (oparg & 1))) {
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1);
PyObject *attr_o;
- /* Designed to work in tandem with CALL, pushes two values. */
- attr_o = NULL;
- int is_meth = _PyObject_GetMethod(PyStackRef_AsPyObjectBorrow(owner), name, &attr_o);
- if (is_meth) {
- /* We can bypass temporary bound method object.
- meth is unbound method and obj is self.
- meth | self | arg1 | ... | argN
+ if (oparg & 1) {
+ /* Designed to work in tandem with CALL, pushes two values. */
+ attr_o = NULL;
+ int is_meth = _PyObject_GetMethod(PyStackRef_AsPyObjectBorrow(owner), name, &attr_o);
+ if (is_meth) {
+ /* We can bypass temporary bound method object.
+ meth is unbound method and obj is self.
+ meth | self | arg1 | ... | argN
+ */
+ assert(attr_o != NULL); // No errors on this branch
+ self_or_null = owner; // Transfer ownership
+ DEAD(owner);
+ }
+ else {
+ /* meth is not an unbound method (but a regular attr, or
+ something was returned by a descriptor protocol). Set
+ the second element of the stack to NULL, to signal
+ CALL that it's not a method call.
+ meth | NULL | arg1 | ... | argN
*/
- assert(attr_o != NULL); // No errors on this branch
- self_or_null = owner; // Transfer ownership
- DEAD(owner);
+ DECREF_INPUTS();
+ ERROR_IF(attr_o == NULL, error);
+ self_or_null = PyStackRef_NULL;
+ }
}
else {
- /* meth is not an unbound method (but a regular attr, or
- something was returned by a descriptor protocol). Set
- the second element of the stack to NULL, to signal
- CALL that it's not a method call.
- meth | NULL | arg1 | ... | argN
- */
+ /* Classic, pushes one value. */
+ attr_o = PyObject_GetAttr(PyStackRef_AsPyObjectBorrow(owner), name);
DECREF_INPUTS();
ERROR_IF(attr_o == NULL, error);
+ /* We need to define self_or_null on all paths */
self_or_null = PyStackRef_NULL;
}
attr = PyStackRef_FromPyObjectSteal(attr_o);
}
- op(_LOAD_ATTR, (owner -- attr)) {
- PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
- PyObject *attr_o = PyObject_GetAttr(PyStackRef_AsPyObjectBorrow(owner), name);
- DECREF_INPUTS();
- ERROR_IF(attr_o == NULL, error);
- attr = PyStackRef_FromPyObjectSteal(attr_o);
- }
-
macro(LOAD_ATTR) =
_SPECIALIZE_LOAD_ATTR +
unused/8 +
_LOAD_ATTR;
-
- macro(LOAD_METHOD) =
- _SPECIALIZE_LOAD_METHOD +
- unused/8 +
- _LOAD_METHOD;
-
op(_GUARD_TYPE_VERSION, (type_version/2, owner -- owner)) {
PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner));
assert(type_version != 0);
@@ -2260,7 +2220,7 @@ dummy_func(
DEOPT_IF(!FT_ATOMIC_LOAD_UINT8(_PyObject_InlineValues(owner_o)->valid));
}
- op(_LOAD_ATTR_INSTANCE_VALUE, (offset/1, owner -- attr)) {
+ split op(_LOAD_ATTR_INSTANCE_VALUE, (offset/1, owner -- attr, null if (oparg & 1))) {
PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
PyObject **value_ptr = (PyObject**)(((char *)owner_o) + offset);
PyObject *attr_o = FT_ATOMIC_LOAD_PTR_ACQUIRE(*value_ptr);
@@ -2273,6 +2233,7 @@ dummy_func(
attr = PyStackRef_FromPyObjectNew(attr_o);
#endif
STAT_INC(LOAD_ATTR, hit);
+ null = PyStackRef_NULL;
DECREF_INPUTS();
}
@@ -2293,7 +2254,7 @@ dummy_func(
mod_keys = keys;
}
- op(_LOAD_ATTR_MODULE_FROM_KEYS, (index/1, owner, mod_keys: PyDictKeysObject * -- attr)) {
+ op(_LOAD_ATTR_MODULE_FROM_KEYS, (index/1, owner, mod_keys: PyDictKeysObject * -- attr, null if (oparg & 1))) {
assert(mod_keys->dk_kind == DICT_KEYS_UNICODE);
assert(index < FT_ATOMIC_LOAD_SSIZE_RELAXED(mod_keys->dk_nentries));
PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(mod_keys) + index;
@@ -2311,6 +2272,7 @@ dummy_func(
attr = PyStackRef_FromPyObjectSteal(attr_o);
#endif
STAT_INC(LOAD_ATTR, hit);
+ null = PyStackRef_NULL;
PyStackRef_CLOSE(owner);
}
@@ -2330,7 +2292,7 @@ dummy_func(
dict = dict_o;
}
- op(_LOAD_ATTR_WITH_HINT, (hint/1, owner, dict: PyDictObject * -- attr)) {
+ op(_LOAD_ATTR_WITH_HINT, (hint/1, owner, dict: PyDictObject * -- attr, null if (oparg & 1))) {
PyObject *attr_o;
if (!LOCK_OBJECT(dict)) {
POP_INPUT(dict);
@@ -2342,7 +2304,7 @@ dummy_func(
POP_INPUT(dict);
DEOPT_IF(true);
}
- PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
if (dict->ma_keys->dk_kind != DICT_KEYS_UNICODE) {
UNLOCK_OBJECT(dict);
POP_INPUT(dict);
@@ -2364,6 +2326,7 @@ dummy_func(
attr = PyStackRef_FromPyObjectNew(attr_o);
UNLOCK_OBJECT(dict);
DEAD(dict);
+ null = PyStackRef_NULL;
DECREF_INPUTS();
}
@@ -2374,7 +2337,7 @@ dummy_func(
_LOAD_ATTR_WITH_HINT +
unused/5;
- op(_LOAD_ATTR_SLOT, (index/1, owner -- attr)) {
+ split op(_LOAD_ATTR_SLOT, (index/1, owner -- attr, null if (oparg & 1))) {
PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
PyObject **addr = (PyObject **)((char *)owner_o + index);
@@ -2387,6 +2350,7 @@ dummy_func(
attr = PyStackRef_FromPyObjectNew(attr_o);
#endif
STAT_INC(LOAD_ATTR, hit);
+ null = PyStackRef_NULL;
DECREF_INPUTS();
}
@@ -2404,10 +2368,11 @@ dummy_func(
EXIT_IF(FT_ATOMIC_LOAD_UINT_RELAXED(((PyTypeObject *)owner_o)->tp_version_tag) != type_version);
}
- op(_LOAD_ATTR_CLASS, (descr/4, owner -- attr)) {
+ split op(_LOAD_ATTR_CLASS, (descr/4, owner -- attr, null if (oparg & 1))) {
STAT_INC(LOAD_ATTR, hit);
assert(descr != NULL);
attr = PyStackRef_FromPyObjectNew(descr);
+ null = PyStackRef_NULL;
DECREF_INPUTS();
}
@@ -2424,6 +2389,7 @@ dummy_func(
_LOAD_ATTR_CLASS;
op(_LOAD_ATTR_PROPERTY_FRAME, (fget/4, owner -- new_frame: _PyInterpreterFrame *)) {
+ assert((oparg & 1) == 0);
assert(Py_IS_TYPE(fget, &PyFunction_Type));
PyFunctionObject *f = (PyFunctionObject *)fget;
PyCodeObject *code = (PyCodeObject *)f->func_code;
@@ -2446,8 +2412,10 @@ dummy_func(
_SAVE_RETURN_OFFSET +
_PUSH_FRAME;
- inst(LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN, (unused/1, type_version/2, func_version/2, getattribute/4, owner -- unused)) {
+ inst(LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN, (unused/1, type_version/2, func_version/2, getattribute/4, owner -- unused, unused if (0))) {
PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
+
+ assert((oparg & 1) == 0);
DEOPT_IF(tstate->interp->eval_frame);
PyTypeObject *cls = Py_TYPE(owner_o);
assert(type_version != 0);
@@ -2461,7 +2429,7 @@ dummy_func(
DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize));
STAT_INC(LOAD_ATTR, hit);
- PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1);
_PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(
tstate, PyStackRef_FromPyObjectNew(f), 2, frame);
// Manipulate stack directly because we exit with DISPATCH_INLINED().
@@ -3380,7 +3348,8 @@ dummy_func(
DEOPT_IF(FT_ATOMIC_LOAD_UINT32_RELAXED(keys->dk_version) != keys_version);
}
- op(_LOAD_METHOD_WITH_VALUES, (descr/4, owner -- attr, self)) {
+ split op(_LOAD_ATTR_METHOD_WITH_VALUES, (descr/4, owner -- attr, self if (1))) {
+ assert(oparg & 1);
/* Cached method object */
STAT_INC(LOAD_ATTR, hit);
assert(descr != NULL);
@@ -3390,14 +3359,15 @@ dummy_func(
DEAD(owner);
}
- macro(LOAD_METHOD_WITH_VALUES) =
+ macro(LOAD_ATTR_METHOD_WITH_VALUES) =
unused/1 +
_GUARD_TYPE_VERSION +
_GUARD_DORV_VALUES_INST_ATTR_FROM_DICT +
_GUARD_KEYS_VERSION +
- _LOAD_METHOD_WITH_VALUES;
+ _LOAD_ATTR_METHOD_WITH_VALUES;
- op(_LOAD_METHOD_NO_DICT, (descr/4, owner -- attr, self)) {
+ op(_LOAD_ATTR_METHOD_NO_DICT, (descr/4, owner -- attr, self if (1))) {
+ assert(oparg & 1);
assert(Py_TYPE(PyStackRef_AsPyObjectBorrow(owner))->tp_dictoffset == 0);
STAT_INC(LOAD_ATTR, hit);
assert(descr != NULL);
@@ -3407,13 +3377,14 @@ dummy_func(
DEAD(owner);
}
- macro(LOAD_METHOD_NO_DICT) =
+ macro(LOAD_ATTR_METHOD_NO_DICT) =
unused/1 +
_GUARD_TYPE_VERSION +
unused/2 +
- _LOAD_METHOD_NO_DICT;
+ _LOAD_ATTR_METHOD_NO_DICT;
- op(_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES, (descr/4, owner -- attr)) {
+ op(_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES, (descr/4, owner -- attr, unused if (0))) {
+ assert((oparg & 1) == 0);
STAT_INC(LOAD_ATTR, hit);
assert(descr != NULL);
DECREF_INPUTS();
@@ -3427,7 +3398,8 @@ dummy_func(
_GUARD_KEYS_VERSION +
_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES;
- op(_LOAD_ATTR_NONDESCRIPTOR_NO_DICT, (descr/4, owner -- attr)) {
+ op(_LOAD_ATTR_NONDESCRIPTOR_NO_DICT, (descr/4, owner -- attr, unused if (0))) {
+ assert((oparg & 1) == 0);
assert(Py_TYPE(PyStackRef_AsPyObjectBorrow(owner))->tp_dictoffset == 0);
STAT_INC(LOAD_ATTR, hit);
assert(descr != NULL);
@@ -3448,7 +3420,8 @@ dummy_func(
DEOPT_IF(dict != NULL);
}
- op(_LOAD_METHOD_LAZY_DICT, (descr/4, owner -- attr, self)) {
+ op(_LOAD_ATTR_METHOD_LAZY_DICT, (descr/4, owner -- attr, self if (1))) {
+ assert(oparg & 1);
STAT_INC(LOAD_ATTR, hit);
assert(descr != NULL);
assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR));
@@ -3457,12 +3430,12 @@ dummy_func(
DEAD(owner);
}
- macro(LOAD_METHOD_LAZY_DICT) =
+ macro(LOAD_ATTR_METHOD_LAZY_DICT) =
unused/1 +
_GUARD_TYPE_VERSION +
_CHECK_ATTR_METHOD_LAZY_DICT +
unused/1 +
- _LOAD_METHOD_LAZY_DICT;
+ _LOAD_ATTR_METHOD_LAZY_DICT;
// Cache layout: counter/1, func_version/2
// CALL_INTRINSIC_1/2, CALL_KW, and CALL_FUNCTION_EX aren't members!
@@ -4564,7 +4537,7 @@ dummy_func(
GO_TO_INSTRUCTION(CALL_FUNCTION_EX);
}
- op(_MAKE_CALLARGS_A_TUPLE, (func, unused, callargs, kwargs_in -- func, unused, tuple, kwargs_out)) {
+ op(_MAKE_CALLARGS_A_TUPLE, (func, unused, callargs, kwargs_in if (oparg & 1) -- func, unused, tuple, kwargs_out if (oparg & 1))) {
PyObject *callargs_o = PyStackRef_AsPyObjectBorrow(callargs);
if (PyTuple_CheckExact(callargs_o)) {
tuple = callargs;
@@ -4588,7 +4561,7 @@ dummy_func(
}
}
- op(_DO_CALL_FUNCTION_EX, (func_st, unused, callargs_st, kwargs_st -- result)) {
+ op(_DO_CALL_FUNCTION_EX, (func_st, unused, callargs_st, kwargs_st if (oparg & 1) -- result)) {
PyObject *func = PyStackRef_AsPyObjectBorrow(func_st);
// DICT_MERGE is called before this opcode if there are kwargs.
@@ -4722,16 +4695,11 @@ dummy_func(
LLTRACE_RESUME_FRAME();
}
- inst(BUILD_SLICE, (args[oparg] -- slice)) {
- assert(oparg == 2 || oparg == 3);
- _PyStackRef start = args[0];
- _PyStackRef stop = args[1];
+ inst(BUILD_SLICE, (start, stop, step if (oparg == 3) -- slice)) {
PyObject *start_o = PyStackRef_AsPyObjectBorrow(start);
PyObject *stop_o = PyStackRef_AsPyObjectBorrow(stop);
- PyObject * step_o = NULL;
- if (oparg == 3) {
- step_o = PyStackRef_AsPyObjectBorrow(args[2]);
- }
+ PyObject *step_o = PyStackRef_AsPyObjectBorrow(step);
+
PyObject *slice_o = PySlice_New(start_o, stop_o, step_o);
DECREF_INPUTS();
ERROR_IF(slice_o == NULL, error);
@@ -5074,25 +5042,27 @@ dummy_func(
DEOPT_IF(func->func_version != func_version);
}
- tier2 op(_LOAD_GLOBAL_MODULE, (index/1 -- res)) {
+ tier2 op(_LOAD_GLOBAL_MODULE, (index/1 -- res, null if (oparg & 1))) {
PyDictObject *dict = (PyDictObject *)GLOBALS();
PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(dict->ma_keys);
PyObject *res_o = entries[index].me_value;
DEOPT_IF(res_o == NULL);
Py_INCREF(res_o);
res = PyStackRef_FromPyObjectSteal(res_o);
+ null = PyStackRef_NULL;
}
- tier2 op(_LOAD_GLOBAL_BUILTINS, (index/1 -- res)) {
+ tier2 op(_LOAD_GLOBAL_BUILTINS, (index/1 -- res, null if (oparg & 1))) {
PyDictObject *dict = (PyDictObject *)BUILTINS();
PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(dict->ma_keys);
PyObject *res_o = entries[index].me_value;
DEOPT_IF(res_o == NULL);
Py_INCREF(res_o);
res = PyStackRef_FromPyObjectSteal(res_o);
+ null = PyStackRef_NULL;
}
- tier2 op(_LOAD_ATTR_MODULE, (index/1, owner -- attr)) {
+ tier2 op(_LOAD_ATTR_MODULE, (index/1, owner -- attr, null if (oparg & 1))) {
PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
PyDictObject *dict = (PyDictObject *)((PyModuleObject *)owner_o)->md_dict;
assert(dict->ma_keys->dk_kind == DICT_KEYS_UNICODE);
@@ -5103,6 +5073,7 @@ dummy_func(
STAT_INC(LOAD_ATTR, hit);
Py_INCREF(attr_o);
attr = PyStackRef_FromPyObjectSteal(attr_o);
+ null = PyStackRef_NULL;
DECREF_INPUTS();
}