aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Python/executor_cases.c.h
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/executor_cases.c.h
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/executor_cases.c.h')
-rw-r--r--Python/executor_cases.c.h306
1 files changed, 223 insertions, 83 deletions
diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h
index d2da9a8acf9..d336f73c4a2 100644
--- a/Python/executor_cases.c.h
+++ b/Python/executor_cases.c.h
@@ -406,9 +406,9 @@
}
case _PUSH_NULL: {
- _PyStackRef null;
- null = PyStackRef_NULL;
- stack_pointer[0] = null;
+ _PyStackRef res;
+ res = PyStackRef_NULL;
+ stack_pointer[0] = res;
stack_pointer += 1;
assert(WITHIN_STACK_BOUNDS());
break;
@@ -1953,14 +1953,17 @@
case _LOAD_GLOBAL: {
_PyStackRef *res;
+ _PyStackRef null = PyStackRef_NULL;
oparg = CURRENT_OPARG();
res = &stack_pointer[0];
- PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
_PyFrame_SetStackPointer(frame, stack_pointer);
_PyEval_LoadGlobalStackRef(GLOBALS(), BUILTINS(), name, res);
stack_pointer = _PyFrame_GetStackPointer(frame);
if (PyStackRef_IsNull(*res)) JUMP_TO_ERROR();
- stack_pointer += 1;
+ null = PyStackRef_NULL;
+ if (oparg & 1) stack_pointer[1] = null;
+ stack_pointer += 1 + (oparg & 1);
assert(WITHIN_STACK_BOUNDS());
break;
}
@@ -2026,6 +2029,8 @@
case _LOAD_GLOBAL_MODULE_FROM_KEYS: {
PyDictKeysObject *globals_keys;
_PyStackRef res;
+ _PyStackRef null = PyStackRef_NULL;
+ oparg = CURRENT_OPARG();
globals_keys = (PyDictKeysObject *)stack_pointer[-1].bits;
uint16_t index = (uint16_t)CURRENT_OPERAND0();
PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(globals_keys);
@@ -2047,8 +2052,10 @@
res = PyStackRef_FromPyObjectSteal(res_o);
#endif
STAT_INC(LOAD_GLOBAL, hit);
+ null = PyStackRef_NULL;
stack_pointer[0] = res;
- stack_pointer += 1;
+ if (oparg & 1) stack_pointer[1] = null;
+ stack_pointer += 1 + (oparg & 1);
assert(WITHIN_STACK_BOUNDS());
break;
}
@@ -2056,6 +2063,8 @@
case _LOAD_GLOBAL_BUILTINS_FROM_KEYS: {
PyDictKeysObject *builtins_keys;
_PyStackRef res;
+ _PyStackRef null = PyStackRef_NULL;
+ oparg = CURRENT_OPARG();
builtins_keys = (PyDictKeysObject *)stack_pointer[-1].bits;
uint16_t index = (uint16_t)CURRENT_OPERAND0();
PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(builtins_keys);
@@ -2077,8 +2086,10 @@
res = PyStackRef_FromPyObjectSteal(res_o);
#endif
STAT_INC(LOAD_GLOBAL, hit);
+ null = PyStackRef_NULL;
stack_pointer[0] = res;
- stack_pointer += 1;
+ if (oparg & 1) stack_pointer[1] = null;
+ stack_pointer += 1 + (oparg & 1);
assert(WITHIN_STACK_BOUNDS());
break;
}
@@ -2508,8 +2519,6 @@
/* _INSTRUMENTED_LOAD_SUPER_ATTR is not a viable micro-op for tier 2 because it is instrumented */
- /* _INSTRUMENTED_LOAD_SUPER_METHOD is not a viable micro-op for tier 2 because it is instrumented */
-
case _LOAD_SUPER_ATTR_ATTR: {
_PyStackRef self_st;
_PyStackRef class_st;
@@ -2547,7 +2556,7 @@
break;
}
- case _LOAD_SUPER_METHOD_METHOD: {
+ case _LOAD_SUPER_ATTR_METHOD: {
_PyStackRef self_st;
_PyStackRef class_st;
_PyStackRef global_super_st;
@@ -2596,62 +2605,58 @@
break;
}
- case _LOAD_METHOD: {
+ case _LOAD_ATTR: {
_PyStackRef owner;
_PyStackRef attr;
- _PyStackRef self_or_null;
+ _PyStackRef self_or_null = PyStackRef_NULL;
oparg = CURRENT_OPARG();
owner = stack_pointer[-1];
- PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1);
PyObject *attr_o;
- /* Designed to work in tandem with CALL, pushes two values. */
- attr_o = NULL;
- _PyFrame_SetStackPointer(frame, stack_pointer);
- int is_meth = _PyObject_GetMethod(PyStackRef_AsPyObjectBorrow(owner), name, &attr_o);
- stack_pointer = _PyFrame_GetStackPointer(frame);
- 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
+ if (oparg & 1) {
+ /* Designed to work in tandem with CALL, pushes two values. */
+ attr_o = NULL;
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ int is_meth = _PyObject_GetMethod(PyStackRef_AsPyObjectBorrow(owner), name, &attr_o);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
+ 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
+ }
+ 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
+ */
+ PyStackRef_CLOSE(owner);
+ if (attr_o == NULL) JUMP_TO_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. */
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ attr_o = PyObject_GetAttr(PyStackRef_AsPyObjectBorrow(owner), name);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
PyStackRef_CLOSE(owner);
if (attr_o == NULL) JUMP_TO_ERROR();
+ /* We need to define self_or_null on all paths */
self_or_null = PyStackRef_NULL;
}
attr = PyStackRef_FromPyObjectSteal(attr_o);
stack_pointer[-1] = attr;
- stack_pointer[0] = self_or_null;
- stack_pointer += 1;
+ if (oparg & 1) stack_pointer[0] = self_or_null;
+ stack_pointer += (oparg & 1);
assert(WITHIN_STACK_BOUNDS());
break;
}
- case _LOAD_ATTR: {
- _PyStackRef owner;
- _PyStackRef attr;
- oparg = CURRENT_OPARG();
- owner = stack_pointer[-1];
- PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
- _PyFrame_SetStackPointer(frame, stack_pointer);
- PyObject *attr_o = PyObject_GetAttr(PyStackRef_AsPyObjectBorrow(owner), name);
- stack_pointer = _PyFrame_GetStackPointer(frame);
- PyStackRef_CLOSE(owner);
- if (attr_o == NULL) JUMP_TO_ERROR();
- attr = PyStackRef_FromPyObjectSteal(attr_o);
- stack_pointer[-1] = attr;
- break;
- }
-
case _GUARD_TYPE_VERSION: {
_PyStackRef owner;
owner = stack_pointer[-1];
@@ -2699,9 +2704,42 @@
break;
}
- case _LOAD_ATTR_INSTANCE_VALUE: {
+ case _LOAD_ATTR_INSTANCE_VALUE_0: {
+ _PyStackRef owner;
+ _PyStackRef attr;
+ _PyStackRef null = PyStackRef_NULL;
+ (void)null;
+ owner = stack_pointer[-1];
+ uint16_t offset = (uint16_t)CURRENT_OPERAND0();
+ PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
+ PyObject **value_ptr = (PyObject**)(((char *)owner_o) + offset);
+ PyObject *attr_o = FT_ATOMIC_LOAD_PTR_ACQUIRE(*value_ptr);
+ if (attr_o == NULL) {
+ UOP_STAT_INC(uopcode, miss);
+ JUMP_TO_JUMP_TARGET();
+ }
+ #ifdef Py_GIL_DISABLED
+ if (!_Py_TryIncrefCompareStackRef(value_ptr, attr_o, &attr)) {
+ if (true) {
+ UOP_STAT_INC(uopcode, miss);
+ JUMP_TO_JUMP_TARGET();
+ }
+ }
+ #else
+ attr = PyStackRef_FromPyObjectNew(attr_o);
+ #endif
+ STAT_INC(LOAD_ATTR, hit);
+ null = PyStackRef_NULL;
+ PyStackRef_CLOSE(owner);
+ stack_pointer[-1] = attr;
+ break;
+ }
+
+ case _LOAD_ATTR_INSTANCE_VALUE_1: {
_PyStackRef owner;
_PyStackRef attr;
+ _PyStackRef null = PyStackRef_NULL;
+ (void)null;
owner = stack_pointer[-1];
uint16_t offset = (uint16_t)CURRENT_OPERAND0();
PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
@@ -2722,11 +2760,17 @@
attr = PyStackRef_FromPyObjectNew(attr_o);
#endif
STAT_INC(LOAD_ATTR, hit);
+ null = PyStackRef_NULL;
PyStackRef_CLOSE(owner);
stack_pointer[-1] = attr;
+ stack_pointer[0] = null;
+ stack_pointer += 1;
+ assert(WITHIN_STACK_BOUNDS());
break;
}
+ /* _LOAD_ATTR_INSTANCE_VALUE is split on (oparg & 1) */
+
case _CHECK_ATTR_MODULE_PUSH_KEYS: {
_PyStackRef owner;
PyDictKeysObject *mod_keys;
@@ -2755,6 +2799,8 @@
PyDictKeysObject *mod_keys;
_PyStackRef owner;
_PyStackRef attr;
+ _PyStackRef null = PyStackRef_NULL;
+ oparg = CURRENT_OPARG();
mod_keys = (PyDictKeysObject *)stack_pointer[-1].bits;
owner = stack_pointer[-2];
uint16_t index = (uint16_t)CURRENT_OPERAND0();
@@ -2782,8 +2828,12 @@
attr = PyStackRef_FromPyObjectSteal(attr_o);
#endif
STAT_INC(LOAD_ATTR, hit);
+ null = PyStackRef_NULL;
PyStackRef_CLOSE(owner);
stack_pointer[-1] = attr;
+ if (oparg & 1) stack_pointer[0] = null;
+ stack_pointer += (oparg & 1);
+ assert(WITHIN_STACK_BOUNDS());
break;
}
@@ -2810,6 +2860,7 @@
PyDictObject *dict;
_PyStackRef owner;
_PyStackRef attr;
+ _PyStackRef null = PyStackRef_NULL;
oparg = CURRENT_OPARG();
dict = (PyDictObject *)stack_pointer[-1].bits;
owner = stack_pointer[-2];
@@ -2832,7 +2883,7 @@
JUMP_TO_JUMP_TARGET();
}
}
- 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);
stack_pointer += -1;
@@ -2865,16 +2916,20 @@
STAT_INC(LOAD_ATTR, hit);
attr = PyStackRef_FromPyObjectNew(attr_o);
UNLOCK_OBJECT(dict);
+ null = PyStackRef_NULL;
PyStackRef_CLOSE(owner);
stack_pointer[-2] = attr;
- stack_pointer += -1;
+ if (oparg & 1) stack_pointer[-1] = null;
+ stack_pointer += -1 + (oparg & 1);
assert(WITHIN_STACK_BOUNDS());
break;
}
- case _LOAD_ATTR_SLOT: {
+ case _LOAD_ATTR_SLOT_0: {
_PyStackRef owner;
_PyStackRef attr;
+ _PyStackRef null = PyStackRef_NULL;
+ (void)null;
owner = stack_pointer[-1];
uint16_t index = (uint16_t)CURRENT_OPERAND0();
PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
@@ -2894,11 +2949,47 @@
attr = PyStackRef_FromPyObjectNew(attr_o);
#endif
STAT_INC(LOAD_ATTR, hit);
+ null = PyStackRef_NULL;
PyStackRef_CLOSE(owner);
stack_pointer[-1] = attr;
break;
}
+ case _LOAD_ATTR_SLOT_1: {
+ _PyStackRef owner;
+ _PyStackRef attr;
+ _PyStackRef null = PyStackRef_NULL;
+ (void)null;
+ owner = stack_pointer[-1];
+ uint16_t index = (uint16_t)CURRENT_OPERAND0();
+ PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
+ PyObject **addr = (PyObject **)((char *)owner_o + index);
+ PyObject *attr_o = FT_ATOMIC_LOAD_PTR(*addr);
+ if (attr_o == NULL) {
+ UOP_STAT_INC(uopcode, miss);
+ JUMP_TO_JUMP_TARGET();
+ }
+ #ifdef Py_GIL_DISABLED
+ int increfed = _Py_TryIncrefCompareStackRef(addr, attr_o, &attr);
+ if (!increfed) {
+ UOP_STAT_INC(uopcode, miss);
+ JUMP_TO_JUMP_TARGET();
+ }
+ #else
+ attr = PyStackRef_FromPyObjectNew(attr_o);
+ #endif
+ STAT_INC(LOAD_ATTR, hit);
+ null = PyStackRef_NULL;
+ PyStackRef_CLOSE(owner);
+ stack_pointer[-1] = attr;
+ stack_pointer[0] = null;
+ stack_pointer += 1;
+ assert(WITHIN_STACK_BOUNDS());
+ break;
+ }
+
+ /* _LOAD_ATTR_SLOT is split on (oparg & 1) */
+
case _CHECK_ATTR_CLASS: {
_PyStackRef owner;
owner = stack_pointer[-1];
@@ -2916,24 +3007,50 @@
break;
}
- case _LOAD_ATTR_CLASS: {
+ case _LOAD_ATTR_CLASS_0: {
_PyStackRef owner;
_PyStackRef attr;
+ _PyStackRef null = PyStackRef_NULL;
+ (void)null;
owner = stack_pointer[-1];
PyObject *descr = (PyObject *)CURRENT_OPERAND0();
STAT_INC(LOAD_ATTR, hit);
assert(descr != NULL);
attr = PyStackRef_FromPyObjectNew(descr);
+ null = PyStackRef_NULL;
PyStackRef_CLOSE(owner);
stack_pointer[-1] = attr;
break;
}
+ case _LOAD_ATTR_CLASS_1: {
+ _PyStackRef owner;
+ _PyStackRef attr;
+ _PyStackRef null = PyStackRef_NULL;
+ (void)null;
+ owner = stack_pointer[-1];
+ PyObject *descr = (PyObject *)CURRENT_OPERAND0();
+ STAT_INC(LOAD_ATTR, hit);
+ assert(descr != NULL);
+ attr = PyStackRef_FromPyObjectNew(descr);
+ null = PyStackRef_NULL;
+ PyStackRef_CLOSE(owner);
+ stack_pointer[-1] = attr;
+ stack_pointer[0] = null;
+ stack_pointer += 1;
+ assert(WITHIN_STACK_BOUNDS());
+ break;
+ }
+
+ /* _LOAD_ATTR_CLASS is split on (oparg & 1) */
+
case _LOAD_ATTR_PROPERTY_FRAME: {
_PyStackRef owner;
_PyInterpreterFrame *new_frame;
+ oparg = CURRENT_OPARG();
owner = stack_pointer[-1];
PyObject *fget = (PyObject *)CURRENT_OPERAND0();
+ assert((oparg & 1) == 0);
assert(Py_IS_TYPE(fget, &PyFunction_Type));
PyFunctionObject *f = (PyFunctionObject *)fget;
PyCodeObject *code = (PyCodeObject *)f->func_code;
@@ -3939,12 +4056,14 @@
break;
}
- case _LOAD_METHOD_WITH_VALUES: {
+ case _LOAD_ATTR_METHOD_WITH_VALUES: {
_PyStackRef owner;
_PyStackRef attr;
- _PyStackRef self;
+ _PyStackRef self = PyStackRef_NULL;
+ oparg = CURRENT_OPARG();
owner = stack_pointer[-1];
PyObject *descr = (PyObject *)CURRENT_OPERAND0();
+ assert(oparg & 1);
/* Cached method object */
STAT_INC(LOAD_ATTR, hit);
assert(descr != NULL);
@@ -3958,12 +4077,14 @@
break;
}
- case _LOAD_METHOD_NO_DICT: {
+ case _LOAD_ATTR_METHOD_NO_DICT: {
_PyStackRef owner;
_PyStackRef attr;
- _PyStackRef self;
+ _PyStackRef self = PyStackRef_NULL;
+ oparg = CURRENT_OPARG();
owner = stack_pointer[-1];
PyObject *descr = (PyObject *)CURRENT_OPERAND0();
+ assert(oparg & 1);
assert(Py_TYPE(PyStackRef_AsPyObjectBorrow(owner))->tp_dictoffset == 0);
STAT_INC(LOAD_ATTR, hit);
assert(descr != NULL);
@@ -3980,8 +4101,10 @@
case _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES: {
_PyStackRef owner;
_PyStackRef attr;
+ oparg = CURRENT_OPARG();
owner = stack_pointer[-1];
PyObject *descr = (PyObject *)CURRENT_OPERAND0();
+ assert((oparg & 1) == 0);
STAT_INC(LOAD_ATTR, hit);
assert(descr != NULL);
PyStackRef_CLOSE(owner);
@@ -3993,8 +4116,10 @@
case _LOAD_ATTR_NONDESCRIPTOR_NO_DICT: {
_PyStackRef owner;
_PyStackRef attr;
+ oparg = CURRENT_OPARG();
owner = stack_pointer[-1];
PyObject *descr = (PyObject *)CURRENT_OPERAND0();
+ assert((oparg & 1) == 0);
assert(Py_TYPE(PyStackRef_AsPyObjectBorrow(owner))->tp_dictoffset == 0);
STAT_INC(LOAD_ATTR, hit);
assert(descr != NULL);
@@ -4018,12 +4143,14 @@
break;
}
- case _LOAD_METHOD_LAZY_DICT: {
+ case _LOAD_ATTR_METHOD_LAZY_DICT: {
_PyStackRef owner;
_PyStackRef attr;
- _PyStackRef self;
+ _PyStackRef self = PyStackRef_NULL;
+ oparg = CURRENT_OPARG();
owner = stack_pointer[-1];
PyObject *descr = (PyObject *)CURRENT_OPERAND0();
+ assert(oparg & 1);
STAT_INC(LOAD_ATTR, hit);
assert(descr != NULL);
assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR));
@@ -5517,14 +5644,15 @@
/* _INSTRUMENTED_CALL_FUNCTION_EX is not a viable micro-op for tier 2 because it is instrumented */
case _MAKE_CALLARGS_A_TUPLE: {
- _PyStackRef kwargs_in;
+ _PyStackRef kwargs_in = PyStackRef_NULL;
_PyStackRef callargs;
_PyStackRef func;
_PyStackRef tuple;
- _PyStackRef kwargs_out;
- kwargs_in = stack_pointer[-1];
- callargs = stack_pointer[-2];
- func = stack_pointer[-4];
+ _PyStackRef kwargs_out = PyStackRef_NULL;
+ oparg = CURRENT_OPARG();
+ if (oparg & 1) { kwargs_in = stack_pointer[-(oparg & 1)]; }
+ callargs = stack_pointer[-1 - (oparg & 1)];
+ func = stack_pointer[-3 - (oparg & 1)];
PyObject *callargs_o = PyStackRef_AsPyObjectBorrow(callargs);
if (PyTuple_CheckExact(callargs_o)) {
tuple = callargs;
@@ -5547,8 +5675,8 @@
PyStackRef_CLOSE(callargs);
tuple = PyStackRef_FromPyObjectSteal(tuple_o);
}
- stack_pointer[-2] = tuple;
- stack_pointer[-1] = kwargs_out;
+ stack_pointer[-1 - (oparg & 1)] = tuple;
+ if (oparg & 1) stack_pointer[-(oparg & 1)] = kwargs_out;
break;
}
@@ -5625,27 +5753,25 @@
}
case _BUILD_SLICE: {
- _PyStackRef *args;
+ _PyStackRef step = PyStackRef_NULL;
+ _PyStackRef stop;
+ _PyStackRef start;
_PyStackRef slice;
oparg = CURRENT_OPARG();
- args = &stack_pointer[-oparg];
- assert(oparg == 2 || oparg == 3);
- _PyStackRef start = args[0];
- _PyStackRef stop = args[1];
+ if (oparg == 3) { step = stack_pointer[-((oparg == 3) ? 1 : 0)]; }
+ stop = stack_pointer[-1 - ((oparg == 3) ? 1 : 0)];
+ start = stack_pointer[-2 - ((oparg == 3) ? 1 : 0)];
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);
- for (int _i = oparg; --_i >= 0;) {
- PyStackRef_CLOSE(args[_i]);
- }
+ PyStackRef_CLOSE(start);
+ PyStackRef_CLOSE(stop);
+ PyStackRef_XCLOSE(step);
if (slice_o == NULL) JUMP_TO_ERROR();
slice = PyStackRef_FromPyObjectSteal(slice_o);
- stack_pointer[-oparg] = slice;
- stack_pointer += 1 - oparg;
+ stack_pointer[-2 - ((oparg == 3) ? 1 : 0)] = slice;
+ stack_pointer += -1 - ((oparg == 3) ? 1 : 0);
assert(WITHIN_STACK_BOUNDS());
break;
}
@@ -6012,6 +6138,8 @@
case _LOAD_GLOBAL_MODULE: {
_PyStackRef res;
+ _PyStackRef null = PyStackRef_NULL;
+ oparg = CURRENT_OPARG();
uint16_t index = (uint16_t)CURRENT_OPERAND0();
PyDictObject *dict = (PyDictObject *)GLOBALS();
PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(dict->ma_keys);
@@ -6022,14 +6150,18 @@
}
Py_INCREF(res_o);
res = PyStackRef_FromPyObjectSteal(res_o);
+ null = PyStackRef_NULL;
stack_pointer[0] = res;
- stack_pointer += 1;
+ if (oparg & 1) stack_pointer[1] = null;
+ stack_pointer += 1 + (oparg & 1);
assert(WITHIN_STACK_BOUNDS());
break;
}
case _LOAD_GLOBAL_BUILTINS: {
_PyStackRef res;
+ _PyStackRef null = PyStackRef_NULL;
+ oparg = CURRENT_OPARG();
uint16_t index = (uint16_t)CURRENT_OPERAND0();
PyDictObject *dict = (PyDictObject *)BUILTINS();
PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(dict->ma_keys);
@@ -6040,8 +6172,10 @@
}
Py_INCREF(res_o);
res = PyStackRef_FromPyObjectSteal(res_o);
+ null = PyStackRef_NULL;
stack_pointer[0] = res;
- stack_pointer += 1;
+ if (oparg & 1) stack_pointer[1] = null;
+ stack_pointer += 1 + (oparg & 1);
assert(WITHIN_STACK_BOUNDS());
break;
}
@@ -6049,6 +6183,8 @@
case _LOAD_ATTR_MODULE: {
_PyStackRef owner;
_PyStackRef attr;
+ _PyStackRef null = PyStackRef_NULL;
+ oparg = CURRENT_OPARG();
owner = stack_pointer[-1];
uint16_t index = (uint16_t)CURRENT_OPERAND0();
PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
@@ -6064,8 +6200,12 @@
STAT_INC(LOAD_ATTR, hit);
Py_INCREF(attr_o);
attr = PyStackRef_FromPyObjectSteal(attr_o);
+ null = PyStackRef_NULL;
PyStackRef_CLOSE(owner);
stack_pointer[-1] = attr;
+ if (oparg & 1) stack_pointer[0] = null;
+ stack_pointer += (oparg & 1);
+ assert(WITHIN_STACK_BOUNDS());
break;
}