diff --git a/Lib/test/test_capi/test_misc.py b/Lib/test/test_capi/test_misc.py index fd27bd06097f6a..9cbd5506bf6dea 100644 --- a/Lib/test/test_capi/test_misc.py +++ b/Lib/test/test_capi/test_misc.py @@ -2525,7 +2525,6 @@ def testfunc(n): i += 1 opt = _testinternalcapi.get_uop_optimizer() - with temporary_optimizer(opt): testfunc(10) @@ -2541,7 +2540,6 @@ def testfunc(n): i += 1 opt = _testinternalcapi.get_uop_optimizer() - with temporary_optimizer(opt): testfunc(10) @@ -2550,6 +2548,20 @@ def testfunc(n): uops = {opname for opname, _ in ex} self.assertIn("_POP_JUMP_IF_TRUE", uops) + def test_jump_backward(self): + def testfunc(n): + i = 0 + while i < n: + i += 1 + opt = _testinternalcapi.get_uop_optimizer() + with temporary_optimizer(opt): + testfunc(10) + + ex = get_first_executor(testfunc) + self.assertIsNotNone(ex) + uops = {opname for opname, _ in ex} + self.assertIn("JUMP_TO_TOP", uops) + if __name__ == "__main__": unittest.main() diff --git a/Python/ceval.c b/Python/ceval.c index 866acd2dd69c7e..57e478c1313f64 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2783,6 +2783,13 @@ _PyUopExecute(_PyExecutorObject *executor, _PyInterpreterFrame *frame, PyObject break; } + case JUMP_TO_TOP: + { + pc = 0; + CHECK_EVAL_BREAKER(); + break; + } + case SAVE_IP: { frame->prev_instr = ip_offset + oparg; diff --git a/Python/opcode_metadata.h b/Python/opcode_metadata.h index 34ac85d6517a88..4a41cd86a4287b 100644 --- a/Python/opcode_metadata.h +++ b/Python/opcode_metadata.h @@ -23,19 +23,20 @@ #define SAVE_IP 301 #define _POP_JUMP_IF_FALSE 302 #define _POP_JUMP_IF_TRUE 303 -#define _GUARD_BOTH_INT 304 -#define _BINARY_OP_MULTIPLY_INT 305 -#define _BINARY_OP_ADD_INT 306 -#define _BINARY_OP_SUBTRACT_INT 307 -#define _GUARD_BOTH_FLOAT 308 -#define _BINARY_OP_MULTIPLY_FLOAT 309 -#define _BINARY_OP_ADD_FLOAT 310 -#define _BINARY_OP_SUBTRACT_FLOAT 311 -#define _GUARD_BOTH_UNICODE 312 -#define _BINARY_OP_ADD_UNICODE 313 -#define _LOAD_LOCALS 314 -#define _LOAD_FROM_DICT_OR_GLOBALS 315 -#define IS_NONE 316 +#define JUMP_TO_TOP 304 +#define _GUARD_BOTH_INT 305 +#define _BINARY_OP_MULTIPLY_INT 306 +#define _BINARY_OP_ADD_INT 307 +#define _BINARY_OP_SUBTRACT_INT 308 +#define _GUARD_BOTH_FLOAT 309 +#define _BINARY_OP_MULTIPLY_FLOAT 310 +#define _BINARY_OP_ADD_FLOAT 311 +#define _BINARY_OP_SUBTRACT_FLOAT 312 +#define _GUARD_BOTH_UNICODE 313 +#define _BINARY_OP_ADD_UNICODE 314 +#define _LOAD_LOCALS 315 +#define _LOAD_FROM_DICT_OR_GLOBALS 316 +#define IS_NONE 317 #ifndef NEED_OPCODE_METADATA extern int _PyOpcode_num_popped(int opcode, int oparg, bool jump); @@ -1298,18 +1299,19 @@ const char * const _PyOpcode_uop_name[512] = { [301] = "SAVE_IP", [302] = "_POP_JUMP_IF_FALSE", [303] = "_POP_JUMP_IF_TRUE", - [304] = "_GUARD_BOTH_INT", - [305] = "_BINARY_OP_MULTIPLY_INT", - [306] = "_BINARY_OP_ADD_INT", - [307] = "_BINARY_OP_SUBTRACT_INT", - [308] = "_GUARD_BOTH_FLOAT", - [309] = "_BINARY_OP_MULTIPLY_FLOAT", - [310] = "_BINARY_OP_ADD_FLOAT", - [311] = "_BINARY_OP_SUBTRACT_FLOAT", - [312] = "_GUARD_BOTH_UNICODE", - [313] = "_BINARY_OP_ADD_UNICODE", - [314] = "_LOAD_LOCALS", - [315] = "_LOAD_FROM_DICT_OR_GLOBALS", - [316] = "IS_NONE", + [304] = "JUMP_TO_TOP", + [305] = "_GUARD_BOTH_INT", + [306] = "_BINARY_OP_MULTIPLY_INT", + [307] = "_BINARY_OP_ADD_INT", + [308] = "_BINARY_OP_SUBTRACT_INT", + [309] = "_GUARD_BOTH_FLOAT", + [310] = "_BINARY_OP_MULTIPLY_FLOAT", + [311] = "_BINARY_OP_ADD_FLOAT", + [312] = "_BINARY_OP_SUBTRACT_FLOAT", + [313] = "_GUARD_BOTH_UNICODE", + [314] = "_BINARY_OP_ADD_UNICODE", + [315] = "_LOAD_LOCALS", + [316] = "_LOAD_FROM_DICT_OR_GLOBALS", + [317] = "IS_NONE", }; #endif // NEED_OPCODE_METADATA diff --git a/Python/optimizer.c b/Python/optimizer.c index 08073193c0228f..8d4162b44c2f35 100644 --- a/Python/optimizer.c +++ b/Python/optimizer.c @@ -372,9 +372,7 @@ translate_bytecode_to_trace( _PyUOpInstruction *trace, int buffer_size) { -#ifdef Py_DEBUG _Py_CODEUNIT *initial_instr = instr; -#endif int trace_length = 0; int max_length = buffer_size; @@ -456,6 +454,19 @@ translate_bytecode_to_trace( break; } + case JUMP_BACKWARD: + { + if (instr + 2 - oparg == initial_instr + && trace_length + 3 <= max_length) + { + ADD_TO_TRACE(JUMP_TO_TOP, 0); + } + else { + DPRINTF(2, "JUMP_BACKWARD not to top ends trace\n"); + } + goto done; + } + default: { const struct opcode_macro_expansion *expansion = &_PyOpcode_macro_expansion[opcode]; diff --git a/Tools/cases_generator/generate_cases.py b/Tools/cases_generator/generate_cases.py index 641a327b06aa22..8c77c1f08335df 100644 --- a/Tools/cases_generator/generate_cases.py +++ b/Tools/cases_generator/generate_cases.py @@ -1346,6 +1346,7 @@ def add(name: str) -> None: add("SAVE_IP") add("_POP_JUMP_IF_FALSE") add("_POP_JUMP_IF_TRUE") + add("JUMP_TO_TOP") for instr in self.instrs.values(): if instr.kind == "op" and instr.is_viable_uop():