From e56fd449fbb9ac099f389806d4c494fa66fca248 Mon Sep 17 00:00:00 2001 From: Donghee Na Date: Thu, 7 Nov 2024 05:23:47 +0900 Subject: [PATCH] gh-115999: Move specializer test from test_dis to test_opcache (gh-126498) --- Lib/test/test_dis.py | 45 +----------------------------- Lib/test/test_opcache.py | 59 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 59 insertions(+), 45 deletions(-) diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py index 337ee3bbb05..f26411ace8f 100644 --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -10,8 +10,7 @@ import sys import types import unittest from test.support import (captured_stdout, requires_debug_ranges, - requires_specialization, requires_specialization_ft, - cpython_only) + requires_specialization, cpython_only) from test.support.bytecode_helper import BytecodeTestCase import opcode @@ -1261,27 +1260,6 @@ class DisTests(DisTestBase): got = self.get_disassembly(load_test, adaptive=True) self.do_disassembly_compare(got, dis_load_test_quickened_code) - @cpython_only - @requires_specialization_ft - def test_binary_specialize(self): - binary_op_quicken = """\ - 0 RESUME_CHECK 0 - - 1 LOAD_NAME 0 (a) - LOAD_NAME 1 (b) - %s - RETURN_VALUE -""" - co_int = compile('a + b', "", "eval") - self.code_quicken(lambda: exec(co_int, {}, {'a': 1, 'b': 2})) - got = self.get_disassembly(co_int, adaptive=True) - self.do_disassembly_compare(got, binary_op_quicken % "BINARY_OP_ADD_INT 0 (+)") - - co_unicode = compile('a + b', "", "eval") - self.code_quicken(lambda: exec(co_unicode, {}, {'a': 'a', 'b': 'b'})) - got = self.get_disassembly(co_unicode, adaptive=True) - self.do_disassembly_compare(got, binary_op_quicken % "BINARY_OP_ADD_UNICODE 0 (+)") - @cpython_only @requires_specialization def test_binary_subscr_specialize(self): @@ -1335,27 +1313,6 @@ class DisTests(DisTestBase): got = self.get_disassembly(co, adaptive=True) self.do_disassembly_compare(got, call_quicken) - @cpython_only - @requires_specialization_ft - def test_contains_specialize(self): - contains_op_quicken = """\ - 0 RESUME_CHECK 0 - - 1 LOAD_NAME 0 (a) - LOAD_NAME 1 (b) - %s - RETURN_VALUE -""" - co_dict = compile('a in b', "", "eval") - self.code_quicken(lambda: exec(co_dict, {}, {'a': 1, 'b': {1: 5}})) - got = self.get_disassembly(co_dict, adaptive=True) - self.do_disassembly_compare(got, contains_op_quicken % "CONTAINS_OP_DICT 0 (in)") - - co_set = compile('a in b', "", "eval") - self.code_quicken(lambda: exec(co_set, {}, {'a': 1.0, 'b': {1, 2, 3}})) - got = self.get_disassembly(co_set, adaptive=True) - self.do_disassembly_compare(got, contains_op_quicken % "CONTAINS_OP_SET 0 (in)") - @cpython_only @requires_specialization def test_loop_quicken(self): diff --git a/Lib/test/test_opcache.py b/Lib/test/test_opcache.py index cdcddb0d717..78e4bf44f7e 100644 --- a/Lib/test/test_opcache.py +++ b/Lib/test/test_opcache.py @@ -4,7 +4,9 @@ import dis import threading import types import unittest -from test.support import threading_helper, check_impl_detail, requires_specialization +from test.support import (threading_helper, check_impl_detail, + requires_specialization, requires_specialization_ft, + cpython_only) from test.support.import_helper import import_module # Skip this module on other interpreters, it is cpython specific: @@ -34,6 +36,11 @@ class TestBase(unittest.TestCase): opnames = {instruction.opname for instruction in instructions} self.assertIn(opname, opnames) + def assert_no_opcode(self, f, opname): + instructions = dis.get_instructions(f, adaptive=True) + opnames = {instruction.opname for instruction in instructions} + self.assertNotIn(opname, opnames) + class TestLoadSuperAttrCache(unittest.TestCase): def test_descriptor_not_double_executed_on_spec_fail(self): @@ -1200,5 +1207,55 @@ class TestInstanceDict(unittest.TestCase): self.assertEqual(test_obj.b, 0) +class TestSpecializer(TestBase): + + @cpython_only + @requires_specialization_ft + def test_binary_op(self): + def f(): + for _ in range(100): + a, b = 1, 2 + c = a + b + self.assertEqual(c, 3) + + f() + self.assert_specialized(f, "BINARY_OP_ADD_INT") + self.assert_no_opcode(f, "BINARY_OP") + + def g(): + for _ in range(100): + a, b = "foo", "bar" + c = a + b + self.assertEqual(c, "foobar") + + g() + self.assert_specialized(g, "BINARY_OP_ADD_UNICODE") + self.assert_no_opcode(g, "BINARY_OP") + + @cpython_only + @requires_specialization_ft + def test_contain_op(self): + def f(): + for _ in range(100): + a, b = 1, {1: 2, 2: 5} + self.assertTrue(a in b) + self.assertFalse(3 in b) + + f() + self.assert_specialized(f, "CONTAINS_OP_DICT") + self.assert_no_opcode(f, "CONTAINS_OP") + + def g(): + for _ in range(100): + a, b = 1, {1, 2} + self.assertTrue(a in b) + self.assertFalse(3 in b) + + g() + self.assert_specialized(g, "CONTAINS_OP_SET") + self.assert_no_opcode(g, "CONTAINS_OP") + + + if __name__ == "__main__": unittest.main()