7
7
import sys
8
8
import types
9
9
import unittest
10
- from test .support import captured_stdout , requires_debug_ranges , import_helper , cpython_only
10
+ from test .support import captured_stdout , requires_debug_ranges , cpython_only
11
11
from test .support .bytecode_helper import BytecodeTestCase
12
12
13
13
import opcode
@@ -583,7 +583,7 @@ def foo(x):
583
583
_h .__code__ .co_firstlineno + 3 ,
584
584
)
585
585
586
- def load_test (x , y ):
586
+ def load_test (x , y = 0 ):
587
587
a , b = x , y
588
588
return a , b
589
589
@@ -603,10 +603,37 @@ def load_test(x, y):
603
603
load_test .__code__ .co_firstlineno + 1 ,
604
604
load_test .__code__ .co_firstlineno + 2 )
605
605
606
- def binary_test (x , y ):
607
- a = x + y
608
- b = x - y
609
- return a + b
606
+ def loop_test ():
607
+ for i in [1 , 2 , 3 ] * 3 :
608
+ load_test (i )
609
+
610
+ dis_loop_test_quickened_code = """\
611
+ %3d 0 RESUME_QUICK 0
612
+
613
+ %3d 2 BUILD_LIST 0
614
+ 4 LOAD_CONST 1 ((1, 2, 3))
615
+ 6 LIST_EXTEND 1
616
+ 8 LOAD_CONST 2 (3)
617
+ 10 BINARY_OP_ADAPTIVE 5 (*)
618
+ 14 GET_ITER
619
+ 16 FOR_ITER 17 (to 52)
620
+ 18 STORE_FAST 0 (i)
621
+
622
+ %3d 20 LOAD_GLOBAL_MODULE 1 (NULL + load_test)
623
+ 32 LOAD_FAST 0 (i)
624
+ 34 PRECALL_PYFUNC 1
625
+ 38 CALL_PY_WITH_DEFAULTS 1
626
+ 48 POP_TOP
627
+ 50 JUMP_BACKWARD_QUICK 18 (to 16)
628
+
629
+ %3d >> 52 LOAD_CONST 0 (None)
630
+ 54 RETURN_VALUE
631
+ """ % (loop_test .__code__ .co_firstlineno ,
632
+ loop_test .__code__ .co_firstlineno + 1 ,
633
+ loop_test .__code__ .co_firstlineno + 2 ,
634
+ loop_test .__code__ .co_firstlineno + 1 ,)
635
+
636
+ QUICKENING_WARMUP_DELAY = 8
610
637
611
638
class DisTestBase (unittest .TestCase ):
612
639
"Common utilities for DisTests and TestDisTraceback"
@@ -887,11 +914,14 @@ def check(expected, **kwargs):
887
914
check (dis_nested_2 , depth = None )
888
915
check (dis_nested_2 )
889
916
890
- _testinternalcapi = import_helper .import_module ('_testinternalcapi' )
917
+ @staticmethod
918
+ def code_quicken (f , times = QUICKENING_WARMUP_DELAY ):
919
+ for _ in range (times ):
920
+ f ()
891
921
892
922
@cpython_only
893
923
def test_super_instructions (self ):
894
- self ._testinternalcapi . code_quicken (load_test . __code__ )
924
+ self .code_quicken (lambda : load_test ( 0 , 0 ) )
895
925
got = self .get_disassembly (load_test , adaptive = True )
896
926
self .do_disassembly_compare (got , dis_load_test_quickened_code , True )
897
927
@@ -906,35 +936,46 @@ def test_binary_specialize(self):
906
936
10 RETURN_VALUE
907
937
"""
908
938
co_int = compile ('a + b' , "<int>" , "eval" )
909
- self ._testinternalcapi .code_quicken (co_int )
910
- got = self .get_disassembly (co_int , adaptive = True )
911
- self .do_disassembly_compare (got , binary_op_quicken % "BINARY_OP_ADAPTIVE 0 (+)" , True )
912
- exec (co_int , {}, {'a' : 1 , 'b' : 2 })
939
+ self .code_quicken (lambda : exec (co_int , {}, {'a' : 1 , 'b' : 2 }))
913
940
got = self .get_disassembly (co_int , adaptive = True )
914
941
self .do_disassembly_compare (got , binary_op_quicken % "BINARY_OP_ADD_INT 0 (+)" , True )
915
942
916
943
co_unicode = compile ('a + b' , "<unicode>" , "eval" )
917
- self ._testinternalcapi .code_quicken (co_unicode )
918
- exec (co_unicode , {}, {'a' : 'a' , 'b' : 'b' })
944
+ self .code_quicken (lambda : exec (co_unicode , {}, {'a' : 'a' , 'b' : 'b' }))
919
945
got = self .get_disassembly (co_unicode , adaptive = True )
920
946
self .do_disassembly_compare (got , binary_op_quicken % "BINARY_OP_ADD_UNICODE 0 (+)" , True )
921
947
948
+ binary_subsrc_quicken = """\
949
+ 0 RESUME_QUICK 0
950
+
951
+ 1 2 LOAD_NAME 0 (a)
952
+ 4 LOAD_CONST 0 (0)
953
+ 6 %s
954
+ 16 RETURN_VALUE
955
+ """
956
+ co_list = compile ('a[0]' , "<list>" , "eval" )
957
+ self .code_quicken (lambda : exec (co_list , {}, {'a' : [0 ]}))
958
+ got = self .get_disassembly (co_list , adaptive = True )
959
+ self .do_disassembly_compare (got , binary_subsrc_quicken % "BINARY_SUBSCR_LIST_INT" , True )
960
+
961
+ co_dict = compile ('a[0]' , "<dict>" , "eval" )
962
+ self .code_quicken (lambda : exec (co_dict , {}, {'a' : {0 : '1' }}))
963
+ got = self .get_disassembly (co_dict , adaptive = True )
964
+ self .do_disassembly_compare (got , binary_subsrc_quicken % "BINARY_SUBSCR_DICT" , True )
965
+
922
966
@cpython_only
923
967
def test_load_attr_specialize (self ):
924
968
load_attr_quicken = """\
925
969
0 RESUME_QUICK 0
926
970
927
971
1 2 LOAD_CONST 0 ('a')
928
- 4 %s
972
+ 4 LOAD_ATTR_SLOT 0 (__class__)
929
973
14 RETURN_VALUE
930
974
"""
931
975
co = compile ("'a'.__class__" , "" , "eval" )
932
- self ._testinternalcapi . code_quicken (co )
976
+ self .code_quicken (lambda : exec ( co , {}, {}) )
933
977
got = self .get_disassembly (co , adaptive = True )
934
- self .do_disassembly_compare (got , load_attr_quicken % "LOAD_ATTR_ADAPTIVE 0 (__class__)" , True )
935
- exec (co , {}, {})
936
- got = self .get_disassembly (co , adaptive = True )
937
- self .do_disassembly_compare (got , load_attr_quicken % "LOAD_ATTR_SLOT 0 (__class__)" , True )
978
+ self .do_disassembly_compare (got , load_attr_quicken , True )
938
979
939
980
@cpython_only
940
981
def test_call_specialize (self ):
@@ -944,21 +985,21 @@ def test_call_specialize(self):
944
985
1 2 PUSH_NULL
945
986
4 LOAD_NAME 0 (str)
946
987
6 LOAD_CONST 0 (1)
947
- 8 %s
948
- 12 %s
988
+ 8 PRECALL_NO_KW_STR_1 1
989
+ 12 CALL_ADAPTIVE 1
949
990
22 RETURN_VALUE
950
991
"""
951
992
co = compile ("str(1)" , "" , "eval" )
952
- self ._testinternalcapi .code_quicken (co )
953
- got = self .get_disassembly (co , adaptive = True )
954
- self .do_disassembly_compare (got , call_quicken % (
955
- "PRECALL_ADAPTIVE 1" ,
956
- "CALL_ADAPTIVE 1" ), True )
957
- exec (co , {}, {})
993
+ self .code_quicken (lambda : exec (co , {}, {}))
958
994
got = self .get_disassembly (co , adaptive = True )
959
- self .do_disassembly_compare (got , call_quicken % (
960
- "PRECALL_NO_KW_STR_1 1" ,
961
- "CALL_ADAPTIVE 1" ), True )
995
+ self .do_disassembly_compare (got , call_quicken , True )
996
+
997
+ @cpython_only
998
+ def test_loop_quicken (self ):
999
+ # Loop can trigger a quicken where the loop is located
1000
+ self .code_quicken (loop_test , 1 )
1001
+ got = self .get_disassembly (loop_test , adaptive = True )
1002
+ self .do_disassembly_compare (got , dis_loop_test_quickened_code , True )
962
1003
963
1004
964
1005
class DisWithFileTests (DisTests ):
0 commit comments