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