]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
fix a few tests and their exposed bugs
authorKen Jin <28750310+Fidget-Spinner@users.noreply.github.com>
Fri, 17 Oct 2025 23:47:16 +0000 (00:47 +0100)
committerKen Jin <28750310+Fidget-Spinner@users.noreply.github.com>
Fri, 17 Oct 2025 23:47:16 +0000 (00:47 +0100)
Include/internal/pycore_opcode_metadata.h
Include/internal/pycore_uop_ids.h
Lib/test/test_capi/test_opt.py
Lib/test/test_sys.py
Modules/_testinternalcapi.c
Python/bytecodes.c
Python/ceval.c
Python/executor_cases.c.h
Python/optimizer.c

index b96033eadf90b66963c2f4da19755f576e356d7f..477553e2563f8ce3e382a390830dcd22e7d24501 100644 (file)
@@ -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,
index 2ef1fccc8d8ee2d36f7cdf676835e0622820f66e..9f4ae71a313aa07dd6104b16744f6953188dc16d 100644 (file)
@@ -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
 }
index 3cc8fbe0de0a6cd72316a486b6121ec0a840df8b..842a328f5d83b41b666b1ab8be0a7ff8e94a4428 100644 (file)
@@ -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
         """))
index 1198c6d35113c81b0689a60528ef65ef30b52807..98dd466849e555ed214bc95ebad73afd9545bd2c 100644 (file)
@@ -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
index 7aa63f913af3356e89d6f2bbc4b5c8857bdb6450..158ffb5b9d803bed5a57a0e63d7ae754058e6fa0 100644 (file)
@@ -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;
     }
 
index 5ab80565d6d486cfdb601d46bfc00bc6d7654233..a4a75008c66cdf58981e8f08eb78376e1814f380 100644 (file)
@@ -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);
             }
index 035a22615ca961d9fdfbf8ba476ba6dbd68cc82c..844ca4297f4157e07f62714c21499b169eda5253 100644 (file)
@@ -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;
index f13baadd3bc76f54699a71cb824f37dd184adfb5..0a664209830f1fb4549f632e6e1db5a75c198db7 100644 (file)
         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;
         }
 
                     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);
             }
index 77f7dee553f364b7ed53bbdb8b1f3ed8e2a184d1..5d75a87ee0de5e1f6e53d12bcd88eee47882b896 100644 (file)
@@ -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;
     }