]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
GH-129386: Use symbolic constants for specialization tests (GH-129415)
authorBrandt Bucher <brandtbucher@microsoft.com>
Wed, 29 Jan 2025 18:49:58 +0000 (10:49 -0800)
committerGitHub <noreply@github.com>
Wed, 29 Jan 2025 18:49:58 +0000 (10:49 -0800)
Lib/test/test_call.py
Lib/test/test_dis.py
Lib/test/test_embed.py
Lib/test/test_monitoring.py
Lib/test/test_opcache.py
Lib/test/test_super.py
Lib/test/test_type_cache.py
Modules/_testinternalcapi.c

index 78a706436aea0e7ea0bf8efcfee97d7d1a4fd0a8..a4115d54ce5995839791eec4d68e5a371a960ce1 100644 (file)
@@ -1,6 +1,6 @@
 import unittest
 from test.support import (cpython_only, is_wasi, requires_limited_api, Py_DEBUG,
-                          set_recursion_limit, skip_on_s390x, skip_emscripten_stack_overflow)
+                          set_recursion_limit, skip_on_s390x, skip_emscripten_stack_overflow, import_helper)
 try:
     import _testcapi
 except ImportError:
@@ -616,9 +616,6 @@ def testfunction_kw(self, *, kw):
     return self
 
 
-ADAPTIVE_WARMUP_DELAY = 2
-
-
 @unittest.skipIf(_testcapi is None, "requires _testcapi")
 class TestPEP590(unittest.TestCase):
 
@@ -802,17 +799,18 @@ class TestPEP590(unittest.TestCase):
 
     def test_setvectorcall(self):
         from _testcapi import function_setvectorcall
+        _testinternalcapi = import_helper.import_module("_testinternalcapi")
         def f(num): return num + 1
         assert_equal = self.assertEqual
         num = 10
         assert_equal(11, f(num))
         function_setvectorcall(f)
-        # make sure specializer is triggered by running > 50 times
-        for _ in range(10 * ADAPTIVE_WARMUP_DELAY):
+        for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
             assert_equal("overridden", f(num))
 
     def test_setvectorcall_load_attr_specialization_skip(self):
         from _testcapi import function_setvectorcall
+        _testinternalcapi = import_helper.import_module("_testinternalcapi")
 
         class X:
             def __getattribute__(self, attr):
@@ -824,11 +822,12 @@ class TestPEP590(unittest.TestCase):
         function_setvectorcall(X.__getattribute__)
         # make sure specialization doesn't trigger
         # when vectorcall is overridden
-        for _ in range(ADAPTIVE_WARMUP_DELAY):
+        for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
             assert_equal("overridden", x.a)
 
     def test_setvectorcall_load_attr_specialization_deopt(self):
         from _testcapi import function_setvectorcall
+        _testinternalcapi = import_helper.import_module("_testinternalcapi")
 
         class X:
             def __getattribute__(self, attr):
@@ -840,12 +839,12 @@ class TestPEP590(unittest.TestCase):
         assert_equal = self.assertEqual
         x = X()
         # trigger LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN specialization
-        for _ in range(ADAPTIVE_WARMUP_DELAY):
+        for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
             assert_equal("a", get_a(x))
         function_setvectorcall(X.__getattribute__)
         # make sure specialized LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN
         # gets deopted due to overridden vectorcall
-        for _ in range(ADAPTIVE_WARMUP_DELAY):
+        for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
             assert_equal("overridden", get_a(x))
 
     @requires_limited_api
index 2e149b32e5c1ec9d3296d7944b81d3d197ab7cfa..bba2ac80aa6769fdd8b179e91ffabe8d85368422 100644 (file)
@@ -931,8 +931,6 @@ dis_extended_arg_quick_code = """\
 """% (extended_arg_quick.__code__.co_firstlineno,
       extended_arg_quick.__code__.co_firstlineno + 1,)
 
-ADAPTIVE_WARMUP_DELAY = 2
-
 class DisTestBase(unittest.TestCase):
     "Common utilities for DisTests and TestDisTraceback"
 
@@ -1259,8 +1257,9 @@ class DisTests(DisTestBase):
             self.assertIsNone(e.__context__)
 
     @staticmethod
-    def code_quicken(f, times=ADAPTIVE_WARMUP_DELAY):
-        for _ in range(times):
+    def code_quicken(f):
+        _testinternalcapi = import_helper.import_module("_testinternalcapi")
+        for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
             f()
 
     @cpython_only
@@ -1306,7 +1305,7 @@ class DisTests(DisTestBase):
     @requires_specialization
     def test_loop_quicken(self):
         # Loop can trigger a quicken where the loop is located
-        self.code_quicken(loop_test, 4)
+        self.code_quicken(loop_test)
         got = self.get_disassembly(loop_test, adaptive=True)
         jit = import_helper.import_module("_testinternalcapi").jit_enabled()
         expected = dis_loop_test_quickened_code.format("JIT" if jit else "NO_JIT")
@@ -1315,8 +1314,9 @@ class DisTests(DisTestBase):
     @cpython_only
     @requires_specialization
     def test_loop_with_conditional_at_end_is_quickened(self):
+        _testinternalcapi = import_helper.import_module("_testinternalcapi")
         def for_loop_true(x):
-            for i in range(10):
+            for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
                 if x:
                     pass
 
@@ -1325,7 +1325,7 @@ class DisTests(DisTestBase):
                       self.get_disassembly(for_loop_true, adaptive=True))
 
         def for_loop_false(x):
-            for i in range(10):
+            for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
                 if x:
                     pass
 
@@ -1335,7 +1335,7 @@ class DisTests(DisTestBase):
 
         def while_loop():
             i = 0
-            while i < 10:
+            while i < _testinternalcapi.SPECIALIZATION_THRESHOLD:
                 i += 1
 
         while_loop()
index ffb69c87a065aac9ca44d4bdedbd22bfbe4ac5e3..f41c45ec4d9cddad502c3470d302fc96e0118c83 100644 (file)
@@ -384,7 +384,9 @@ class EmbeddingTests(EmbeddingTestsMixin, unittest.TestCase):
     def test_specialized_static_code_gets_unspecialized_at_Py_FINALIZE(self):
         # https://github.com/python/cpython/issues/92031
 
-        code = textwrap.dedent("""\
+        _testinternalcapi = import_helper.import_module("_testinternalcapi")
+
+        code = textwrap.dedent(f"""\
             import dis
             import importlib._bootstrap
             import opcode
@@ -411,7 +413,7 @@ class EmbeddingTests(EmbeddingTestsMixin, unittest.TestCase):
 
             assert not is_specialized(func), "specialized instructions found"
 
-            for i in range(test.test_dis.ADAPTIVE_WARMUP_DELAY):
+            for _ in range({_testinternalcapi.SPECIALIZATION_THRESHOLD}):
                 func(importlib._bootstrap, ["x"], lambda *args: None)
 
             assert is_specialized(func), "no specialized instructions found"
index 364381e7dce00a414a21da76c2c982a23e8b0128..3125d190626e3801ffe112ac4fe42a2d969e3186 100644 (file)
@@ -14,6 +14,7 @@ import test.support
 from test.support import requires_specialization_ft, script_helper
 
 _testcapi = test.support.import_helper.import_module("_testcapi")
+_testinternalcapi = test.support.import_helper.import_module("_testinternalcapi")
 
 PAIR = (0,1)
 
@@ -897,13 +898,13 @@ class ExceptionMonitoringTest(CheckEvents):
         # re-specialize immediately, so that we can we can test the
         # unspecialized version of the loop first.
         # Note: this assumes that we don't specialize loops over sets.
-        implicit_stop_iteration(set(range(100)))
+        implicit_stop_iteration(set(range(_testinternalcapi.SPECIALIZATION_THRESHOLD)))
 
         # This will record a RAISE event for the StopIteration.
         self.check_events(implicit_stop_iteration, expected, recorders=recorders)
 
         # Now specialize, so that we see a STOP_ITERATION event.
-        for _ in range(100):
+        for _ in range(_testinternalcapi.SPECIALIZATION_COOLDOWN):
             implicit_stop_iteration()
 
         # This will record a STOP_ITERATION event for the StopIteration.
@@ -1057,7 +1058,7 @@ class ExceptionMonitoringTest(CheckEvents):
             except ValueError:
                 pass
 
-        for _ in range(100):
+        for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
             f()
         recorders = (
             ReturnRecorder,
@@ -2033,8 +2034,8 @@ class TestRegressions(MonitoringTestBase, unittest.TestCase):
                     sys.monitoring.set_events(TEST_TOOL, E.PY_RESUME)
 
         def make_foo_optimized_then_set_event():
-            for i in range(100):
-                Foo(i == 99)
+            for i in range(_testinternalcapi.SPECIALIZATION_THRESHOLD + 1):
+                Foo(i == _testinternalcapi.SPECIALIZATION_THRESHOLD)
 
         try:
             make_foo_optimized_then_set_event()
@@ -2106,9 +2107,9 @@ class TestTier2Optimizer(CheckEvents):
             set_events = sys.monitoring.set_events
             line = E.LINE
             i = 0
-            for i in range(551):
-                # Turn on events without branching once i reaches 500.
-                set_events(TEST_TOOL, line * int(i >= 500))
+            for i in range(_testinternalcapi.SPECIALIZATION_THRESHOLD + 51):
+                # Turn on events without branching once i reaches _testinternalcapi.SPECIALIZATION_THRESHOLD.
+                set_events(TEST_TOOL, line * int(i >= _testinternalcapi.SPECIALIZATION_THRESHOLD))
                 pass
                 pass
                 pass
index dc02d1d7babb23eefb9e99a4c342e3bf1f7db6cc..2defe74892786d2fc83a5294744abbd81432848e 100644 (file)
@@ -45,7 +45,8 @@ class TestLoadSuperAttrCache(unittest.TestCase):
 
         d = D()
 
-        self.assertEqual(d.f(), 1)  # warmup
+        for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD - 1):
+            self.assertEqual(d.f(), 1)  # warmup
         calls.clear()
         self.assertEqual(d.f(), 1)  # try to specialize
         self.assertEqual(calls, [(d, D)])
@@ -65,7 +66,7 @@ class TestLoadAttrCache(unittest.TestCase):
             return o.x
 
         o = C()
-        for i in range(1025):
+        for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
             assert f(o) == 1
 
         Descriptor.__get__ = lambda self, instance, value: 2
@@ -92,13 +93,13 @@ class TestLoadAttrCache(unittest.TestCase):
         def f():
             return Class.attribute
 
-        for _ in range(1025):
+        for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
             self.assertTrue(f())
 
         Descriptor.__get__ = __get__
         Descriptor.__set__ = __set__
 
-        for _ in range(1025):
+        for _ in range(_testinternalcapi.SPECIALIZATION_COOLDOWN):
             self.assertFalse(f())
 
     def test_metaclass_descriptor_shadows_class_attribute(self):
@@ -113,7 +114,7 @@ class TestLoadAttrCache(unittest.TestCase):
         def f():
             return Class.attribute
 
-        for _ in range(1025):
+        for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
             self.assertTrue(f())
 
     def test_metaclass_set_descriptor_after_optimization(self):
@@ -130,12 +131,12 @@ class TestLoadAttrCache(unittest.TestCase):
         def f():
             return Class.attribute
 
-        for _ in range(1025):
+        for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
             self.assertTrue(f())
 
         Metaclass.attribute = attribute
 
-        for _ in range(1025):
+        for _ in range(_testinternalcapi.SPECIALIZATION_COOLDOWN):
             self.assertFalse(f())
 
     def test_metaclass_del_descriptor_after_optimization(self):
@@ -150,12 +151,12 @@ class TestLoadAttrCache(unittest.TestCase):
         def f():
             return Class.attribute
 
-        for _ in range(1025):
+        for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
             self.assertTrue(f())
 
         del Metaclass.attribute
 
-        for _ in range(1025):
+        for _ in range(_testinternalcapi.SPECIALIZATION_COOLDOWN):
             self.assertFalse(f())
 
     def test_type_descriptor_shadows_attribute_method(self):
@@ -165,7 +166,7 @@ class TestLoadAttrCache(unittest.TestCase):
         def f():
             return Class.mro
 
-        for _ in range(1025):
+        for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
             self.assertIsNone(f())
 
     def test_type_descriptor_shadows_attribute_member(self):
@@ -175,7 +176,7 @@ class TestLoadAttrCache(unittest.TestCase):
         def f():
             return Class.__base__
 
-        for _ in range(1025):
+        for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
             self.assertIs(f(), object)
 
     def test_type_descriptor_shadows_attribute_getset(self):
@@ -185,7 +186,7 @@ class TestLoadAttrCache(unittest.TestCase):
         def f():
             return Class.__name__
 
-        for _ in range(1025):
+        for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
             self.assertEqual(f(), "Class")
 
     def test_metaclass_getattribute(self):
@@ -199,7 +200,7 @@ class TestLoadAttrCache(unittest.TestCase):
         def f():
             return Class.attribute
 
-        for _ in range(1025):
+        for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
             self.assertTrue(f())
 
     def test_metaclass_swap(self):
@@ -219,12 +220,12 @@ class TestLoadAttrCache(unittest.TestCase):
         def f():
             return Class.attribute
 
-        for _ in range(1025):
+        for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
             self.assertTrue(f())
 
         Class.__class__ = NewMetaclass
 
-        for _ in range(1025):
+        for _ in range(_testinternalcapi.SPECIALIZATION_COOLDOWN):
             self.assertFalse(f())
 
     def test_load_shadowing_slot_should_raise_type_error(self):
@@ -241,7 +242,7 @@ class TestLoadAttrCache(unittest.TestCase):
         o = Sneaky()
         o.shadowed = 42
 
-        for _ in range(1025):
+        for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
             with self.assertRaises(TypeError):
                 f(o)
 
@@ -258,7 +259,7 @@ class TestLoadAttrCache(unittest.TestCase):
 
         o = Sneaky()
 
-        for _ in range(1025):
+        for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
             with self.assertRaises(TypeError):
                 f(o)
 
@@ -274,7 +275,7 @@ class TestLoadAttrCache(unittest.TestCase):
 
         o = Sneaky()
 
-        for _ in range(1025):
+        for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
             with self.assertRaises(TypeError):
                 f(o)
 
@@ -290,7 +291,7 @@ class TestLoadAttrCache(unittest.TestCase):
 
         o = Sneaky()
 
-        for _ in range(1025):
+        for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
             with self.assertRaises(TypeError):
                 f(o)
 
@@ -318,13 +319,13 @@ class TestLoadMethodCache(unittest.TestCase):
         def f():
             return instance.attribute()
 
-        for _ in range(1025):
+        for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
             self.assertTrue(f())
 
         Descriptor.__get__ = __get__
         Descriptor.__set__ = __set__
 
-        for _ in range(1025):
+        for _ in range(_testinternalcapi.SPECIALIZATION_COOLDOWN):
             self.assertFalse(f())
 
     def test_metaclass_descriptor_added_after_optimization(self):
@@ -347,13 +348,13 @@ class TestLoadMethodCache(unittest.TestCase):
         def f():
             return Class.attribute()
 
-        for _ in range(1025):
+        for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
             self.assertTrue(f())
 
         Descriptor.__get__ = __get__
         Descriptor.__set__ = __set__
 
-        for _ in range(1025):
+        for _ in range(_testinternalcapi.SPECIALIZATION_COOLDOWN):
             self.assertFalse(f())
 
     def test_metaclass_descriptor_shadows_class_attribute(self):
@@ -369,7 +370,7 @@ class TestLoadMethodCache(unittest.TestCase):
         def f():
             return Class.attribute()
 
-        for _ in range(1025):
+        for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
             self.assertTrue(f())
 
     def test_metaclass_set_descriptor_after_optimization(self):
@@ -387,12 +388,12 @@ class TestLoadMethodCache(unittest.TestCase):
         def f():
             return Class.attribute()
 
-        for _ in range(1025):
+        for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
             self.assertTrue(f())
 
         Metaclass.attribute = attribute
 
-        for _ in range(1025):
+        for _ in range(_testinternalcapi.SPECIALIZATION_COOLDOWN):
             self.assertFalse(f())
 
     def test_metaclass_del_descriptor_after_optimization(self):
@@ -408,12 +409,12 @@ class TestLoadMethodCache(unittest.TestCase):
         def f():
             return Class.attribute()
 
-        for _ in range(1025):
+        for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
             self.assertTrue(f())
 
         del Metaclass.attribute
 
-        for _ in range(1025):
+        for _ in range(_testinternalcapi.SPECIALIZATION_COOLDOWN):
             self.assertFalse(f())
 
     def test_type_descriptor_shadows_attribute_method(self):
@@ -424,7 +425,7 @@ class TestLoadMethodCache(unittest.TestCase):
         def f():
             return Class.mro()
 
-        for _ in range(1025):
+        for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
             self.assertEqual(f(), ["Spam", "eggs"])
 
     def test_type_descriptor_shadows_attribute_member(self):
@@ -435,7 +436,7 @@ class TestLoadMethodCache(unittest.TestCase):
         def f():
             return Class.__base__()
 
-        for _ in range(1025):
+        for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
             self.assertNotEqual(f(), "Spam")
 
     def test_metaclass_getattribute(self):
@@ -450,7 +451,7 @@ class TestLoadMethodCache(unittest.TestCase):
         def f():
             return Class.attribute()
 
-        for _ in range(1025):
+        for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
             self.assertTrue(f())
 
     def test_metaclass_swap(self):
@@ -470,12 +471,12 @@ class TestLoadMethodCache(unittest.TestCase):
         def f():
             return Class.attribute()
 
-        for _ in range(1025):
+        for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
             self.assertTrue(f())
 
         Class.__class__ = NewMetaclass
 
-        for _ in range(1025):
+        for _ in range(_testinternalcapi.SPECIALIZATION_COOLDOWN):
             self.assertFalse(f())
 
 
@@ -490,7 +491,7 @@ class TestCallCache(TestBase):
             pass
 
         f.__defaults__ = (None,)
-        for _ in range(1025):
+        for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
             f()
 
     def test_too_many_defaults_1(self):
@@ -498,7 +499,7 @@ class TestCallCache(TestBase):
             pass
 
         f.__defaults__ = (None, None)
-        for _ in range(1025):
+        for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
             f(None)
             f()
 
@@ -507,7 +508,7 @@ class TestCallCache(TestBase):
             pass
 
         f.__defaults__ = (None, None, None)
-        for _ in range(1025):
+        for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
             f(None, None)
             f(None)
             f()
@@ -523,7 +524,7 @@ class TestCallCache(TestBase):
             return MyClass()
 
         # Trigger specialization
-        for _ in range(1025):
+        for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
             instantiate()
         self.assert_specialized(instantiate, "CALL_ALLOC_AND_ENTER_INIT")
 
@@ -541,7 +542,7 @@ class TestCallCache(TestBase):
         def instantiate():
             return InitTakesArg()
 
-        for _ in range(2):
+        for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
             with self.assertRaises(TypeError):
                 instantiate()
         self.assert_specialized(instantiate, "CALL_ALLOC_AND_ENTER_INIT")
@@ -566,7 +567,6 @@ class TestRacesDoNotCrash(TestBase):
     # but you can also burn through a *ton* of type/dict/function versions:
     ITEMS = 1000
     LOOPS = 4
-    WARMUPS = 2
     WRITERS = 2
 
     @requires_jit_disabled
@@ -583,7 +583,7 @@ class TestRacesDoNotCrash(TestBase):
             else:
                 read.__code__ = read.__code__.replace()
             # Specialize:
-            for _ in range(self.WARMUPS):
+            for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
                 read(items)
             if check_items:
                 for item in items:
@@ -1011,7 +1011,7 @@ class TestRacesDoNotCrash(TestBase):
                 item = C()
                 item.a = None
                 # Resize into a combined unicode dict:
-                for i in range(29):
+                for i in range(_testinternalcapi.SHARED_KEYS_MAX_SIZE - 1):
                     setattr(item, f"_{i}", None)
                 items.append(item)
             return items
@@ -1082,7 +1082,7 @@ class TestRacesDoNotCrash(TestBase):
             for _ in range(self.ITEMS):
                 item = C()
                 # Resize into a combined unicode dict:
-                for i in range(29):
+                for i in range(_testinternalcapi.SHARED_KEYS_MAX_SIZE - 1):
                     setattr(item, f"_{i}", None)
                 items.append(item)
             return items
@@ -1178,7 +1178,7 @@ class TestInstanceDict(unittest.TestCase):
         c.a = 1
         c.b = 2
         c.__dict__
-        for _ in range(100):
+        for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
             c.a
         self.assertEqual(
             _testinternalcapi.get_object_dict_values(c),
@@ -1190,7 +1190,7 @@ class TestInstanceDict(unittest.TestCase):
         c.a = 1
         c.b = 2
         d = c.__dict__
-        for _ in range(100):
+        for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
             c.a
         self.assertIs(c.__dict__, d)
 
@@ -1199,7 +1199,7 @@ class TestInstanceDict(unittest.TestCase):
         c.a = 1
         c.b = 2
         c2 = copy.copy(c)
-        for _ in range(100):
+        for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
             c.a
             c2.a
         self.assertEqual(
@@ -1211,7 +1211,7 @@ class TestInstanceDict(unittest.TestCase):
             (1, 2, '<NULL>')
         )
         c3 = copy.deepcopy(c)
-        for _ in range(100):
+        for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
             c.a
             c3.a
         self.assertEqual(
@@ -1225,7 +1225,7 @@ class TestInstanceDict(unittest.TestCase):
         c.a = 1
         c.b = 2
         c2 = pickle.loads(pickle.dumps(c))
-        for _ in range(100):
+        for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
             c.a
             c2.a
         self.assertEqual(
@@ -1243,7 +1243,7 @@ class TestInstanceDict(unittest.TestCase):
         c.a = 1
         c.b = 2
         c.__dict__ = D(c.__dict__)
-        for _ in range(100):
+        for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
             c.a
         self.assertIs(
             _testinternalcapi.get_object_dict_values(c),
@@ -1288,7 +1288,7 @@ class TestInstanceDict(unittest.TestCase):
             for i in range(n):
                 o.b = i
         # Prime f to store to dict slot 1
-        f(c, 100)
+        f(c, _testinternalcapi.SPECIALIZATION_THRESHOLD)
 
         test_obj = NoInlineAorB()
         test_obj.__dict__ = make_special_dict()
@@ -1305,7 +1305,7 @@ class TestSpecializer(TestBase):
     @requires_specialization_ft
     def test_binary_op(self):
         def binary_op_add_int():
-            for _ in range(100):
+            for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
                 a, b = 1, 2
                 c = a + b
                 self.assertEqual(c, 3)
@@ -1315,7 +1315,7 @@ class TestSpecializer(TestBase):
         self.assert_no_opcode(binary_op_add_int, "BINARY_OP")
 
         def binary_op_add_unicode():
-            for _ in range(100):
+            for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
                 a, b = "foo", "bar"
                 c = a + b
                 self.assertEqual(c, "foobar")
@@ -1325,7 +1325,7 @@ class TestSpecializer(TestBase):
         self.assert_no_opcode(binary_op_add_unicode, "BINARY_OP")
 
         def binary_op_add_extend():
-            for _ in range(100):
+            for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
                 a, b = 6, 3.0
                 c = a + b
                 self.assertEqual(c, 9.0)
@@ -1384,11 +1384,13 @@ class TestSpecializer(TestBase):
                     arg / 42,
                 )
             nan = float('nan')
-            self.assertEqual(compactlong_lhs(1.0), (43.0, 41.0, 42.0, 42.0))
-            for _ in range(100):
+            for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
+                self.assertEqual(compactlong_lhs(1.0), (43.0, 41.0, 42.0, 42.0))
+            for _ in range(_testinternalcapi.SPECIALIZATION_COOLDOWN):
                 self.assertTrue(all(filter(lambda x: x is nan, compactlong_lhs(nan))))
-            self.assertEqual(compactlong_rhs(42.0), (84.0, 0.0, 84.0, 1.0))
-            for _ in range(100):
+            for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
+                self.assertEqual(compactlong_rhs(42.0), (84.0, 0.0, 84.0, 1.0))
+            for _ in range(_testinternalcapi.SPECIALIZATION_COOLDOWN):
                 self.assertTrue(all(filter(lambda x: x is nan, compactlong_rhs(nan))))
 
             self.assert_no_opcode(compactlong_lhs, "BINARY_OP_EXTEND")
@@ -1429,7 +1431,7 @@ class TestSpecializer(TestBase):
                 meth = super().__init__
                 super().__init__()
 
-        for _ in range(100):
+        for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
             A()
 
         self.assert_specialized(A.__init__, "LOAD_SUPER_ATTR_ATTR")
@@ -1449,7 +1451,7 @@ class TestSpecializer(TestBase):
         globals()['super'] = fake_super
         try:
             # Should be unspecialized after enough calls.
-            for _ in range(100):
+            for _ in range(_testinternalcapi.SPECIALIZATION_COOLDOWN):
                 A()
         finally:
             globals()['super'] = real_super
@@ -1462,7 +1464,7 @@ class TestSpecializer(TestBase):
     @requires_specialization_ft
     def test_contain_op(self):
         def contains_op_dict():
-            for _ in range(100):
+            for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
                 a, b = 1, {1: 2, 2: 5}
                 self.assertTrue(a in b)
                 self.assertFalse(3 in b)
@@ -1472,7 +1474,7 @@ class TestSpecializer(TestBase):
         self.assert_no_opcode(contains_op_dict, "CONTAINS_OP")
 
         def contains_op_set():
-            for _ in range(100):
+            for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
                 a, b = 1, {1, 2}
                 self.assertTrue(a in b)
                 self.assertFalse(3 in b)
@@ -1499,7 +1501,7 @@ class TestSpecializer(TestBase):
                 pass
 
         async def send_with():
-            for i in range(100):
+            for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
                 async with CM():
                     x = 1
 
@@ -1517,7 +1519,7 @@ class TestSpecializer(TestBase):
         def send_yield_from():
             yield from g()
 
-        for i in range(100):
+        for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
             list(send_yield_from())
 
         self.assert_specialized(send_yield_from, "SEND_GEN")
@@ -1529,19 +1531,19 @@ class TestSpecializer(TestBase):
         class C:
             __slots__ = ['x']
 
-        def set_slot():
+        def set_slot(n):
             c = C()
-            for i in range(100):
+            for i in range(n):
                 c.x = i
 
-        set_slot()
+        set_slot(_testinternalcapi.SPECIALIZATION_THRESHOLD)
 
         self.assert_specialized(set_slot, "STORE_ATTR_SLOT")
         self.assert_no_opcode(set_slot, "STORE_ATTR")
 
         # Adding a property for 'x' should unspecialize it.
         C.x = property(lambda self: None, lambda self, x: None)
-        set_slot()
+        set_slot(_testinternalcapi.SPECIALIZATION_COOLDOWN)
         self.assert_no_opcode(set_slot, "STORE_ATTR_SLOT")
 
     @cpython_only
@@ -1550,19 +1552,19 @@ class TestSpecializer(TestBase):
         class C:
             pass
 
-        def set_value():
+        def set_value(n):
             c = C()
-            for i in range(100):
+            for i in range(n):
                 c.x = i
 
-        set_value()
+        set_value(_testinternalcapi.SPECIALIZATION_THRESHOLD)
 
         self.assert_specialized(set_value, "STORE_ATTR_INSTANCE_VALUE")
         self.assert_no_opcode(set_value, "STORE_ATTR")
 
         # Adding a property for 'x' should unspecialize it.
         C.x = property(lambda self: None, lambda self, x: None)
-        set_value()
+        set_value(_testinternalcapi.SPECIALIZATION_COOLDOWN)
         self.assert_no_opcode(set_value, "STORE_ATTR_INSTANCE_VALUE")
 
     @cpython_only
@@ -1572,21 +1574,21 @@ class TestSpecializer(TestBase):
             pass
 
         c = C()
-        for i in range(29):
+        for i in range(_testinternalcapi.SHARED_KEYS_MAX_SIZE - 1):
             setattr(c, f"_{i}", None)
 
-        def set_value():
-            for i in range(100):
+        def set_value(n):
+            for i in range(n):
                 c.x = i
 
-        set_value()
+        set_value(_testinternalcapi.SPECIALIZATION_THRESHOLD)
 
         self.assert_specialized(set_value, "STORE_ATTR_WITH_HINT")
         self.assert_no_opcode(set_value, "STORE_ATTR")
 
         # Adding a property for 'x' should unspecialize it.
         C.x = property(lambda self: None, lambda self, x: None)
-        set_value()
+        set_value(_testinternalcapi.SPECIALIZATION_COOLDOWN)
         self.assert_no_opcode(set_value, "STORE_ATTR_WITH_HINT")
 
     @cpython_only
@@ -1594,14 +1596,15 @@ class TestSpecializer(TestBase):
     def test_to_bool(self):
         def to_bool_bool():
             true_cnt, false_cnt = 0, 0
-            elems = [e % 2 == 0 for e in range(100)]
+            elems = [e % 2 == 0 for e in range(_testinternalcapi.SPECIALIZATION_THRESHOLD)]
             for e in elems:
                 if e:
                     true_cnt += 1
                 else:
                     false_cnt += 1
-            self.assertEqual(true_cnt, 50)
-            self.assertEqual(false_cnt, 50)
+            d, m = divmod(_testinternalcapi.SPECIALIZATION_THRESHOLD, 2)
+            self.assertEqual(true_cnt, d + m)
+            self.assertEqual(false_cnt, d)
 
         to_bool_bool()
         self.assert_specialized(to_bool_bool, "TO_BOOL_BOOL")
@@ -1609,12 +1612,12 @@ class TestSpecializer(TestBase):
 
         def to_bool_int():
             count = 0
-            for i in range(100):
+            for i in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
                 if i:
                     count += 1
                 else:
                     count -= 1
-            self.assertEqual(count, 98)
+            self.assertEqual(count, _testinternalcapi.SPECIALIZATION_THRESHOLD - 2)
 
         to_bool_int()
         self.assert_specialized(to_bool_int, "TO_BOOL_INT")
@@ -1622,11 +1625,11 @@ class TestSpecializer(TestBase):
 
         def to_bool_list():
             count = 0
-            elems = [1, 2, 3]
+            elems = list(range(_testinternalcapi.SPECIALIZATION_THRESHOLD))
             while elems:
                 count += elems.pop()
             self.assertEqual(elems, [])
-            self.assertEqual(count, 6)
+            self.assertEqual(count, sum(range(_testinternalcapi.SPECIALIZATION_THRESHOLD)))
 
         to_bool_list()
         self.assert_specialized(to_bool_list, "TO_BOOL_LIST")
@@ -1634,11 +1637,11 @@ class TestSpecializer(TestBase):
 
         def to_bool_none():
             count = 0
-            elems = [None, None, None, None]
+            elems = [None] * _testinternalcapi.SPECIALIZATION_THRESHOLD
             for e in elems:
                 if not e:
                     count += 1
-            self.assertEqual(count, len(elems))
+            self.assertEqual(count, _testinternalcapi.SPECIALIZATION_THRESHOLD)
 
         to_bool_none()
         self.assert_specialized(to_bool_none, "TO_BOOL_NONE")
@@ -1646,11 +1649,11 @@ class TestSpecializer(TestBase):
 
         def to_bool_str():
             count = 0
-            elems = ["", "foo", ""]
+            elems = [""] + ["foo"] * (_testinternalcapi.SPECIALIZATION_THRESHOLD - 1)
             for e in elems:
                 if e:
                     count += 1
-            self.assertEqual(count, 1)
+            self.assertEqual(count, _testinternalcapi.SPECIALIZATION_THRESHOLD - 1)
 
         to_bool_str()
         self.assert_specialized(to_bool_str, "TO_BOOL_STR")
@@ -1660,7 +1663,7 @@ class TestSpecializer(TestBase):
     @requires_specialization_ft
     def test_unpack_sequence(self):
         def unpack_sequence_two_tuple():
-            for _ in range(100):
+            for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
                 a, b = 1, 2
                 self.assertEqual(a, 1)
                 self.assertEqual(b, 2)
@@ -1671,7 +1674,7 @@ class TestSpecializer(TestBase):
         self.assert_no_opcode(unpack_sequence_two_tuple, "UNPACK_SEQUENCE")
 
         def unpack_sequence_tuple():
-            for _ in range(100):
+            for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
                 a, = 1,
                 self.assertEqual(a, 1)
 
@@ -1680,7 +1683,7 @@ class TestSpecializer(TestBase):
         self.assert_no_opcode(unpack_sequence_tuple, "UNPACK_SEQUENCE")
 
         def unpack_sequence_list():
-            for _ in range(100):
+            for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
                 a, b = [1, 2]
                 self.assertEqual(a, 1)
                 self.assertEqual(b, 2)
@@ -1693,7 +1696,7 @@ class TestSpecializer(TestBase):
     @requires_specialization_ft
     def test_binary_subscr(self):
         def binary_subscr_list_int():
-            for _ in range(100):
+            for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
                 a = [1, 2, 3]
                 for idx, expected in enumerate(a):
                     self.assertEqual(a[idx], expected)
@@ -1704,7 +1707,7 @@ class TestSpecializer(TestBase):
         self.assert_no_opcode(binary_subscr_list_int, "BINARY_SUBSCR")
 
         def binary_subscr_tuple_int():
-            for _ in range(100):
+            for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
                 a = (1, 2, 3)
                 for idx, expected in enumerate(a):
                     self.assertEqual(a[idx], expected)
@@ -1715,7 +1718,7 @@ class TestSpecializer(TestBase):
         self.assert_no_opcode(binary_subscr_tuple_int, "BINARY_SUBSCR")
 
         def binary_subscr_dict():
-            for _ in range(100):
+            for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
                 a = {1: 2, 2: 3}
                 self.assertEqual(a[1], 2)
                 self.assertEqual(a[2], 3)
@@ -1725,7 +1728,7 @@ class TestSpecializer(TestBase):
         self.assert_no_opcode(binary_subscr_dict, "BINARY_SUBSCR")
 
         def binary_subscr_str_int():
-            for _ in range(100):
+            for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
                 a = "foobar"
                 for idx, expected in enumerate(a):
                     self.assertEqual(a[idx], expected)
@@ -1741,8 +1744,8 @@ class TestSpecializer(TestBase):
                 def __getitem__(self, item):
                     return self.val
 
-            items = [C(i) for i in range(100)]
-            for i in range(100):
+            items = [C(i) for i in range(_testinternalcapi.SPECIALIZATION_THRESHOLD)]
+            for i in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
                 self.assertEqual(items[i][i], i)
 
         binary_subscr_getitems()
@@ -1753,7 +1756,7 @@ class TestSpecializer(TestBase):
     @requires_specialization_ft
     def test_compare_op(self):
         def compare_op_int():
-            for _ in range(100):
+            for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
                 a, b = 1, 2
                 c = a == b
                 self.assertFalse(c)
@@ -1763,7 +1766,7 @@ class TestSpecializer(TestBase):
         self.assert_no_opcode(compare_op_int, "COMPARE_OP")
 
         def compare_op_float():
-            for _ in range(100):
+            for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
                 a, b = 1.0, 2.0
                 c = a == b
                 self.assertFalse(c)
@@ -1773,7 +1776,7 @@ class TestSpecializer(TestBase):
         self.assert_no_opcode(compare_op_float, "COMPARE_OP")
 
         def compare_op_str():
-            for _ in range(100):
+            for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
                 a, b = "spam", "ham"
                 c = a == b
                 self.assertFalse(c)
index 149016635522c3f585e1c7474e95fddcb1a16199..5cef612a340be9564965073f0df239260f56142e 100644 (file)
@@ -9,9 +9,6 @@ from unittest.mock import patch
 from test.support import import_helper, threading_helper
 
 
-ADAPTIVE_WARMUP_DELAY = 2
-
-
 class A:
     def f(self):
         return 'A'
@@ -466,7 +463,8 @@ class TestSuper(unittest.TestCase):
             super(MyType, type(mytype)).__setattr__(mytype, "bar", 1)
             self.assertEqual(mytype.bar, 1)
 
-        for _ in range(ADAPTIVE_WARMUP_DELAY):
+        _testinternalcapi = import_helper.import_module("_testinternalcapi")
+        for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
             test("foo1")
 
     def test_reassigned_new(self):
@@ -485,7 +483,8 @@ class TestSuper(unittest.TestCase):
             def __new__(cls):
                 return super().__new__(cls)
 
-        for _ in range(ADAPTIVE_WARMUP_DELAY):
+        _testinternalcapi = import_helper.import_module("_testinternalcapi")
+        for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
             C()
 
     def test_mixed_staticmethod_hierarchy(self):
@@ -505,7 +504,8 @@ class TestSuper(unittest.TestCase):
             def some(cls):
                 return super().some(cls)
 
-        for _ in range(ADAPTIVE_WARMUP_DELAY):
+        _testinternalcapi = import_helper.import_module("_testinternalcapi")
+        for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
             C.some(C)
 
     @threading_helper.requires_working_threading()
index e109a65741309a094c91d9c2c1adf63bb8469a6d..ee64f89358ed55a39d00ca3e72d1782ac36c522e 100644 (file)
@@ -131,7 +131,7 @@ class TypeCacheWithSpecializationTests(unittest.TestCase):
         return set(instr.opname for instr in dis.Bytecode(func, adaptive=True))
 
     def _check_specialization(self, func, arg, opname, *, should_specialize):
-        for _ in range(100):
+        for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
             func(arg)
 
         if should_specialize:
index 9f38a9d7a9a5c22814079a5712e236f10549e456..e44b629897c58abe0b8f5dfe797c8f9ca94e47bb 100644 (file)
@@ -2138,6 +2138,21 @@ module_exec(PyObject *module)
         return 1;
     }
 
+    if (PyModule_Add(module, "SPECIALIZATION_THRESHOLD",
+                        PyLong_FromLong(ADAPTIVE_WARMUP_VALUE + 1)) < 0) {
+        return 1;
+    }
+
+    if (PyModule_Add(module, "SPECIALIZATION_COOLDOWN",
+                        PyLong_FromLong(ADAPTIVE_COOLDOWN_VALUE + 1)) < 0) {
+        return 1;
+    }
+
+    if (PyModule_Add(module, "SHARED_KEYS_MAX_SIZE",
+                        PyLong_FromLong(SHARED_KEYS_MAX_SIZE)) < 0) {
+        return 1;
+    }
+
     return 0;
 }