summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Include/internal/pycore_uops.h2
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2023-11-20-10-40-40.gh-issue-112287.15gWAK.rst3
-rw-r--r--Python/ceval.c16
-rw-r--r--Python/ceval_macros.h4
-rw-r--r--Python/executor_cases.c.h135
-rw-r--r--Tools/cases_generator/generate_cases.py2
-rw-r--r--Tools/cases_generator/instructions.py2
7 files changed, 131 insertions, 33 deletions
diff --git a/Include/internal/pycore_uops.h b/Include/internal/pycore_uops.h
index 8ab9aaf..e2b9489 100644
--- a/Include/internal/pycore_uops.h
+++ b/Include/internal/pycore_uops.h
@@ -10,7 +10,7 @@ extern "C" {
#include "pycore_frame.h" // _PyInterpreterFrame
-#define _Py_UOP_MAX_TRACE_LENGTH 256
+#define _Py_UOP_MAX_TRACE_LENGTH 512
typedef struct {
uint16_t opcode;
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-11-20-10-40-40.gh-issue-112287.15gWAK.rst b/Misc/NEWS.d/next/Core and Builtins/2023-11-20-10-40-40.gh-issue-112287.15gWAK.rst
new file mode 100644
index 0000000..3f31a0f
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-11-20-10-40-40.gh-issue-112287.15gWAK.rst
@@ -0,0 +1,3 @@
+Slightly optimize the Tier 2 (uop) interpreter by only loading ``oparg`` and
+``operand`` when needed. Also double the trace size limit again, to 512 this
+time.
diff --git a/Python/ceval.c b/Python/ceval.c
index b5e8593..b19b746 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -994,21 +994,18 @@ enter_tier_two:
OPT_STAT_INC(traces_executed);
_PyUOpInstruction *next_uop = current_executor->trace;
- uint64_t operand;
#ifdef Py_STATS
uint64_t trace_uop_execution_counter = 0;
#endif
for (;;) {
opcode = next_uop->opcode;
- oparg = next_uop->oparg;
- operand = next_uop->operand;
DPRINTF(3,
"%4d: uop %s, oparg %d, operand %" PRIu64 ", target %d, stack_level %d\n",
(int)(next_uop - current_executor->trace),
_PyUopName(opcode),
- oparg,
- operand,
+ next_uop->oparg,
+ next_uop->operand,
next_uop->target,
(int)(stack_pointer - _PyFrame_Stackbase(frame)));
next_uop++;
@@ -1025,8 +1022,9 @@ enter_tier_two:
default:
#ifdef Py_DEBUG
{
- fprintf(stderr, "Unknown uop %d, oparg %d, operand %" PRIu64 "\n",
- opcode, oparg, operand);
+ fprintf(stderr, "Unknown uop %d, oparg %d, operand %" PRIu64 " @ %d\n",
+ opcode, next_uop[-1].oparg, next_uop[-1].operand,
+ (int)(next_uop - current_executor->trace - 1));
Py_FatalError("Unknown uop");
}
#else
@@ -1055,7 +1053,7 @@ pop_1_error_tier_two:
STACK_SHRINK(1);
error_tier_two:
DPRINTF(2, "Error: [Uop %d (%s), oparg %d, operand %" PRIu64 ", target %d @ %d]\n",
- opcode, _PyUopName(opcode), oparg, operand, next_uop[-1].target,
+ opcode, _PyUopName(opcode), next_uop[-1].oparg, next_uop[-1].operand, next_uop[-1].target,
(int)(next_uop - current_executor->trace - 1));
OPT_HIST(trace_uop_execution_counter, trace_run_length_hist);
frame->return_offset = 0; // Don't leave this random
@@ -1068,7 +1066,7 @@ deoptimize:
// On DEOPT_IF we just repeat the last instruction.
// This presumes nothing was popped from the stack (nor pushed).
DPRINTF(2, "DEOPT: [Uop %d (%s), oparg %d, operand %" PRIu64 ", target %d @ %d]\n",
- opcode, _PyUopName(opcode), oparg, operand, next_uop[-1].target,
+ opcode, _PyUopName(opcode), next_uop[-1].oparg, next_uop[-1].operand, next_uop[-1].target,
(int)(next_uop - current_executor->trace - 1));
OPT_HIST(trace_uop_execution_counter, trace_run_length_hist);
UOP_STAT_INC(opcode, miss);
diff --git a/Python/ceval_macros.h b/Python/ceval_macros.h
index 546adbe..b0cb7c8 100644
--- a/Python/ceval_macros.h
+++ b/Python/ceval_macros.h
@@ -397,3 +397,7 @@ stack_pointer = _PyFrame_GetStackPointer(frame);
#define GOTO_TIER_TWO() goto enter_tier_two;
#define GOTO_TIER_ONE() goto exit_trace;
+
+#define CURRENT_OPARG() (next_uop[-1].oparg)
+
+#define CURRENT_OPERAND() (next_uop[-1].operand)
diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h
index ae662b2..547be6f 100644
--- a/Python/executor_cases.c.h
+++ b/Python/executor_cases.c.h
@@ -25,6 +25,7 @@
}
case LOAD_FAST_CHECK: {
+ oparg = CURRENT_OPARG();
PyObject *value;
value = GETLOCAL(oparg);
if (value == NULL) goto unbound_local_error_tier_two;
@@ -35,6 +36,7 @@
}
case LOAD_FAST: {
+ oparg = CURRENT_OPARG();
PyObject *value;
value = GETLOCAL(oparg);
assert(value != NULL);
@@ -45,6 +47,7 @@
}
case LOAD_FAST_AND_CLEAR: {
+ oparg = CURRENT_OPARG();
PyObject *value;
value = GETLOCAL(oparg);
// do not use SETLOCAL here, it decrefs the old value
@@ -55,6 +58,7 @@
}
case LOAD_CONST: {
+ oparg = CURRENT_OPARG();
PyObject *value;
value = GETITEM(FRAME_CO_CONSTS, oparg);
Py_INCREF(value);
@@ -64,6 +68,7 @@
}
case STORE_FAST: {
+ oparg = CURRENT_OPARG();
PyObject *value;
value = stack_pointer[-1];
SETLOCAL(oparg, value);
@@ -204,7 +209,7 @@
PyObject *value;
PyObject *res;
value = stack_pointer[-1];
- uint32_t version = (uint32_t)operand;
+ uint32_t version = (uint32_t)CURRENT_OPERAND();
// This one is a bit weird, because we expect *some* failures:
assert(version);
DEOPT_IF(Py_TYPE(value)->tp_version_tag != version, TO_BOOL);
@@ -525,6 +530,7 @@
}
case LIST_APPEND: {
+ oparg = CURRENT_OPARG();
PyObject *v;
PyObject *list;
v = stack_pointer[-1];
@@ -535,6 +541,7 @@
}
case SET_ADD: {
+ oparg = CURRENT_OPARG();
PyObject *v;
PyObject *set;
v = stack_pointer[-1];
@@ -621,6 +628,7 @@
}
case CALL_INTRINSIC_1: {
+ oparg = CURRENT_OPARG();
PyObject *value;
PyObject *res;
value = stack_pointer[-1];
@@ -633,6 +641,7 @@
}
case CALL_INTRINSIC_2: {
+ oparg = CURRENT_OPARG();
PyObject *value1;
PyObject *value2;
PyObject *res;
@@ -764,6 +773,7 @@
}
case GET_AWAITABLE: {
+ oparg = CURRENT_OPARG();
PyObject *iterable;
PyObject *iter;
iterable = stack_pointer[-1];
@@ -825,6 +835,7 @@
}
case STORE_NAME: {
+ oparg = CURRENT_OPARG();
PyObject *v;
v = stack_pointer[-1];
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
@@ -847,6 +858,7 @@
}
case DELETE_NAME: {
+ oparg = CURRENT_OPARG();
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
PyObject *ns = LOCALS();
int err;
@@ -867,6 +879,7 @@
}
case _UNPACK_SEQUENCE: {
+ oparg = CURRENT_OPARG();
PyObject *seq;
seq = stack_pointer[-1];
PyObject **top = stack_pointer + oparg - 1;
@@ -879,6 +892,7 @@
}
case UNPACK_SEQUENCE_TWO_TUPLE: {
+ oparg = CURRENT_OPARG();
PyObject *seq;
PyObject **values;
seq = stack_pointer[-1];
@@ -896,6 +910,7 @@
}
case UNPACK_SEQUENCE_TUPLE: {
+ oparg = CURRENT_OPARG();
PyObject *seq;
PyObject **values;
seq = stack_pointer[-1];
@@ -914,6 +929,7 @@
}
case UNPACK_SEQUENCE_LIST: {
+ oparg = CURRENT_OPARG();
PyObject *seq;
PyObject **values;
seq = stack_pointer[-1];
@@ -932,6 +948,7 @@
}
case UNPACK_EX: {
+ oparg = CURRENT_OPARG();
PyObject *seq;
seq = stack_pointer[-1];
int totalargs = 1 + (oparg & 0xFF) + (oparg >> 8);
@@ -944,6 +961,7 @@
}
case _STORE_ATTR: {
+ oparg = CURRENT_OPARG();
PyObject *owner;
PyObject *v;
owner = stack_pointer[-1];
@@ -958,6 +976,7 @@
}
case DELETE_ATTR: {
+ oparg = CURRENT_OPARG();
PyObject *owner;
owner = stack_pointer[-1];
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
@@ -969,6 +988,7 @@
}
case STORE_GLOBAL: {
+ oparg = CURRENT_OPARG();
PyObject *v;
v = stack_pointer[-1];
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
@@ -980,6 +1000,7 @@
}
case DELETE_GLOBAL: {
+ oparg = CURRENT_OPARG();
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
int err;
err = PyDict_DelItem(GLOBALS(), name);
@@ -1009,6 +1030,7 @@
}
case LOAD_FROM_DICT_OR_GLOBALS: {
+ oparg = CURRENT_OPARG();
PyObject *mod_or_class_dict;
PyObject *v;
mod_or_class_dict = stack_pointer[-1];
@@ -1038,6 +1060,7 @@
}
case LOAD_NAME: {
+ oparg = CURRENT_OPARG();
PyObject *v;
PyObject *mod_or_class_dict = LOCALS();
if (mod_or_class_dict == NULL) {
@@ -1071,6 +1094,7 @@
}
case _LOAD_GLOBAL: {
+ oparg = CURRENT_OPARG();
PyObject *res;
PyObject *null = NULL;
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
@@ -1115,7 +1139,7 @@
}
case _GUARD_GLOBALS_VERSION: {
- uint16_t version = (uint16_t)operand;
+ uint16_t version = (uint16_t)CURRENT_OPERAND();
PyDictObject *dict = (PyDictObject *)GLOBALS();
DEOPT_IF(!PyDict_CheckExact(dict), _GUARD_GLOBALS_VERSION);
DEOPT_IF(dict->ma_keys->dk_version != version, _GUARD_GLOBALS_VERSION);
@@ -1124,7 +1148,7 @@
}
case _GUARD_BUILTINS_VERSION: {
- uint16_t version = (uint16_t)operand;
+ uint16_t version = (uint16_t)CURRENT_OPERAND();
PyDictObject *dict = (PyDictObject *)BUILTINS();
DEOPT_IF(!PyDict_CheckExact(dict), _GUARD_BUILTINS_VERSION);
DEOPT_IF(dict->ma_keys->dk_version != version, _GUARD_BUILTINS_VERSION);
@@ -1133,9 +1157,10 @@
}
case _LOAD_GLOBAL_MODULE: {
+ oparg = CURRENT_OPARG();
PyObject *res;
PyObject *null = NULL;
- uint16_t index = (uint16_t)operand;
+ uint16_t index = (uint16_t)CURRENT_OPERAND();
PyDictObject *dict = (PyDictObject *)GLOBALS();
PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(dict->ma_keys);
res = entries[index].me_value;
@@ -1151,9 +1176,10 @@
}
case _LOAD_GLOBAL_BUILTINS: {
+ oparg = CURRENT_OPARG();
PyObject *res;
PyObject *null = NULL;
- uint16_t index = (uint16_t)operand;
+ uint16_t index = (uint16_t)CURRENT_OPERAND();
PyDictObject *bdict = (PyDictObject *)BUILTINS();
PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(bdict->ma_keys);
res = entries[index].me_value;
@@ -1169,6 +1195,7 @@
}
case DELETE_FAST: {
+ oparg = CURRENT_OPARG();
PyObject *v = GETLOCAL(oparg);
if (v == NULL) goto unbound_local_error_tier_two;
SETLOCAL(oparg, NULL);
@@ -1176,6 +1203,7 @@
}
case MAKE_CELL: {
+ oparg = CURRENT_OPARG();
// "initial" is probably NULL but not if it's an arg (or set
// via PyFrame_LocalsToFast() before MAKE_CELL has run).
PyObject *initial = GETLOCAL(oparg);
@@ -1188,6 +1216,7 @@
}
case DELETE_DEREF: {
+ oparg = CURRENT_OPARG();
PyObject *cell = GETLOCAL(oparg);
PyObject *oldobj = PyCell_GET(cell);
// Can't use ERROR_IF here.
@@ -1202,6 +1231,7 @@
}
case LOAD_FROM_DICT_OR_DEREF: {
+ oparg = CURRENT_OPARG();
PyObject *class_dict;
PyObject *value;
class_dict = stack_pointer[-1];
@@ -1227,6 +1257,7 @@
}
case LOAD_DEREF: {
+ oparg = CURRENT_OPARG();
PyObject *value;
PyObject *cell = GETLOCAL(oparg);
value = PyCell_GET(cell);
@@ -1241,6 +1272,7 @@
}
case STORE_DEREF: {
+ oparg = CURRENT_OPARG();
PyObject *v;
v = stack_pointer[-1];
PyObject *cell = GETLOCAL(oparg);
@@ -1252,6 +1284,7 @@
}
case COPY_FREE_VARS: {
+ oparg = CURRENT_OPARG();
/* Copy closure variables to free variables */
PyCodeObject *co = _PyFrame_GetCode(frame);
assert(PyFunction_Check(frame->f_funcobj));
@@ -1266,6 +1299,7 @@
}
case BUILD_STRING: {
+ oparg = CURRENT_OPARG();
PyObject **pieces;
PyObject *str;
pieces = stack_pointer - oparg;
@@ -1281,6 +1315,7 @@
}
case BUILD_TUPLE: {
+ oparg = CURRENT_OPARG();
PyObject **values;
PyObject *tup;
values = stack_pointer - oparg;
@@ -1293,6 +1328,7 @@
}
case BUILD_LIST: {
+ oparg = CURRENT_OPARG();
PyObject **values;
PyObject *list;
values = stack_pointer - oparg;
@@ -1305,6 +1341,7 @@
}
case LIST_EXTEND: {
+ oparg = CURRENT_OPARG();
PyObject *iterable;
PyObject *list;
iterable = stack_pointer[-1];
@@ -1329,6 +1366,7 @@
}
case SET_UPDATE: {
+ oparg = CURRENT_OPARG();
PyObject *iterable;
PyObject *set;
iterable = stack_pointer[-1];
@@ -1341,6 +1379,7 @@
}
case BUILD_SET: {
+ oparg = CURRENT_OPARG();
PyObject **values;
PyObject *set;
values = stack_pointer - oparg;
@@ -1365,6 +1404,7 @@
}
case BUILD_MAP: {
+ oparg = CURRENT_OPARG();
PyObject **values;
PyObject *map;
values = stack_pointer - oparg*2;
@@ -1407,6 +1447,7 @@
}
case BUILD_CONST_KEY_MAP: {
+ oparg = CURRENT_OPARG();
PyObject *keys;
PyObject **values;
PyObject *map;
@@ -1432,6 +1473,7 @@
}
case DICT_UPDATE: {
+ oparg = CURRENT_OPARG();
PyObject *update;
PyObject *dict;
update = stack_pointer[-1];
@@ -1451,6 +1493,7 @@
}
case DICT_MERGE: {
+ oparg = CURRENT_OPARG();
PyObject *update;
PyObject *dict;
PyObject *callable;
@@ -1468,6 +1511,7 @@
}
case MAP_ADD: {
+ oparg = CURRENT_OPARG();
PyObject *value;
PyObject *key;
PyObject *dict;
@@ -1483,6 +1527,7 @@
}
case LOAD_SUPER_ATTR_ATTR: {
+ oparg = CURRENT_OPARG();
PyObject *self;
PyObject *class;
PyObject *global_super;
@@ -1506,6 +1551,7 @@
}
case LOAD_SUPER_ATTR_METHOD: {
+ oparg = CURRENT_OPARG();
PyObject *self;
PyObject *class;
PyObject *global_super;
@@ -1542,6 +1588,7 @@
}
case _LOAD_ATTR: {
+ oparg = CURRENT_OPARG();
PyObject *owner;
PyObject *attr;
PyObject *self_or_null = NULL;
@@ -1585,7 +1632,7 @@
case _GUARD_TYPE_VERSION: {
PyObject *owner;
owner = stack_pointer[-1];
- uint32_t type_version = (uint32_t)operand;
+ uint32_t type_version = (uint32_t)CURRENT_OPERAND();
PyTypeObject *tp = Py_TYPE(owner);
assert(type_version != 0);
DEOPT_IF(tp->tp_version_tag != type_version, _GUARD_TYPE_VERSION);
@@ -1603,11 +1650,12 @@
}
case _LOAD_ATTR_INSTANCE_VALUE: {
+ oparg = CURRENT_OPARG();
PyObject *owner;
PyObject *attr;
PyObject *null = NULL;
owner = stack_pointer[-1];
- uint16_t index = (uint16_t)operand;
+ uint16_t index = (uint16_t)CURRENT_OPERAND();
PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
attr = _PyDictOrValues_GetValues(dorv)->values[index];
DEOPT_IF(attr == NULL, _LOAD_ATTR_INSTANCE_VALUE);
@@ -1624,7 +1672,7 @@
case _CHECK_ATTR_MODULE: {
PyObject *owner;
owner = stack_pointer[-1];
- uint32_t type_version = (uint32_t)operand;
+ uint32_t type_version = (uint32_t)CURRENT_OPERAND();
DEOPT_IF(!PyModule_CheckExact(owner), _CHECK_ATTR_MODULE);
PyDictObject *dict = (PyDictObject *)((PyModuleObject *)owner)->md_dict;
assert(dict != NULL);
@@ -1633,11 +1681,12 @@
}
case _LOAD_ATTR_MODULE: {
+ oparg = CURRENT_OPARG();
PyObject *owner;
PyObject *attr;
PyObject *null = NULL;
owner = stack_pointer[-1];
- uint16_t index = (uint16_t)operand;
+ uint16_t index = (uint16_t)CURRENT_OPERAND();
PyDictObject *dict = (PyDictObject *)((PyModuleObject *)owner)->md_dict;
assert(dict->ma_keys->dk_kind == DICT_KEYS_UNICODE);
assert(index < dict->ma_keys->dk_nentries);
@@ -1667,11 +1716,12 @@
}
case _LOAD_ATTR_WITH_HINT: {
+ oparg = CURRENT_OPARG();
PyObject *owner;
PyObject *attr;
PyObject *null = NULL;
owner = stack_pointer[-1];
- uint16_t hint = (uint16_t)operand;
+ uint16_t hint = (uint16_t)CURRENT_OPERAND();
PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
PyDictObject *dict = (PyDictObject *)_PyDictOrValues_GetDict(dorv);
DEOPT_IF(hint >= (size_t)dict->ma_keys->dk_nentries, _LOAD_ATTR_WITH_HINT);
@@ -1698,11 +1748,12 @@
}
case _LOAD_ATTR_SLOT: {
+ oparg = CURRENT_OPARG();
PyObject *owner;
PyObject *attr;
PyObject *null = NULL;
owner = stack_pointer[-1];
- uint16_t index = (uint16_t)operand;
+ uint16_t index = (uint16_t)CURRENT_OPERAND();
char *addr = (char *)owner + index;
attr = *(PyObject **)addr;
DEOPT_IF(attr == NULL, _LOAD_ATTR_SLOT);
@@ -1719,7 +1770,7 @@
case _CHECK_ATTR_CLASS: {
PyObject *owner;
owner = stack_pointer[-1];
- uint32_t type_version = (uint32_t)operand;
+ uint32_t type_version = (uint32_t)CURRENT_OPERAND();
DEOPT_IF(!PyType_Check(owner), _CHECK_ATTR_CLASS);
assert(type_version != 0);
DEOPT_IF(((PyTypeObject *)owner)->tp_version_tag != type_version, _CHECK_ATTR_CLASS);
@@ -1727,11 +1778,12 @@
}
case _LOAD_ATTR_CLASS: {
+ oparg = CURRENT_OPARG();
PyObject *owner;
PyObject *attr;
PyObject *null = NULL;
owner = stack_pointer[-1];
- PyObject *descr = (PyObject *)operand;
+ PyObject *descr = (PyObject *)CURRENT_OPERAND();
STAT_INC(LOAD_ATTR, hit);
assert(descr != NULL);
attr = Py_NewRef(descr);
@@ -1757,7 +1809,7 @@
PyObject *value;
owner = stack_pointer[-1];
value = stack_pointer[-2];
- uint16_t index = (uint16_t)operand;
+ uint16_t index = (uint16_t)CURRENT_OPERAND();
PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
STAT_INC(STORE_ATTR, hit);
PyDictValues *values = _PyDictOrValues_GetValues(dorv);
@@ -1779,7 +1831,7 @@
PyObject *value;
owner = stack_pointer[-1];
value = stack_pointer[-2];
- uint16_t index = (uint16_t)operand;
+ uint16_t index = (uint16_t)CURRENT_OPERAND();
char *addr = (char *)owner + index;
STAT_INC(STORE_ATTR, hit);
PyObject *old_value = *(PyObject **)addr;
@@ -1791,6 +1843,7 @@
}
case _COMPARE_OP: {
+ oparg = CURRENT_OPARG();
PyObject *right;
PyObject *left;
PyObject *res;
@@ -1813,6 +1866,7 @@
}
case COMPARE_OP_FLOAT: {
+ oparg = CURRENT_OPARG();
PyObject *right;
PyObject *left;
PyObject *res;
@@ -1835,6 +1889,7 @@
}
case COMPARE_OP_INT: {
+ oparg = CURRENT_OPARG();
PyObject *right;
PyObject *left;
PyObject *res;
@@ -1861,6 +1916,7 @@
}
case COMPARE_OP_STR: {
+ oparg = CURRENT_OPARG();
PyObject *right;
PyObject *left;
PyObject *res;
@@ -1884,6 +1940,7 @@
}
case IS_OP: {
+ oparg = CURRENT_OPARG();
PyObject *right;
PyObject *left;
PyObject *b;
@@ -1899,6 +1956,7 @@
}
case CONTAINS_OP: {
+ oparg = CURRENT_OPARG();
PyObject *right;
PyObject *left;
PyObject *b;
@@ -1995,6 +2053,7 @@
}
case MATCH_CLASS: {
+ oparg = CURRENT_OPARG();
PyObject *names;
PyObject *type;
PyObject *subject;
@@ -2378,7 +2437,7 @@
case _GUARD_KEYS_VERSION: {
PyObject *owner;
owner = stack_pointer[-1];
- uint32_t keys_version = (uint32_t)operand;
+ uint32_t keys_version = (uint32_t)CURRENT_OPERAND();
PyTypeObject *owner_cls = Py_TYPE(owner);
PyHeapTypeObject *owner_heap_type = (PyHeapTypeObject *)owner_cls;
DEOPT_IF(owner_heap_type->ht_cached_keys->dk_version != keys_version, _GUARD_KEYS_VERSION);
@@ -2386,11 +2445,12 @@
}
case _LOAD_ATTR_METHOD_WITH_VALUES: {
+ oparg = CURRENT_OPARG();
PyObject *owner;
PyObject *attr;
PyObject *self;
owner = stack_pointer[-1];
- PyObject *descr = (PyObject *)operand;
+ PyObject *descr = (PyObject *)CURRENT_OPERAND();
assert(oparg & 1);
/* Cached method object */
STAT_INC(LOAD_ATTR, hit);
@@ -2405,11 +2465,12 @@
}
case _LOAD_ATTR_METHOD_NO_DICT: {
+ oparg = CURRENT_OPARG();
PyObject *owner;
PyObject *attr;
PyObject *self;
owner = stack_pointer[-1];
- PyObject *descr = (PyObject *)operand;
+ PyObject *descr = (PyObject *)CURRENT_OPERAND();
assert(oparg & 1);
assert(Py_TYPE(owner)->tp_dictoffset == 0);
STAT_INC(LOAD_ATTR, hit);
@@ -2424,10 +2485,11 @@
}
case _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES: {
+ oparg = CURRENT_OPARG();
PyObject *owner;
PyObject *attr;
owner = stack_pointer[-1];
- PyObject *descr = (PyObject *)operand;
+ PyObject *descr = (PyObject *)CURRENT_OPERAND();
assert((oparg & 1) == 0);
STAT_INC(LOAD_ATTR, hit);
assert(descr != NULL);
@@ -2438,10 +2500,11 @@
}
case _LOAD_ATTR_NONDESCRIPTOR_NO_DICT: {
+ oparg = CURRENT_OPARG();
PyObject *owner;
PyObject *attr;
owner = stack_pointer[-1];
- PyObject *descr = (PyObject *)operand;
+ PyObject *descr = (PyObject *)CURRENT_OPERAND();
assert((oparg & 1) == 0);
assert(Py_TYPE(owner)->tp_dictoffset == 0);
STAT_INC(LOAD_ATTR, hit);
@@ -2464,11 +2527,12 @@
}
case _LOAD_ATTR_METHOD_LAZY_DICT: {
+ oparg = CURRENT_OPARG();
PyObject *owner;
PyObject *attr;
PyObject *self;
owner = stack_pointer[-1];
- PyObject *descr = (PyObject *)operand;
+ PyObject *descr = (PyObject *)CURRENT_OPERAND();
assert(oparg & 1);
STAT_INC(LOAD_ATTR, hit);
assert(descr != NULL);
@@ -2482,6 +2546,7 @@
}
case _CHECK_CALL_BOUND_METHOD_EXACT_ARGS: {
+ oparg = CURRENT_OPARG();
PyObject *null;
PyObject *callable;
null = stack_pointer[-1 - oparg];
@@ -2492,6 +2557,7 @@
}
case _INIT_CALL_BOUND_METHOD_EXACT_ARGS: {
+ oparg = CURRENT_OPARG();
PyObject *callable;
PyObject *func;
PyObject *self;
@@ -2513,11 +2579,12 @@
}
case _CHECK_FUNCTION_EXACT_ARGS: {
+ oparg = CURRENT_OPARG();
PyObject *self_or_null;
PyObject *callable;
self_or_null = stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg];
- uint32_t func_version = (uint32_t)operand;
+ uint32_t func_version = (uint32_t)CURRENT_OPERAND();
DEOPT_IF(!PyFunction_Check(callable), _CHECK_FUNCTION_EXACT_ARGS);
PyFunctionObject *func = (PyFunctionObject *)callable;
DEOPT_IF(func->func_version != func_version, _CHECK_FUNCTION_EXACT_ARGS);
@@ -2527,6 +2594,7 @@
}
case _CHECK_STACK_SPACE: {
+ oparg = CURRENT_OPARG();
PyObject *callable;
callable = stack_pointer[-2 - oparg];
PyFunctionObject *func = (PyFunctionObject *)callable;
@@ -2537,6 +2605,7 @@
}
case _INIT_CALL_PY_EXACT_ARGS: {
+ oparg = CURRENT_OPARG();
PyObject **args;
PyObject *self_or_null;
PyObject *callable;
@@ -2585,6 +2654,7 @@
}
case CALL_TYPE_1: {
+ oparg = CURRENT_OPARG();
PyObject **args;
PyObject *null;
PyObject *callable;
@@ -2607,6 +2677,7 @@
}
case CALL_STR_1: {
+ oparg = CURRENT_OPARG();
PyObject **args;
PyObject *null;
PyObject *callable;
@@ -2631,6 +2702,7 @@
}
case CALL_TUPLE_1: {
+ oparg = CURRENT_OPARG();
PyObject **args;
PyObject *null;
PyObject *callable;
@@ -2669,6 +2741,7 @@
}
case CALL_BUILTIN_CLASS: {
+ oparg = CURRENT_OPARG();
PyObject **args;
PyObject *self_or_null;
PyObject *callable;
@@ -2700,6 +2773,7 @@
}
case CALL_BUILTIN_O: {
+ oparg = CURRENT_OPARG();
PyObject **args;
PyObject *self_or_null;
PyObject *callable;
@@ -2739,6 +2813,7 @@
}
case CALL_BUILTIN_FAST: {
+ oparg = CURRENT_OPARG();
PyObject **args;
PyObject *self_or_null;
PyObject *callable;
@@ -2782,6 +2857,7 @@
}
case CALL_BUILTIN_FAST_WITH_KEYWORDS: {
+ oparg = CURRENT_OPARG();
PyObject **args;
PyObject *self_or_null;
PyObject *callable;
@@ -2819,6 +2895,7 @@
}
case CALL_LEN: {
+ oparg = CURRENT_OPARG();
PyObject **args;
PyObject *self_or_null;
PyObject *callable;
@@ -2854,6 +2931,7 @@
}
case CALL_ISINSTANCE: {
+ oparg = CURRENT_OPARG();
PyObject **args;
PyObject *self_or_null;
PyObject *callable;
@@ -2891,6 +2969,7 @@
}
case CALL_METHOD_DESCRIPTOR_O: {
+ oparg = CURRENT_OPARG();
PyObject **args;
PyObject *self_or_null;
PyObject *callable;
@@ -2933,6 +3012,7 @@
}
case CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS: {
+ oparg = CURRENT_OPARG();
PyObject **args;
PyObject *self_or_null;
PyObject *callable;
@@ -2973,6 +3053,7 @@
}
case CALL_METHOD_DESCRIPTOR_NOARGS: {
+ oparg = CURRENT_OPARG();
PyObject **args;
PyObject *self_or_null;
PyObject *callable;
@@ -3014,6 +3095,7 @@
}
case CALL_METHOD_DESCRIPTOR_FAST: {
+ oparg = CURRENT_OPARG();
PyObject **args;
PyObject *self_or_null;
PyObject *callable;
@@ -3073,6 +3155,7 @@
}
case SET_FUNCTION_ATTRIBUTE: {
+ oparg = CURRENT_OPARG();
PyObject *func;
PyObject *attr;
func = stack_pointer[-1];
@@ -3107,6 +3190,7 @@
}
case BUILD_SLICE: {
+ oparg = CURRENT_OPARG();
PyObject *step = NULL;
PyObject *stop;
PyObject *start;
@@ -3126,6 +3210,7 @@
}
case CONVERT_VALUE: {
+ oparg = CURRENT_OPARG();
PyObject *value;
PyObject *result;
value = stack_pointer[-1];
@@ -3173,6 +3258,7 @@
}
case COPY: {
+ oparg = CURRENT_OPARG();
PyObject *bottom;
PyObject *top;
bottom = stack_pointer[-1 - (oparg-1)];
@@ -3184,6 +3270,7 @@
}
case _BINARY_OP: {
+ oparg = CURRENT_OPARG();
PyObject *rhs;
PyObject *lhs;
PyObject *res;
@@ -3200,6 +3287,7 @@
}
case SWAP: {
+ oparg = CURRENT_OPARG();
PyObject *top;
PyObject *bottom;
top = stack_pointer[-1];
@@ -3252,6 +3340,7 @@
}
case _SET_IP: {
+ oparg = CURRENT_OPARG();
TIER_TWO_ONLY
// TODO: Put the code pointer in `operand` to avoid indirection via `frame`
frame->instr_ptr = _PyCode_CODE(_PyFrame_GetCode(frame)) + oparg;
@@ -3259,6 +3348,7 @@
}
case _SAVE_RETURN_OFFSET: {
+ oparg = CURRENT_OPARG();
#if TIER_ONE
frame->return_offset = (uint16_t)(next_instr - this_instr);
#endif
@@ -3275,6 +3365,7 @@
}
case _INSERT: {
+ oparg = CURRENT_OPARG();
PyObject *top;
top = stack_pointer[-1];
// Inserts TOS at position specified by oparg;
diff --git a/Tools/cases_generator/generate_cases.py b/Tools/cases_generator/generate_cases.py
index 149558e..851bd2f 100644
--- a/Tools/cases_generator/generate_cases.py
+++ b/Tools/cases_generator/generate_cases.py
@@ -810,6 +810,8 @@ class Generator(Analyzer):
n_uops += 1
self.out.emit("")
with self.out.block(f"case {instr.name}:"):
+ if instr.instr_flags.HAS_ARG_FLAG:
+ self.out.emit("oparg = CURRENT_OPARG();")
stacking.write_single_instr(instr, self.out, tier=TIER_TWO)
if instr.check_eval_breaker:
self.out.emit("CHECK_EVAL_BREAKER();")
diff --git a/Tools/cases_generator/instructions.py b/Tools/cases_generator/instructions.py
index 9039ac5..149a088 100644
--- a/Tools/cases_generator/instructions.py
+++ b/Tools/cases_generator/instructions.py
@@ -166,7 +166,7 @@ class Instruction:
f"{func}(&this_instr[{active.offset + 1}].cache);"
)
else:
- out.emit(f"{typ}{ceffect.name} = ({typ.strip()})operand;")
+ out.emit(f"{typ}{ceffect.name} = ({typ.strip()})CURRENT_OPERAND();")
# Write the body, substituting a goto for ERROR_IF() and other stuff
assert dedent <= 0