From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com> Date: Fri, 17 Oct 2025 23:47:16 +0000 (+0100) Subject: fix a few tests and their exposed bugs X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5102ab6028fba189ffb7f409046ab125381a5503;p=thirdparty%2FPython%2Fcpython.git fix a few tests and their exposed bugs --- diff --git a/Include/internal/pycore_opcode_metadata.h b/Include/internal/pycore_opcode_metadata.h index b96033eadf90..477553e2563f 100644 --- a/Include/internal/pycore_opcode_metadata.h +++ b/Include/internal/pycore_opcode_metadata.h @@ -1778,6 +1778,7 @@ const uint8_t _PyOpcode_NeedsGuardIp[256] = { [RETURN_VALUE] = 1, [YIELD_VALUE] = 1, [JUMP_FORWARD] = 1, + [JUMP_BACKWARD_NO_INTERRUPT] = 1, [INSTRUMENTED_FOR_ITER] = 1, [RETURN_GENERATOR] = 1, [BINARY_OP_SUBSCR_GETITEM] = 1, @@ -1795,7 +1796,6 @@ const uint8_t _PyOpcode_NeedsGuardIp[256] = { [POP_JUMP_IF_FALSE] = 1, [POP_JUMP_IF_NONE] = 1, [POP_JUMP_IF_NOT_NONE] = 1, - [JUMP_BACKWARD_NO_INTERRUPT] = 1, [FOR_ITER] = 1, [FOR_ITER_LIST] = 1, [FOR_ITER_TUPLE] = 1, diff --git a/Include/internal/pycore_uop_ids.h b/Include/internal/pycore_uop_ids.h index 2ef1fccc8d8e..9f4ae71a313a 100644 --- a/Include/internal/pycore_uop_ids.h +++ b/Include/internal/pycore_uop_ids.h @@ -199,166 +199,166 @@ extern "C" { #define _ITER_NEXT_LIST_TIER_TWO 442 #define _ITER_NEXT_RANGE 443 #define _ITER_NEXT_TUPLE 444 -#define _JUMP_BACKWARD_NO_INTERRUPT 445 -#define _JUMP_TO_TOP 446 +#define _JUMP_BACKWARD_NO_INTERRUPT JUMP_BACKWARD_NO_INTERRUPT +#define _JUMP_TO_TOP 445 #define _LIST_APPEND LIST_APPEND #define _LIST_EXTEND LIST_EXTEND -#define _LOAD_ATTR 447 -#define _LOAD_ATTR_CLASS 448 +#define _LOAD_ATTR 446 +#define _LOAD_ATTR_CLASS 447 #define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN -#define _LOAD_ATTR_INSTANCE_VALUE 449 -#define _LOAD_ATTR_METHOD_LAZY_DICT 450 -#define _LOAD_ATTR_METHOD_NO_DICT 451 -#define _LOAD_ATTR_METHOD_WITH_VALUES 452 -#define _LOAD_ATTR_MODULE 453 -#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 454 -#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 455 -#define _LOAD_ATTR_PROPERTY_FRAME 456 -#define _LOAD_ATTR_SLOT 457 -#define _LOAD_ATTR_WITH_HINT 458 +#define _LOAD_ATTR_INSTANCE_VALUE 448 +#define _LOAD_ATTR_METHOD_LAZY_DICT 449 +#define _LOAD_ATTR_METHOD_NO_DICT 450 +#define _LOAD_ATTR_METHOD_WITH_VALUES 451 +#define _LOAD_ATTR_MODULE 452 +#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 453 +#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 454 +#define _LOAD_ATTR_PROPERTY_FRAME 455 +#define _LOAD_ATTR_SLOT 456 +#define _LOAD_ATTR_WITH_HINT 457 #define _LOAD_BUILD_CLASS LOAD_BUILD_CLASS -#define _LOAD_BYTECODE 459 +#define _LOAD_BYTECODE 458 #define _LOAD_COMMON_CONSTANT LOAD_COMMON_CONSTANT #define _LOAD_CONST LOAD_CONST -#define _LOAD_CONST_INLINE 460 -#define _LOAD_CONST_INLINE_BORROW 461 -#define _LOAD_CONST_UNDER_INLINE 462 -#define _LOAD_CONST_UNDER_INLINE_BORROW 463 +#define _LOAD_CONST_INLINE 459 +#define _LOAD_CONST_INLINE_BORROW 460 +#define _LOAD_CONST_UNDER_INLINE 461 +#define _LOAD_CONST_UNDER_INLINE_BORROW 462 #define _LOAD_DEREF LOAD_DEREF -#define _LOAD_FAST 464 -#define _LOAD_FAST_0 465 -#define _LOAD_FAST_1 466 -#define _LOAD_FAST_2 467 -#define _LOAD_FAST_3 468 -#define _LOAD_FAST_4 469 -#define _LOAD_FAST_5 470 -#define _LOAD_FAST_6 471 -#define _LOAD_FAST_7 472 +#define _LOAD_FAST 463 +#define _LOAD_FAST_0 464 +#define _LOAD_FAST_1 465 +#define _LOAD_FAST_2 466 +#define _LOAD_FAST_3 467 +#define _LOAD_FAST_4 468 +#define _LOAD_FAST_5 469 +#define _LOAD_FAST_6 470 +#define _LOAD_FAST_7 471 #define _LOAD_FAST_AND_CLEAR LOAD_FAST_AND_CLEAR -#define _LOAD_FAST_BORROW 473 -#define _LOAD_FAST_BORROW_0 474 -#define _LOAD_FAST_BORROW_1 475 -#define _LOAD_FAST_BORROW_2 476 -#define _LOAD_FAST_BORROW_3 477 -#define _LOAD_FAST_BORROW_4 478 -#define _LOAD_FAST_BORROW_5 479 -#define _LOAD_FAST_BORROW_6 480 -#define _LOAD_FAST_BORROW_7 481 +#define _LOAD_FAST_BORROW 472 +#define _LOAD_FAST_BORROW_0 473 +#define _LOAD_FAST_BORROW_1 474 +#define _LOAD_FAST_BORROW_2 475 +#define _LOAD_FAST_BORROW_3 476 +#define _LOAD_FAST_BORROW_4 477 +#define _LOAD_FAST_BORROW_5 478 +#define _LOAD_FAST_BORROW_6 479 +#define _LOAD_FAST_BORROW_7 480 #define _LOAD_FAST_BORROW_LOAD_FAST_BORROW LOAD_FAST_BORROW_LOAD_FAST_BORROW #define _LOAD_FAST_CHECK LOAD_FAST_CHECK #define _LOAD_FAST_LOAD_FAST LOAD_FAST_LOAD_FAST #define _LOAD_FROM_DICT_OR_DEREF LOAD_FROM_DICT_OR_DEREF #define _LOAD_FROM_DICT_OR_GLOBALS LOAD_FROM_DICT_OR_GLOBALS -#define _LOAD_GLOBAL 482 -#define _LOAD_GLOBAL_BUILTINS 483 -#define _LOAD_GLOBAL_MODULE 484 +#define _LOAD_GLOBAL 481 +#define _LOAD_GLOBAL_BUILTINS 482 +#define _LOAD_GLOBAL_MODULE 483 #define _LOAD_LOCALS LOAD_LOCALS #define _LOAD_NAME LOAD_NAME -#define _LOAD_SMALL_INT 485 -#define _LOAD_SMALL_INT_0 486 -#define _LOAD_SMALL_INT_1 487 -#define _LOAD_SMALL_INT_2 488 -#define _LOAD_SMALL_INT_3 489 -#define _LOAD_SPECIAL 490 +#define _LOAD_SMALL_INT 484 +#define _LOAD_SMALL_INT_0 485 +#define _LOAD_SMALL_INT_1 486 +#define _LOAD_SMALL_INT_2 487 +#define _LOAD_SMALL_INT_3 488 +#define _LOAD_SPECIAL 489 #define _LOAD_SUPER_ATTR_ATTR LOAD_SUPER_ATTR_ATTR #define _LOAD_SUPER_ATTR_METHOD LOAD_SUPER_ATTR_METHOD -#define _MAKE_CALLARGS_A_TUPLE 491 +#define _MAKE_CALLARGS_A_TUPLE 490 #define _MAKE_CELL MAKE_CELL #define _MAKE_FUNCTION MAKE_FUNCTION -#define _MAKE_WARM 492 +#define _MAKE_WARM 491 #define _MAP_ADD MAP_ADD #define _MATCH_CLASS MATCH_CLASS #define _MATCH_KEYS MATCH_KEYS #define _MATCH_MAPPING MATCH_MAPPING #define _MATCH_SEQUENCE MATCH_SEQUENCE -#define _MAYBE_EXPAND_METHOD 493 -#define _MAYBE_EXPAND_METHOD_KW 494 -#define _MONITOR_CALL 495 -#define _MONITOR_CALL_KW 496 -#define _MONITOR_JUMP_BACKWARD 497 -#define _MONITOR_RESUME 498 +#define _MAYBE_EXPAND_METHOD 492 +#define _MAYBE_EXPAND_METHOD_KW 493 +#define _MONITOR_CALL 494 +#define _MONITOR_CALL_KW 495 +#define _MONITOR_JUMP_BACKWARD 496 +#define _MONITOR_RESUME 497 #define _NOP NOP -#define _POP_CALL 499 -#define _POP_CALL_LOAD_CONST_INLINE_BORROW 500 -#define _POP_CALL_ONE 501 -#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW 502 -#define _POP_CALL_TWO 503 -#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW 504 +#define _POP_CALL 498 +#define _POP_CALL_LOAD_CONST_INLINE_BORROW 499 +#define _POP_CALL_ONE 500 +#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW 501 +#define _POP_CALL_TWO 502 +#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW 503 #define _POP_EXCEPT POP_EXCEPT #define _POP_ITER POP_ITER -#define _POP_JUMP_IF_FALSE 505 -#define _POP_JUMP_IF_TRUE 506 +#define _POP_JUMP_IF_FALSE 504 +#define _POP_JUMP_IF_TRUE 505 #define _POP_TOP POP_TOP -#define _POP_TOP_FLOAT 507 -#define _POP_TOP_INT 508 -#define _POP_TOP_LOAD_CONST_INLINE 509 -#define _POP_TOP_LOAD_CONST_INLINE_BORROW 510 -#define _POP_TOP_NOP 511 -#define _POP_TOP_UNICODE 512 -#define _POP_TWO 513 -#define _POP_TWO_LOAD_CONST_INLINE_BORROW 514 +#define _POP_TOP_FLOAT 506 +#define _POP_TOP_INT 507 +#define _POP_TOP_LOAD_CONST_INLINE 508 +#define _POP_TOP_LOAD_CONST_INLINE_BORROW 509 +#define _POP_TOP_NOP 510 +#define _POP_TOP_UNICODE 511 +#define _POP_TWO 512 +#define _POP_TWO_LOAD_CONST_INLINE_BORROW 513 #define _PUSH_EXC_INFO PUSH_EXC_INFO -#define _PUSH_FRAME 515 +#define _PUSH_FRAME 514 #define _PUSH_NULL PUSH_NULL -#define _PUSH_NULL_CONDITIONAL 516 -#define _PY_FRAME_GENERAL 517 -#define _PY_FRAME_KW 518 -#define _QUICKEN_RESUME 519 -#define _REPLACE_WITH_TRUE 520 +#define _PUSH_NULL_CONDITIONAL 515 +#define _PY_FRAME_GENERAL 516 +#define _PY_FRAME_KW 517 +#define _QUICKEN_RESUME 518 +#define _REPLACE_WITH_TRUE 519 #define _RESUME_CHECK RESUME_CHECK #define _RETURN_GENERATOR RETURN_GENERATOR #define _RETURN_VALUE RETURN_VALUE -#define _SAVE_RETURN_OFFSET 521 -#define _SEND 522 -#define _SEND_GEN_FRAME 523 +#define _SAVE_RETURN_OFFSET 520 +#define _SEND 521 +#define _SEND_GEN_FRAME 522 #define _SETUP_ANNOTATIONS SETUP_ANNOTATIONS #define _SET_ADD SET_ADD #define _SET_FUNCTION_ATTRIBUTE SET_FUNCTION_ATTRIBUTE #define _SET_UPDATE SET_UPDATE -#define _START_EXECUTOR 524 -#define _STORE_ATTR 525 -#define _STORE_ATTR_INSTANCE_VALUE 526 -#define _STORE_ATTR_SLOT 527 -#define _STORE_ATTR_WITH_HINT 528 +#define _START_EXECUTOR 523 +#define _STORE_ATTR 524 +#define _STORE_ATTR_INSTANCE_VALUE 525 +#define _STORE_ATTR_SLOT 526 +#define _STORE_ATTR_WITH_HINT 527 #define _STORE_DEREF STORE_DEREF -#define _STORE_FAST 529 -#define _STORE_FAST_0 530 -#define _STORE_FAST_1 531 -#define _STORE_FAST_2 532 -#define _STORE_FAST_3 533 -#define _STORE_FAST_4 534 -#define _STORE_FAST_5 535 -#define _STORE_FAST_6 536 -#define _STORE_FAST_7 537 +#define _STORE_FAST 528 +#define _STORE_FAST_0 529 +#define _STORE_FAST_1 530 +#define _STORE_FAST_2 531 +#define _STORE_FAST_3 532 +#define _STORE_FAST_4 533 +#define _STORE_FAST_5 534 +#define _STORE_FAST_6 535 +#define _STORE_FAST_7 536 #define _STORE_FAST_LOAD_FAST STORE_FAST_LOAD_FAST #define _STORE_FAST_STORE_FAST STORE_FAST_STORE_FAST #define _STORE_GLOBAL STORE_GLOBAL #define _STORE_NAME STORE_NAME -#define _STORE_SLICE 538 -#define _STORE_SUBSCR 539 -#define _STORE_SUBSCR_DICT 540 -#define _STORE_SUBSCR_LIST_INT 541 -#define _SWAP 542 -#define _SWAP_2 543 -#define _SWAP_3 544 -#define _TIER2_RESUME_CHECK 545 -#define _TO_BOOL 546 +#define _STORE_SLICE 537 +#define _STORE_SUBSCR 538 +#define _STORE_SUBSCR_DICT 539 +#define _STORE_SUBSCR_LIST_INT 540 +#define _SWAP 541 +#define _SWAP_2 542 +#define _SWAP_3 543 +#define _TIER2_RESUME_CHECK 544 +#define _TO_BOOL 545 #define _TO_BOOL_BOOL TO_BOOL_BOOL #define _TO_BOOL_INT TO_BOOL_INT -#define _TO_BOOL_LIST 547 +#define _TO_BOOL_LIST 546 #define _TO_BOOL_NONE TO_BOOL_NONE -#define _TO_BOOL_STR 548 +#define _TO_BOOL_STR 547 #define _UNARY_INVERT UNARY_INVERT #define _UNARY_NEGATIVE UNARY_NEGATIVE #define _UNARY_NOT UNARY_NOT #define _UNPACK_EX UNPACK_EX -#define _UNPACK_SEQUENCE 549 -#define _UNPACK_SEQUENCE_LIST 550 -#define _UNPACK_SEQUENCE_TUPLE 551 -#define _UNPACK_SEQUENCE_TWO_TUPLE 552 +#define _UNPACK_SEQUENCE 548 +#define _UNPACK_SEQUENCE_LIST 549 +#define _UNPACK_SEQUENCE_TUPLE 550 +#define _UNPACK_SEQUENCE_TWO_TUPLE 551 #define _WITH_EXCEPT_START WITH_EXCEPT_START #define _YIELD_VALUE YIELD_VALUE -#define MAX_UOP_ID 552 +#define MAX_UOP_ID 551 #ifdef __cplusplus } diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py index 3cc8fbe0de0a..842a328f5d83 100644 --- a/Lib/test/test_capi/test_opt.py +++ b/Lib/test/test_capi/test_opt.py @@ -17,8 +17,6 @@ _testinternalcapi = import_helper.import_module("_testinternalcapi") from _testinternalcapi import TIER2_THRESHOLD -# We need one more iteration as one iteration is spent on tracing. -TIER2_THRESHOLD = TIER2_THRESHOLD + 1 #For test of issue 136154 GLOBAL_136154 = 42 @@ -628,7 +626,7 @@ class TestUopsOptimization(unittest.TestCase): x = range(i) return x - testfunc(_testinternalcapi.TIER2_THRESHOLD + 1) + testfunc(_testinternalcapi.TIER2_THRESHOLD) ex = get_first_executor(testfunc) assert ex is not None @@ -2463,7 +2461,7 @@ class TestUopsOptimization(unittest.TestCase): del email.jit_testing - testfunc(_testinternalcapi.TIER2_THRESHOLD + 1) + testfunc(_testinternalcapi.TIER2_THRESHOLD) ex = get_first_executor(testfunc) assert ex is not None """)) diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index 1198c6d35113..98dd466849e5 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -2252,9 +2252,10 @@ class TestSysJIT(unittest.TestCase): def frame_3_jit() -> None: # JITs just before the last loop: - for i in range(_testinternalcapi.TIER2_THRESHOLD + 1): + # 1 extra iteration for tracing. + for i in range(_testinternalcapi.TIER2_THRESHOLD + 2): # Careful, doing this in the reverse order breaks tracing: - expected = {enabled} and i == _testinternalcapi.TIER2_THRESHOLD + expected = {enabled} and i >= _testinternalcapi.TIER2_THRESHOLD + 1 assert sys._jit.is_active() is expected frame_2_jit(expected) assert sys._jit.is_active() is expected diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c index 7aa63f913af3..158ffb5b9d80 100644 --- a/Modules/_testinternalcapi.c +++ b/Modules/_testinternalcapi.c @@ -2543,7 +2543,8 @@ module_exec(PyObject *module) } if (PyModule_Add(module, "TIER2_THRESHOLD", - PyLong_FromLong(JUMP_BACKWARD_INITIAL_VALUE + 1)) < 0) { + // + 1 more due to one loop spent on tracing. + PyLong_FromLong(JUMP_BACKWARD_INITIAL_VALUE + 2)) < 0) { return 1; } diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 5ab80565d6d4..a4a75008c66c 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -2993,17 +2993,17 @@ dummy_func( unused/1 + _SPECIALIZE_JUMP_BACKWARD + _CHECK_PERIODIC + - _JUMP_BACKWARD_NO_INTERRUPT; + JUMP_BACKWARD_NO_INTERRUPT; macro(JUMP_BACKWARD_NO_JIT) = unused/1 + _CHECK_PERIODIC + - _JUMP_BACKWARD_NO_INTERRUPT; + JUMP_BACKWARD_NO_INTERRUPT; macro(JUMP_BACKWARD_JIT) = unused/1 + _CHECK_PERIODIC + - _JUMP_BACKWARD_NO_INTERRUPT + + JUMP_BACKWARD_NO_INTERRUPT + _JIT; pseudo(JUMP, (--)) = { @@ -3088,10 +3088,7 @@ dummy_func( macro(POP_JUMP_IF_NOT_NONE) = unused/1 + _IS_NONE + _POP_JUMP_IF_FALSE; - // This actually has 1 cache entry, but for some reason it's not factored in the oparg. - macro(JUMP_BACKWARD_NO_INTERRUPT) = _JUMP_BACKWARD_NO_INTERRUPT; - - op(_JUMP_BACKWARD_NO_INTERRUPT, (--)) { + inst(JUMP_BACKWARD_NO_INTERRUPT, (--)) { /* This bytecode is used in the `yield from` or `await` loop. * If there is an interrupt, we want it handled in the innermost * generator or coroutine, so we deliberately do not check it here. @@ -5431,31 +5428,29 @@ dummy_func( tier2 op(_COLD_EXIT, ( -- )) { _PyExitData *exit = tstate->jit_exit; assert(exit != NULL); - _Py_CODEUNIT *target = (_PyFrame_GetBytecode(frame) + exit->target); + _Py_CODEUNIT *target = _PyFrame_GetBytecode(frame) + exit->target; _Py_BackoffCounter temperature = exit->temperature; + if (!backoff_counter_triggers(temperature)) { + exit->temperature = advance_backoff_counter(temperature); + GOTO_TIER_ONE(target, 0); + } + _PyExecutorObject *executor; if (target->op.code == ENTER_EXECUTOR) { PyCodeObject *code = _PyFrame_GetCode(frame); - _PyExecutorObject *executor = code->co_executors->executors[target->op.arg]; + executor = code->co_executors->executors[target->op.arg]; Py_INCREF(executor); - assert(tstate->jit_exit == exit); - exit->executor = executor; - TIER2_TO_TIER2(exit->executor); } else { - if (frame->owner >= FRAME_OWNED_BY_INTERPRETER) { - GOTO_TIER_ONE(target, 0); - } - if (!backoff_counter_triggers(temperature)) { - exit->temperature = advance_backoff_counter(temperature); - GOTO_TIER_ONE(target, 0); - } - exit->temperature = initial_temperature_backoff_counter(); _PyExecutorObject *previous_executor = _PyExecutor_FromExit(exit); assert(tstate->current_executor == (PyObject *)previous_executor); int chain_depth = previous_executor->vm_data.chain_depth + 1; _PyJIT_InitializeTracing(tstate, frame, target, STACK_LEVEL(), chain_depth, exit); + exit->temperature = initial_temperature_backoff_counter(); GOTO_TIER_ONE(target, 1); } + assert(tstate->jit_exit == exit); + exit->executor = executor; + TIER2_TO_TIER2(exit->executor); } tier2 op(_GUARD_IP, (ip/4 --)) { @@ -5494,8 +5489,6 @@ dummy_func( GOTO_TIER_ONE(target, 0); } exit->temperature = initial_temperature_backoff_counter(); - _PyExecutorObject *previous_executor = _PyExecutor_FromExit(exit); - assert(tstate->current_executor == (PyObject *)previous_executor); _PyJIT_InitializeTracing(tstate, frame, target, STACK_LEVEL(), 0, NULL); GOTO_TIER_ONE(target, 1); } diff --git a/Python/ceval.c b/Python/ceval.c index 035a22615ca9..844ca4297f41 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1054,10 +1054,8 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int _Py_CODEUNIT *next_instr; _PyStackRef *stack_pointer; entry.stack[0] = PyStackRef_NULL; - entry.frame.f_funcobj = PyStackRef_None; -#ifdef Py_STACKREF_DEBUG - entry.frame.f_funcobj = PyStackRef_None; -#elif defined(Py_DEBUG) + entry.frame.f_funcobj = PyStackRef_NULL; +#if defined(Py_DEBUG) /* Set these to invalid but identifiable values for debugging. */ entry.frame.f_locals = (PyObject*)0xaaa1; entry.frame.frame_obj = (PyFrameObject*)0xaaa2; diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index f13baadd3bc7..0a664209830f 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -7487,31 +7487,29 @@ case _COLD_EXIT: { _PyExitData *exit = tstate->jit_exit; assert(exit != NULL); - _Py_CODEUNIT *target = (_PyFrame_GetBytecode(frame) + exit->target); + _Py_CODEUNIT *target = _PyFrame_GetBytecode(frame) + exit->target; _Py_BackoffCounter temperature = exit->temperature; + if (!backoff_counter_triggers(temperature)) { + exit->temperature = advance_backoff_counter(temperature); + GOTO_TIER_ONE(target, 0); + } + _PyExecutorObject *executor; if (target->op.code == ENTER_EXECUTOR) { PyCodeObject *code = _PyFrame_GetCode(frame); - _PyExecutorObject *executor = code->co_executors->executors[target->op.arg]; + executor = code->co_executors->executors[target->op.arg]; Py_INCREF(executor); - assert(tstate->jit_exit == exit); - exit->executor = executor; - TIER2_TO_TIER2(exit->executor); } else { - if (frame->owner >= FRAME_OWNED_BY_INTERPRETER) { - GOTO_TIER_ONE(target, 0); - } - if (!backoff_counter_triggers(temperature)) { - exit->temperature = advance_backoff_counter(temperature); - GOTO_TIER_ONE(target, 0); - } - exit->temperature = initial_temperature_backoff_counter(); _PyExecutorObject *previous_executor = _PyExecutor_FromExit(exit); assert(tstate->current_executor == (PyObject *)previous_executor); int chain_depth = previous_executor->vm_data.chain_depth + 1; _PyJIT_InitializeTracing(tstate, frame, target, STACK_LEVEL(), chain_depth, exit); + exit->temperature = initial_temperature_backoff_counter(); GOTO_TIER_ONE(target, 1); } + assert(tstate->jit_exit == exit); + exit->executor = executor; + TIER2_TO_TIER2(exit->executor); break; } @@ -7557,8 +7555,6 @@ GOTO_TIER_ONE(target, 0); } exit->temperature = initial_temperature_backoff_counter(); - _PyExecutorObject *previous_executor = _PyExecutor_FromExit(exit); - assert(tstate->current_executor == (PyObject *)previous_executor); _PyJIT_InitializeTracing(tstate, frame, target, STACK_LEVEL(), 0, NULL); GOTO_TIER_ONE(target, 1); } diff --git a/Python/optimizer.c b/Python/optimizer.c index 77f7dee553f3..5d75a87ee0de 100644 --- a/Python/optimizer.c +++ b/Python/optimizer.c @@ -128,7 +128,8 @@ _PyOptimizer_Optimize( // make progress in order to avoid infinite loops or excessively-long // side-exit chains. We can only insert the executor into the bytecode if // this is true, since a deopt won't infinitely re-enter the executor: - bool progress_needed = (chain_depth % MAX_CHAIN_DEPTH) == 0; + chain_depth %= MAX_CHAIN_DEPTH; + bool progress_needed = chain_depth == 0; PyCodeObject *code = (PyCodeObject *)tstate->interp->jit_tracer_initial_code; _Py_CODEUNIT *start = tstate->interp->jit_tracer_initial_instr; // A recursive trace might've cleared the values. In that case, bail. @@ -559,8 +560,8 @@ _PyJIT_translate_single_bytecode_to_trace( int oparg, int jump_taken) { - if (Py_IsNone((PyObject *)func)) { - func = NULL; + if (PyStackRef_IsNull(frame->f_funcobj)) { + goto unsupported; } int is_first_instr = tstate->interp->jit_tracer_initial_instr == this_instr; @@ -596,6 +597,11 @@ _PyJIT_translate_single_bytecode_to_trace( (frame != tstate->interp->jit_tracer_current_frame && !needs_guard_ip) || // TODO handle extended args. oparg > 255 || opcode == EXTENDED_ARG || + // TODO handle BINARY_OP_INPLACE_ADD_UNICODE + opcode == BINARY_OP_INPLACE_ADD_UNICODE || + // TODO (gh-140277): The constituent uops are invalid. + opcode == BINARY_OP_SUBSCR_GETITEM || + // Exception stuff, could be handled in the future maybe? opcode == WITH_EXCEPT_START || opcode == RERAISE || opcode == CLEANUP_THROW || opcode == PUSH_EXC_INFO || frame->owner >= FRAME_OWNED_BY_INTERPRETER ) { @@ -603,12 +609,19 @@ _PyJIT_translate_single_bytecode_to_trace( { // Rewind to previous instruction and replace with _EXIT_TRACE. _PyUOpInstruction *curr = &trace[trace_length-1]; - while (curr->opcode != _SET_IP && trace_length > 1) { + while (curr->opcode != _SET_IP && trace_length > 2) { trace_length--; curr = &trace[trace_length-1]; } - assert(curr->opcode == _SET_IP || trace_length == 1); - curr->opcode = _EXIT_TRACE; + assert(curr->opcode == _SET_IP || trace_length == 2); + if (curr->opcode == _SET_IP) { + int32_t old_target = (int32_t)uop_get_target(curr); + curr++; + trace_length++; + curr->opcode = _EXIT_TRACE; + curr->format = UOP_FORMAT_TARGET; + curr->target = old_target; + } goto done; } } @@ -621,10 +634,6 @@ _PyJIT_translate_single_bytecode_to_trace( return 1; } - if (opcode == JUMP_BACKWARD_NO_INTERRUPT) { - return 1; - } - if (opcode == JUMP_FORWARD) { return 1; } @@ -661,8 +670,7 @@ _PyJIT_translate_single_bytecode_to_trace( // Loop back to the start if (is_first_instr && tstate->interp->jit_tracer_code_curr_size > 2) { - // Undo the last few instructions. - trace_length = tstate->interp->jit_tracer_code_curr_size; + ADD_TO_TRACE(_CHECK_PERIODIC, 0, 0, target); ADD_TO_TRACE(_JUMP_TO_TOP, 0, 0, 0); goto done; }