diff options
-rw-r--r-- | Include/internal/pycore_uops.h | 2 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Core and Builtins/2023-11-20-10-40-40.gh-issue-112287.15gWAK.rst | 3 | ||||
-rw-r--r-- | Python/ceval.c | 16 | ||||
-rw-r--r-- | Python/ceval_macros.h | 4 | ||||
-rw-r--r-- | Python/executor_cases.c.h | 135 | ||||
-rw-r--r-- | Tools/cases_generator/generate_cases.py | 2 | ||||
-rw-r--r-- | Tools/cases_generator/instructions.py | 2 |
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 |