From 093ac604b4cc1cade8b0a766a4f5ebea13443d0b Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Tue, 31 Oct 2023 13:21:07 +0000 Subject: [PATCH] GH-111485: Remove some special cases from the code generator and bytecodes.c (GH-111540) --- Include/internal/pycore_opcode_metadata.h | 36 ++++++++-------- Python/abstract_interp_cases.c.h | 11 +++++ Python/bytecodes.c | 18 +++++--- Python/executor_cases.c.h | 52 +++++++++++++++++++++++ Python/generated_cases.c.h | 18 +++++--- Tools/cases_generator/analysis.py | 5 +-- Tools/cases_generator/generate_cases.py | 25 +++++------ Tools/cases_generator/instructions.py | 9 ---- 8 files changed, 119 insertions(+), 55 deletions(-) diff --git a/Include/internal/pycore_opcode_metadata.h b/Include/internal/pycore_opcode_metadata.h index 27948749d58eb77..7b89f89b3f69c35 100644 --- a/Include/internal/pycore_opcode_metadata.h +++ b/Include/internal/pycore_opcode_metadata.h @@ -1298,9 +1298,9 @@ struct opcode_macro_expansion { #define OPARG_BOTTOM 6 #define OPARG_SAVE_RETURN_OFFSET 7 -#define OPCODE_METADATA_FMT(OP) (_PyOpcode_opcode_metadata[(OP)].instr_format) +#define OPCODE_METADATA_FLAGS(OP) (_PyOpcode_opcode_metadata[(OP)].flags & (HAS_ARG_FLAG | HAS_JUMP_FLAG)) #define SAME_OPCODE_METADATA(OP1, OP2) \ - (OPCODE_METADATA_FMT(OP1) == OPCODE_METADATA_FMT(OP2)) + (OPCODE_METADATA_FLAGS(OP1) == OPCODE_METADATA_FLAGS(OP2)) #define OPCODE_METADATA_SIZE 512 #define OPCODE_UOP_NAME_SIZE 512 @@ -1313,14 +1313,14 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[OPCODE_METADATA_SIZE] = { [RESUME] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG }, [RESUME_CHECK] = { true, INSTR_FMT_IX, HAS_DEOPT_FLAG }, [INSTRUMENTED_RESUME] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG }, - [LOAD_CLOSURE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG }, + [LOAD_CLOSURE] = { true, 0, HAS_ARG_FLAG | HAS_LOCAL_FLAG }, [LOAD_FAST_CHECK] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG | HAS_ERROR_FLAG }, [LOAD_FAST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG }, [LOAD_FAST_AND_CLEAR] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG }, [LOAD_FAST_LOAD_FAST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG }, [LOAD_CONST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_CONST_FLAG }, [STORE_FAST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG }, - [STORE_FAST_MAYBE_NULL] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG }, + [STORE_FAST_MAYBE_NULL] = { true, 0, HAS_ARG_FLAG | HAS_LOCAL_FLAG }, [STORE_FAST_LOAD_FAST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG }, [STORE_FAST_STORE_FAST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG }, [POP_TOP] = { true, INSTR_FMT_IX, 0 }, @@ -1436,13 +1436,13 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[OPCODE_METADATA_SIZE] = { [MAP_ADD] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG }, [INSTRUMENTED_LOAD_SUPER_ATTR] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG }, [LOAD_SUPER_ATTR] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG }, - [LOAD_SUPER_METHOD] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG }, - [LOAD_ZERO_SUPER_METHOD] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG }, - [LOAD_ZERO_SUPER_ATTR] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG }, + [LOAD_SUPER_METHOD] = { true, 0, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG }, + [LOAD_ZERO_SUPER_METHOD] = { true, 0, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG }, + [LOAD_ZERO_SUPER_ATTR] = { true, 0, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG }, [LOAD_SUPER_ATTR_ATTR] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG }, [LOAD_SUPER_ATTR_METHOD] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG }, [LOAD_ATTR] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG }, - [LOAD_METHOD] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG }, + [LOAD_METHOD] = { true, 0, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG }, [_GUARD_TYPE_VERSION] = { true, INSTR_FMT_IXC0, HAS_DEOPT_FLAG }, [_CHECK_MANAGED_OBJECT_HAS_VALUES] = { true, INSTR_FMT_IX, HAS_DEOPT_FLAG }, [_LOAD_ATTR_INSTANCE_VALUE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG }, @@ -1477,9 +1477,9 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[OPCODE_METADATA_SIZE] = { [IMPORT_NAME] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG }, [IMPORT_FROM] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG }, [JUMP_FORWARD] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_JUMP_FLAG }, - [JUMP_BACKWARD] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG }, - [JUMP] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_JUMP_FLAG }, - [JUMP_NO_INTERRUPT] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_JUMP_FLAG }, + [JUMP_BACKWARD] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG }, + [JUMP] = { true, 0, HAS_ARG_FLAG | HAS_JUMP_FLAG }, + [JUMP_NO_INTERRUPT] = { true, 0, HAS_ARG_FLAG | HAS_JUMP_FLAG }, [ENTER_EXECUTOR] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG }, [POP_JUMP_IF_FALSE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG }, [POP_JUMP_IF_TRUE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG }, @@ -1515,10 +1515,10 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[OPCODE_METADATA_SIZE] = { [BEFORE_ASYNC_WITH] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG }, [BEFORE_WITH] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG }, [WITH_EXCEPT_START] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG }, - [SETUP_FINALLY] = { true, INSTR_FMT_IX, 0 }, - [SETUP_CLEANUP] = { true, INSTR_FMT_IX, 0 }, - [SETUP_WITH] = { true, INSTR_FMT_IX, 0 }, - [POP_BLOCK] = { true, INSTR_FMT_IX, 0 }, + [SETUP_FINALLY] = { true, 0, 0 }, + [SETUP_CLEANUP] = { true, 0, 0 }, + [SETUP_WITH] = { true, 0, 0 }, + [POP_BLOCK] = { true, 0, 0 }, [PUSH_EXC_INFO] = { true, INSTR_FMT_IX, 0 }, [_GUARD_DORV_VALUES_INST_ATTR_FROM_DICT] = { true, INSTR_FMT_IX, HAS_DEOPT_FLAG }, [_GUARD_KEYS_VERSION] = { true, INSTR_FMT_IXC0, HAS_DEOPT_FLAG }, @@ -1577,7 +1577,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[OPCODE_METADATA_SIZE] = { [SWAP] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, [INSTRUMENTED_INSTRUCTION] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG }, [INSTRUMENTED_JUMP_FORWARD] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, - [INSTRUMENTED_JUMP_BACKWARD] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG }, + [INSTRUMENTED_JUMP_BACKWARD] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG }, [INSTRUMENTED_POP_JUMP_IF_TRUE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG }, [INSTRUMENTED_POP_JUMP_IF_FALSE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG }, [INSTRUMENTED_POP_JUMP_IF_NONE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG }, @@ -1670,6 +1670,7 @@ const struct opcode_macro_expansion _PyOpcode_macro_expansion[OPCODE_MACRO_EXPAN [LOAD_GLOBAL_MODULE] = { .nuops = 2, .uops = { { _GUARD_GLOBALS_VERSION, 1, 1 }, { _LOAD_GLOBAL_MODULE, 1, 3 } } }, [LOAD_GLOBAL_BUILTIN] = { .nuops = 3, .uops = { { _GUARD_GLOBALS_VERSION, 1, 1 }, { _GUARD_BUILTINS_VERSION, 1, 2 }, { _LOAD_GLOBAL_BUILTINS, 1, 3 } } }, [DELETE_FAST] = { .nuops = 1, .uops = { { DELETE_FAST, 0, 0 } } }, + [MAKE_CELL] = { .nuops = 1, .uops = { { MAKE_CELL, 0, 0 } } }, [DELETE_DEREF] = { .nuops = 1, .uops = { { DELETE_DEREF, 0, 0 } } }, [LOAD_FROM_DICT_OR_DEREF] = { .nuops = 1, .uops = { { LOAD_FROM_DICT_OR_DEREF, 0, 0 } } }, [LOAD_DEREF] = { .nuops = 1, .uops = { { LOAD_DEREF, 0, 0 } } }, @@ -1712,6 +1713,7 @@ const struct opcode_macro_expansion _PyOpcode_macro_expansion[OPCODE_MACRO_EXPAN [MATCH_KEYS] = { .nuops = 1, .uops = { { MATCH_KEYS, 0, 0 } } }, [GET_ITER] = { .nuops = 1, .uops = { { GET_ITER, 0, 0 } } }, [GET_YIELD_FROM_ITER] = { .nuops = 1, .uops = { { GET_YIELD_FROM_ITER, 0, 0 } } }, + [BEFORE_ASYNC_WITH] = { .nuops = 1, .uops = { { BEFORE_ASYNC_WITH, 0, 0 } } }, [WITH_EXCEPT_START] = { .nuops = 1, .uops = { { WITH_EXCEPT_START, 0, 0 } } }, [PUSH_EXC_INFO] = { .nuops = 1, .uops = { { PUSH_EXC_INFO, 0, 0 } } }, [LOAD_ATTR_METHOD_WITH_VALUES] = { .nuops = 4, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT, 0, 0 }, { _GUARD_KEYS_VERSION, 2, 3 }, { _LOAD_ATTR_METHOD_WITH_VALUES, 4, 5 } } }, @@ -2057,6 +2059,7 @@ const uint8_t _PyOpcode_Caches[256] = { [LOAD_SUPER_ATTR] = 1, [LOAD_ATTR] = 9, [COMPARE_OP] = 1, + [JUMP_BACKWARD] = 1, [POP_JUMP_IF_FALSE] = 1, [POP_JUMP_IF_TRUE] = 1, [POP_JUMP_IF_NONE] = 1, @@ -2064,7 +2067,6 @@ const uint8_t _PyOpcode_Caches[256] = { [FOR_ITER] = 1, [CALL] = 3, [BINARY_OP] = 1, - [JUMP_BACKWARD] = 1, }; #endif // NEED_OPCODE_METADATA diff --git a/Python/abstract_interp_cases.c.h b/Python/abstract_interp_cases.c.h index 232c569a3ddb300..11090ee4dba39f5 100644 --- a/Python/abstract_interp_cases.c.h +++ b/Python/abstract_interp_cases.c.h @@ -344,6 +344,10 @@ break; } + case MAKE_CELL: { + break; + } + case DELETE_DEREF: { break; } @@ -668,6 +672,13 @@ break; } + case BEFORE_ASYNC_WITH: { + STACK_GROW(1); + PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-2)), true); + PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true); + break; + } + case WITH_EXCEPT_START: { STACK_GROW(1); PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true); diff --git a/Python/bytecodes.c b/Python/bytecodes.c index d33ee3265d254d2..bb2d491523ca438 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -742,6 +742,7 @@ dummy_func( } inst(RAISE_VARARGS, (args[oparg] -- )) { + TIER_ONE_ONLY PyObject *cause = NULL, *exc = NULL; switch (oparg) { case 2: @@ -1073,6 +1074,7 @@ dummy_func( } inst(RERAISE, (values[oparg], exc -- values[oparg])) { + TIER_ONE_ONLY assert(oparg >= 0 && oparg <= 2); if (oparg) { PyObject *lasti = values[0]; @@ -1094,6 +1096,7 @@ dummy_func( } inst(END_ASYNC_FOR, (awaitable, exc -- )) { + TIER_ONE_ONLY assert(exc && PyExceptionInstance_Check(exc)); if (PyErr_GivenExceptionMatches(exc, PyExc_StopAsyncIteration)) { DECREF_INPUTS(); @@ -1107,6 +1110,7 @@ dummy_func( } inst(CLEANUP_THROW, (sub_iter, last_sent_val, exc_value -- none, value)) { + TIER_ONE_ONLY assert(throwflag); assert(exc_value && PyExceptionInstance_Check(exc_value)); if (PyErr_GivenExceptionMatches(exc_value, PyExc_StopIteration)) { @@ -1467,7 +1471,7 @@ dummy_func( PyObject *initial = GETLOCAL(oparg); PyObject *cell = PyCell_New(initial); if (cell == NULL) { - goto resume_with_error; + goto error; } SETLOCAL(oparg, cell); } @@ -2247,6 +2251,7 @@ dummy_func( } inst(IMPORT_NAME, (level, fromlist -- res)) { + TIER_ONE_ONLY PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); res = import_name(tstate, frame, name, fromlist, level); DECREF_INPUTS(); @@ -2254,6 +2259,7 @@ dummy_func( } inst(IMPORT_FROM, (from -- from, res)) { + TIER_ONE_ONLY PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); res = import_from(tstate, from, name); ERROR_IF(res == NULL, error); @@ -2263,10 +2269,10 @@ dummy_func( JUMPBY(oparg); } - inst(JUMP_BACKWARD, (--)) { + inst(JUMP_BACKWARD, (unused/1 --)) { CHECK_EVAL_BREAKER(); assert(oparg <= INSTR_OFFSET()); - JUMPBY(1-oparg); + JUMPBY(-oparg); #if ENABLE_SPECIALIZATION this_instr[1].cache += (1 << OPTIMIZER_BITS_IN_COUNTER); if (this_instr[1].cache > tstate->interp->optimizer_backedge_threshold && @@ -2297,6 +2303,7 @@ dummy_func( }; inst(ENTER_EXECUTOR, (--)) { + TIER_ONE_ONLY CHECK_EVAL_BREAKER(); PyCodeObject *code = _PyFrame_GetCode(frame); @@ -2703,6 +2710,7 @@ dummy_func( } inst(BEFORE_WITH, (mgr -- exit, res)) { + TIER_ONE_ONLY /* pop the context manager, push its __exit__ and the * value returned from calling its __enter__ */ @@ -3831,9 +3839,9 @@ dummy_func( INSTRUMENTED_JUMP(this_instr, next_instr + oparg, PY_MONITORING_EVENT_JUMP); } - inst(INSTRUMENTED_JUMP_BACKWARD, ( -- )) { + inst(INSTRUMENTED_JUMP_BACKWARD, (unused/1 -- )) { CHECK_EVAL_BREAKER(); - INSTRUMENTED_JUMP(this_instr, next_instr + 1 - oparg, PY_MONITORING_EVENT_JUMP); + INSTRUMENTED_JUMP(this_instr, next_instr - oparg, PY_MONITORING_EVENT_JUMP); } inst(INSTRUMENTED_POP_JUMP_IF_TRUE, (unused/1 -- )) { diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index 24de9eadf59048f..4d5b6dc7f01051d 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -1240,6 +1240,18 @@ break; } + case MAKE_CELL: { + // "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); + PyObject *cell = PyCell_New(initial); + if (cell == NULL) { + goto error; + } + SETLOCAL(oparg, cell); + break; + } + case DELETE_DEREF: { PyObject *cell = GETLOCAL(oparg); PyObject *oldobj = PyCell_GET(cell); @@ -2320,6 +2332,46 @@ break; } + case BEFORE_ASYNC_WITH: { + PyObject *mgr; + PyObject *exit; + PyObject *res; + mgr = stack_pointer[-1]; + PyObject *enter = _PyObject_LookupSpecial(mgr, &_Py_ID(__aenter__)); + if (enter == NULL) { + if (!_PyErr_Occurred(tstate)) { + _PyErr_Format(tstate, PyExc_TypeError, + "'%.200s' object does not support the " + "asynchronous context manager protocol", + Py_TYPE(mgr)->tp_name); + } + goto error; + } + exit = _PyObject_LookupSpecial(mgr, &_Py_ID(__aexit__)); + if (exit == NULL) { + if (!_PyErr_Occurred(tstate)) { + _PyErr_Format(tstate, PyExc_TypeError, + "'%.200s' object does not support the " + "asynchronous context manager protocol " + "(missed __aexit__ method)", + Py_TYPE(mgr)->tp_name); + } + Py_DECREF(enter); + goto error; + } + Py_DECREF(mgr); + res = _PyObject_CallNoArgs(enter); + Py_DECREF(enter); + if (res == NULL) { + Py_DECREF(exit); + if (true) goto pop_1_error; + } + STACK_GROW(1); + stack_pointer[-2] = exit; + stack_pointer[-1] = res; + break; + } + case WITH_EXCEPT_START: { PyObject *val; PyObject *lasti; diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 40c8cd8798c93b6..8b6ebe4f8ab4af6 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -1090,6 +1090,7 @@ INSTRUCTION_STATS(RAISE_VARARGS); PyObject **args; args = stack_pointer - oparg; + TIER_ONE_ONLY PyObject *cause = NULL, *exc = NULL; switch (oparg) { case 2: @@ -1532,6 +1533,7 @@ PyObject **values; exc = stack_pointer[-1]; values = stack_pointer - 1 - oparg; + TIER_ONE_ONLY assert(oparg >= 0 && oparg <= 2); if (oparg) { PyObject *lasti = values[0]; @@ -1560,6 +1562,7 @@ PyObject *awaitable; exc = stack_pointer[-1]; awaitable = stack_pointer[-2]; + TIER_ONE_ONLY assert(exc && PyExceptionInstance_Check(exc)); if (PyErr_GivenExceptionMatches(exc, PyExc_StopAsyncIteration)) { Py_DECREF(awaitable); @@ -1587,6 +1590,7 @@ exc_value = stack_pointer[-1]; last_sent_val = stack_pointer[-2]; sub_iter = stack_pointer[-3]; + TIER_ONE_ONLY assert(throwflag); assert(exc_value && PyExceptionInstance_Check(exc_value)); if (PyErr_GivenExceptionMatches(exc_value, PyExc_StopIteration)) { @@ -2107,7 +2111,7 @@ PyObject *initial = GETLOCAL(oparg); PyObject *cell = PyCell_New(initial); if (cell == NULL) { - goto resume_with_error; + goto error; } SETLOCAL(oparg, cell); DISPATCH(); @@ -3282,6 +3286,7 @@ PyObject *res; fromlist = stack_pointer[-1]; level = stack_pointer[-2]; + TIER_ONE_ONLY PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); res = import_name(tstate, frame, name, fromlist, level); Py_DECREF(level); @@ -3299,6 +3304,7 @@ PyObject *from; PyObject *res; from = stack_pointer[-1]; + TIER_ONE_ONLY PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); res = import_from(tstate, from, name); if (res == NULL) goto error; @@ -3317,11 +3323,11 @@ TARGET(JUMP_BACKWARD) { _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; - next_instr += 1; + next_instr += 2; INSTRUCTION_STATS(JUMP_BACKWARD); CHECK_EVAL_BREAKER(); assert(oparg <= INSTR_OFFSET()); - JUMPBY(1-oparg); + JUMPBY(-oparg); #if ENABLE_SPECIALIZATION this_instr[1].cache += (1 << OPTIMIZER_BITS_IN_COUNTER); if (this_instr[1].cache > tstate->interp->optimizer_backedge_threshold && @@ -3346,6 +3352,7 @@ frame->instr_ptr = next_instr; next_instr += 1; INSTRUCTION_STATS(ENTER_EXECUTOR); + TIER_ONE_ONLY CHECK_EVAL_BREAKER(); PyCodeObject *code = _PyFrame_GetCode(frame); @@ -3890,6 +3897,7 @@ PyObject *exit; PyObject *res; mgr = stack_pointer[-1]; + TIER_ONE_ONLY /* pop the context manager, push its __exit__ and the * value returned from calling its __enter__ */ @@ -5560,10 +5568,10 @@ TARGET(INSTRUMENTED_JUMP_BACKWARD) { _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; - next_instr += 1; + next_instr += 2; INSTRUCTION_STATS(INSTRUMENTED_JUMP_BACKWARD); CHECK_EVAL_BREAKER(); - INSTRUMENTED_JUMP(this_instr, next_instr + 1 - oparg, PY_MONITORING_EVENT_JUMP); + INSTRUMENTED_JUMP(this_instr, next_instr - oparg, PY_MONITORING_EVENT_JUMP); DISPATCH(); } diff --git a/Tools/cases_generator/analysis.py b/Tools/cases_generator/analysis.py index 180bd01302ec112..027d953fe47398b 100644 --- a/Tools/cases_generator/analysis.py +++ b/Tools/cases_generator/analysis.py @@ -385,12 +385,9 @@ def analyze_macro(self, macro: parsing.Macro) -> MacroInstruction: def analyze_pseudo(self, pseudo: parsing.Pseudo) -> PseudoInstruction: targets = [self.instrs[target] for target in pseudo.targets] assert targets - # Make sure the targets have the same fmt - fmts = list(set([t.instr_fmt for t in targets])) - assert len(fmts) == 1 ignored_flags = {"HAS_EVAL_BREAK_FLAG", "HAS_DEOPT_FLAG", "HAS_ERROR_FLAG"} assert len({t.instr_flags.bitmap(ignore=ignored_flags) for t in targets}) == 1 - return PseudoInstruction(pseudo.name, targets, fmts[0], targets[0].instr_flags) + return PseudoInstruction(pseudo.name, targets, targets[0].instr_flags) def analyze_instruction( self, instr: Instruction, offset: int diff --git a/Tools/cases_generator/generate_cases.py b/Tools/cases_generator/generate_cases.py index ef96ed3748b056e..ed4fc8d6130cec0 100644 --- a/Tools/cases_generator/generate_cases.py +++ b/Tools/cases_generator/generate_cases.py @@ -395,13 +395,9 @@ def write_metadata(self, metadata_filename: str, pymetadata_filename: str) -> No case parsing.Macro(): format = self.macro_instrs[thing.name].instr_fmt case parsing.Pseudo(): - for target in self.pseudos[thing.name].targets: - target_instr = self.instrs.get(target) - assert target_instr - if format is None: - format = target_instr.instr_fmt - else: - assert format == target_instr.instr_fmt + # Pseudo instructions exist only in the compiler, + # so do not have a format + continue case _: assert_never(thing) assert format is not None @@ -464,12 +460,12 @@ def write_metadata(self, metadata_filename: str, pymetadata_filename: str) -> No self.out.emit("") self.out.emit( - "#define OPCODE_METADATA_FMT(OP) " - "(_PyOpcode_opcode_metadata[(OP)].instr_format)" + "#define OPCODE_METADATA_FLAGS(OP) " + "(_PyOpcode_opcode_metadata[(OP)].flags & (HAS_ARG_FLAG | HAS_JUMP_FLAG))" ) self.out.emit("#define SAME_OPCODE_METADATA(OP1, OP2) \\") self.out.emit( - " (OPCODE_METADATA_FMT(OP1) == OPCODE_METADATA_FMT(OP2))" + " (OPCODE_METADATA_FLAGS(OP1) == OPCODE_METADATA_FLAGS(OP2))" ) self.out.emit("") @@ -545,8 +541,6 @@ def write_metadata(self, metadata_filename: str, pymetadata_filename: str) -> No and not mac.name.startswith("INSTRUMENTED_") ): self.out.emit(f"[{mac.name}] = {mac.cache_offset},") - # Irregular case: - self.out.emit("[JUMP_BACKWARD] = 1,") deoptcodes = {} for name, op in self.opmap.items(): @@ -732,12 +726,13 @@ def write_expansions( f"{{ .nuops = {len(pieces)}, .uops = {{ {', '.join(pieces)} }} }}," ) - def emit_metadata_entry(self, name: str, fmt: str, flags: InstructionFlags) -> None: + def emit_metadata_entry(self, name: str, fmt: str | None, flags: InstructionFlags) -> None: flag_names = flags.names(value=True) if not flag_names: flag_names.append("0") + fmt_macro = "0" if fmt is None else INSTR_FMT_PREFIX + fmt self.out.emit( - f"[{name}] = {{ true, {INSTR_FMT_PREFIX}{fmt}," + f"[{name}] = {{ true, {fmt_macro}," f" {' | '.join(flag_names)} }}," ) @@ -751,7 +746,7 @@ def write_metadata_for_macro(self, mac: MacroInstruction) -> None: def write_metadata_for_pseudo(self, ps: PseudoInstruction) -> None: """Write metadata for a macro-instruction.""" - self.emit_metadata_entry(ps.name, ps.instr_fmt, ps.instr_flags) + self.emit_metadata_entry(ps.name, None, ps.instr_flags) def write_instructions( self, output_filename: str, emit_line_directives: bool diff --git a/Tools/cases_generator/instructions.py b/Tools/cases_generator/instructions.py index e9ed2a867ae2b3d..636a6beb818a1d3 100644 --- a/Tools/cases_generator/instructions.py +++ b/Tools/cases_generator/instructions.py @@ -25,18 +25,10 @@ class ActiveCacheEffect: FORBIDDEN_NAMES_IN_UOPS = ( - "resume_with_error", - "kwnames", "next_instr", "oparg1", # Proxy for super-instructions like LOAD_FAST_LOAD_FAST "JUMPBY", "DISPATCH", - "INSTRUMENTED_JUMP", - "throwflag", - "exception_unwind", - "import_from", - "import_name", - "_PyObject_CallNoArgs", # Proxy for BEFORE_WITH "TIER_ONE_ONLY", ) @@ -294,7 +286,6 @@ class PseudoInstruction: name: str targets: list[Instruction] - instr_fmt: str instr_flags: InstructionFlags