28
28
CODE_OBJECT_ID_KEY = "code_object_id"
29
29
30
30
31
+ class ArtificialInstr (Instr ):
32
+ """Marker subclass to distinguish between original instructions
33
+ and instructions that were inserted by the instrumentation."""
34
+
35
+
31
36
# pylint:disable=too-few-public-methods
32
37
class InstrumentationAdapter :
33
38
"""Abstract base class for bytecode instrumentation adapters.
@@ -94,7 +99,7 @@ def _create_consecutive_blocks(
94
99
current : BasicBlock = first
95
100
nodes : list [BasicBlock ] = []
96
101
# Can be any instruction, as it is discarded anyway.
97
- dummy_instruction = Instr ("POP_TOP" )
102
+ dummy_instruction = ArtificialInstr ("POP_TOP" )
98
103
for _ in range (amount ):
99
104
# Insert dummy instruction, which we can use to split off another block
100
105
current .insert (0 , dummy_instruction )
@@ -348,18 +353,18 @@ def _instrument_bool_based_conditional_jump(
348
353
# We duplicate the value on top of the stack and report
349
354
# it to the tracer.
350
355
block [self ._JUMP_OP_POS : self ._JUMP_OP_POS ] = [
351
- Instr ("DUP_TOP" , lineno = lineno ),
352
- Instr ("LOAD_CONST" , self ._tracer , lineno = lineno ),
353
- Instr (
356
+ ArtificialInstr ("DUP_TOP" , lineno = lineno ),
357
+ ArtificialInstr ("LOAD_CONST" , self ._tracer , lineno = lineno ),
358
+ ArtificialInstr (
354
359
"LOAD_METHOD" ,
355
360
ExecutionTracer .executed_bool_predicate .__name__ ,
356
361
lineno = lineno ,
357
362
),
358
- Instr ("ROT_THREE" , lineno = lineno ),
359
- Instr ("ROT_THREE" , lineno = lineno ),
360
- Instr ("LOAD_CONST" , predicate_id , lineno = lineno ),
361
- Instr ("CALL_METHOD" , 2 , lineno = lineno ),
362
- Instr ("POP_TOP" , lineno = lineno ),
363
+ ArtificialInstr ("ROT_THREE" , lineno = lineno ),
364
+ ArtificialInstr ("ROT_THREE" , lineno = lineno ),
365
+ ArtificialInstr ("LOAD_CONST" , predicate_id , lineno = lineno ),
366
+ ArtificialInstr ("CALL_METHOD" , 2 , lineno = lineno ),
367
+ ArtificialInstr ("POP_TOP" , lineno = lineno ),
363
368
]
364
369
return predicate_id
365
370
@@ -405,19 +410,19 @@ def _instrument_compare_based_conditional_jump(
405
410
# We duplicate the values on top of the stack and report
406
411
# them to the tracer.
407
412
block [self ._COMPARE_OP_POS : self ._COMPARE_OP_POS ] = [
408
- Instr ("DUP_TOP_TWO" , lineno = lineno ),
409
- Instr ("LOAD_CONST" , self ._tracer , lineno = lineno ),
410
- Instr (
413
+ ArtificialInstr ("DUP_TOP_TWO" , lineno = lineno ),
414
+ ArtificialInstr ("LOAD_CONST" , self ._tracer , lineno = lineno ),
415
+ ArtificialInstr (
411
416
"LOAD_METHOD" ,
412
417
ExecutionTracer .executed_compare_predicate .__name__ ,
413
418
lineno = lineno ,
414
419
),
415
- Instr ("ROT_FOUR" , lineno = lineno ),
416
- Instr ("ROT_FOUR" , lineno = lineno ),
417
- Instr ("LOAD_CONST" , predicate_id , lineno = lineno ),
418
- Instr ("LOAD_CONST" , compare , lineno = lineno ),
419
- Instr ("CALL_METHOD" , 4 , lineno = lineno ),
420
- Instr ("POP_TOP" , lineno = lineno ),
420
+ ArtificialInstr ("ROT_FOUR" , lineno = lineno ),
421
+ ArtificialInstr ("ROT_FOUR" , lineno = lineno ),
422
+ ArtificialInstr ("LOAD_CONST" , predicate_id , lineno = lineno ),
423
+ ArtificialInstr ("LOAD_CONST" , compare , lineno = lineno ),
424
+ ArtificialInstr ("CALL_METHOD" , 4 , lineno = lineno ),
425
+ ArtificialInstr ("POP_TOP" , lineno = lineno ),
421
426
]
422
427
return predicate_id
423
428
@@ -445,18 +450,18 @@ def _instrument_exception_based_conditional_jump(
445
450
# We duplicate the values on top of the stack and report
446
451
# them to the tracer.
447
452
block [self ._JUMP_OP_POS : self ._JUMP_OP_POS ] = [
448
- Instr ("DUP_TOP_TWO" , lineno = lineno ),
449
- Instr ("LOAD_CONST" , self ._tracer , lineno = lineno ),
450
- Instr (
453
+ ArtificialInstr ("DUP_TOP_TWO" , lineno = lineno ),
454
+ ArtificialInstr ("LOAD_CONST" , self ._tracer , lineno = lineno ),
455
+ ArtificialInstr (
451
456
"LOAD_METHOD" ,
452
457
ExecutionTracer .executed_exception_match .__name__ ,
453
458
lineno = lineno ,
454
459
),
455
- Instr ("ROT_FOUR" , lineno = lineno ),
456
- Instr ("ROT_FOUR" , lineno = lineno ),
457
- Instr ("LOAD_CONST" , predicate_id , lineno = lineno ),
458
- Instr ("CALL_METHOD" , 3 , lineno = lineno ),
459
- Instr ("POP_TOP" , lineno = lineno ),
460
+ ArtificialInstr ("ROT_FOUR" , lineno = lineno ),
461
+ ArtificialInstr ("ROT_FOUR" , lineno = lineno ),
462
+ ArtificialInstr ("LOAD_CONST" , predicate_id , lineno = lineno ),
463
+ ArtificialInstr ("CALL_METHOD" , 3 , lineno = lineno ),
464
+ ArtificialInstr ("POP_TOP" , lineno = lineno ),
460
465
]
461
466
return predicate_id
462
467
@@ -473,15 +478,15 @@ def visit_entry_node(self, block: BasicBlock, code_object_id: int) -> None:
473
478
lineno = block [0 ].lineno
474
479
# Insert instructions at the beginning.
475
480
block [0 :0 ] = [
476
- Instr ("LOAD_CONST" , self ._tracer , lineno = lineno ),
477
- Instr (
481
+ ArtificialInstr ("LOAD_CONST" , self ._tracer , lineno = lineno ),
482
+ ArtificialInstr (
478
483
"LOAD_METHOD" ,
479
484
ExecutionTracer .executed_code_object .__name__ ,
480
485
lineno = lineno ,
481
486
),
482
- Instr ("LOAD_CONST" , code_object_id , lineno = lineno ),
483
- Instr ("CALL_METHOD" , 1 , lineno = lineno ),
484
- Instr ("POP_TOP" , lineno = lineno ),
487
+ ArtificialInstr ("LOAD_CONST" , code_object_id , lineno = lineno ),
488
+ ArtificialInstr ("CALL_METHOD" , 1 , lineno = lineno ),
489
+ ArtificialInstr ("POP_TOP" , lineno = lineno ),
485
490
]
486
491
487
492
def _instrument_for_loop (
@@ -537,37 +542,39 @@ def _instrument_for_loop(
537
542
entered , not_entered = self ._create_consecutive_blocks (
538
543
cfg .bytecode_cfg (), basic_block , 2
539
544
)
545
+ # TODO(fk) for_instr is not artificial but we changed it
546
+ # How to deal with this?
540
547
for_instr .arg = not_entered
541
548
542
549
entered .extend (
543
550
[
544
- Instr ("LOAD_CONST" , self ._tracer , lineno = lineno ),
545
- Instr (
551
+ ArtificialInstr ("LOAD_CONST" , self ._tracer , lineno = lineno ),
552
+ ArtificialInstr (
546
553
"LOAD_METHOD" ,
547
554
ExecutionTracer .executed_bool_predicate .__name__ ,
548
555
lineno = lineno ,
549
556
),
550
- Instr ("LOAD_CONST" , True , lineno = lineno ),
551
- Instr ("LOAD_CONST" , predicate_id , lineno = lineno ),
552
- Instr ("CALL_METHOD" , 2 , lineno = lineno ),
553
- Instr ("POP_TOP" , lineno = lineno ),
554
- Instr ("JUMP_ABSOLUTE" , for_loop_body , lineno = lineno ),
557
+ ArtificialInstr ("LOAD_CONST" , True , lineno = lineno ),
558
+ ArtificialInstr ("LOAD_CONST" , predicate_id , lineno = lineno ),
559
+ ArtificialInstr ("CALL_METHOD" , 2 , lineno = lineno ),
560
+ ArtificialInstr ("POP_TOP" , lineno = lineno ),
561
+ ArtificialInstr ("JUMP_ABSOLUTE" , for_loop_body , lineno = lineno ),
555
562
]
556
563
)
557
564
558
565
not_entered .extend (
559
566
[
560
- Instr ("LOAD_CONST" , self ._tracer , lineno = lineno ),
561
- Instr (
567
+ ArtificialInstr ("LOAD_CONST" , self ._tracer , lineno = lineno ),
568
+ ArtificialInstr (
562
569
"LOAD_METHOD" ,
563
570
ExecutionTracer .executed_bool_predicate .__name__ ,
564
571
lineno = lineno ,
565
572
),
566
- Instr ("LOAD_CONST" , False , lineno = lineno ),
567
- Instr ("LOAD_CONST" , predicate_id , lineno = lineno ),
568
- Instr ("CALL_METHOD" , 2 , lineno = lineno ),
569
- Instr ("POP_TOP" , lineno = lineno ),
570
- Instr ("JUMP_ABSOLUTE" , for_loop_exit , lineno = lineno ),
573
+ ArtificialInstr ("LOAD_CONST" , False , lineno = lineno ),
574
+ ArtificialInstr ("LOAD_CONST" , predicate_id , lineno = lineno ),
575
+ ArtificialInstr ("CALL_METHOD" , 2 , lineno = lineno ),
576
+ ArtificialInstr ("POP_TOP" , lineno = lineno ),
577
+ ArtificialInstr ("JUMP_ABSOLUTE" , for_loop_exit , lineno = lineno ),
571
578
]
572
579
)
573
580
@@ -622,15 +629,15 @@ def instrument_line(
622
629
The number of instructions inserted into the block
623
630
"""
624
631
inserted_instructions = [
625
- Instr ("LOAD_CONST" , self ._tracer , lineno = lineno ),
626
- Instr (
632
+ ArtificialInstr ("LOAD_CONST" , self ._tracer , lineno = lineno ),
633
+ ArtificialInstr (
627
634
"LOAD_METHOD" ,
628
635
self ._tracer .track_line_visit .__name__ ,
629
636
lineno = lineno ,
630
637
),
631
- Instr ("LOAD_CONST" , line_id , lineno = lineno ),
632
- Instr ("CALL_METHOD" , 1 , lineno = lineno ),
633
- Instr ("POP_TOP" , lineno = lineno ),
638
+ ArtificialInstr ("LOAD_CONST" , line_id , lineno = lineno ),
639
+ ArtificialInstr ("CALL_METHOD" , 1 , lineno = lineno ),
640
+ ArtificialInstr ("POP_TOP" , lineno = lineno ),
634
641
]
635
642
# Insert instructions at the beginning.
636
643
block [instr_index :instr_index ] = inserted_instructions
@@ -734,19 +741,21 @@ def _instrument_startswith_function(self, block: BasicBlock) -> None:
734
741
insert_pos = self ._STRING_FUNC_POS_WITH_ARG + 2
735
742
lineno = block [insert_pos ].lineno
736
743
block [insert_pos :insert_pos ] = [
737
- Instr ("DUP_TOP_TWO" , lineno = lineno ),
738
- Instr ("ROT_TWO" , lineno = lineno ),
739
- Instr ("BINARY_ADD" , lineno = lineno ),
740
- Instr ("LOAD_CONST" , self ._dynamic_constant_seeding , lineno = lineno ),
741
- Instr (
744
+ ArtificialInstr ("DUP_TOP_TWO" , lineno = lineno ),
745
+ ArtificialInstr ("ROT_TWO" , lineno = lineno ),
746
+ ArtificialInstr ("BINARY_ADD" , lineno = lineno ),
747
+ ArtificialInstr (
748
+ "LOAD_CONST" , self ._dynamic_constant_seeding , lineno = lineno
749
+ ),
750
+ ArtificialInstr (
742
751
"LOAD_METHOD" ,
743
752
self ._dynamic_constant_seeding .add_value .__name__ ,
744
753
lineno = lineno ,
745
754
),
746
- Instr ("ROT_THREE" , lineno = lineno ),
747
- Instr ("ROT_THREE" , lineno = lineno ),
748
- Instr ("CALL_METHOD" , 1 , lineno = lineno ),
749
- Instr ("POP_TOP" , lineno = lineno ),
755
+ ArtificialInstr ("ROT_THREE" , lineno = lineno ),
756
+ ArtificialInstr ("ROT_THREE" , lineno = lineno ),
757
+ ArtificialInstr ("CALL_METHOD" , 1 , lineno = lineno ),
758
+ ArtificialInstr ("POP_TOP" , lineno = lineno ),
750
759
]
751
760
self ._logger .info ("Instrumented startswith function" )
752
761
@@ -761,18 +770,20 @@ def _instrument_endswith_function(self, block: BasicBlock) -> None:
761
770
insert_pos = self ._STRING_FUNC_POS_WITH_ARG + 2
762
771
lineno = block [insert_pos ].lineno
763
772
block [insert_pos :insert_pos ] = [
764
- Instr ("DUP_TOP_TWO" , lineno = lineno ),
765
- Instr ("BINARY_ADD" , lineno = lineno ),
766
- Instr ("LOAD_CONST" , self ._dynamic_constant_seeding , lineno = lineno ),
767
- Instr (
773
+ ArtificialInstr ("DUP_TOP_TWO" , lineno = lineno ),
774
+ ArtificialInstr ("BINARY_ADD" , lineno = lineno ),
775
+ ArtificialInstr (
776
+ "LOAD_CONST" , self ._dynamic_constant_seeding , lineno = lineno
777
+ ),
778
+ ArtificialInstr (
768
779
"LOAD_METHOD" ,
769
780
DynamicConstantSeeding .add_value .__name__ ,
770
781
lineno = lineno ,
771
782
),
772
- Instr ("ROT_THREE" , lineno = lineno ),
773
- Instr ("ROT_THREE" , lineno = lineno ),
774
- Instr ("CALL_METHOD" , 1 , lineno = lineno ),
775
- Instr ("POP_TOP" , lineno = lineno ),
783
+ ArtificialInstr ("ROT_THREE" , lineno = lineno ),
784
+ ArtificialInstr ("ROT_THREE" , lineno = lineno ),
785
+ ArtificialInstr ("CALL_METHOD" , 1 , lineno = lineno ),
786
+ ArtificialInstr ("POP_TOP" , lineno = lineno ),
776
787
]
777
788
self ._logger .info ("Instrumented endswith function" )
778
789
@@ -788,18 +799,20 @@ def _instrument_string_function_without_arg(
788
799
insert_pos = self ._STRING_FUNC_POS_WITH_ARG + 2
789
800
lineno = block [insert_pos ].lineno
790
801
block [insert_pos :insert_pos ] = [
791
- Instr ("DUP_TOP" , lineno = lineno ),
792
- Instr ("LOAD_CONST" , self ._dynamic_constant_seeding , lineno = lineno ),
793
- Instr (
802
+ ArtificialInstr ("DUP_TOP" , lineno = lineno ),
803
+ ArtificialInstr (
804
+ "LOAD_CONST" , self ._dynamic_constant_seeding , lineno = lineno
805
+ ),
806
+ ArtificialInstr (
794
807
"LOAD_METHOD" ,
795
808
DynamicConstantSeeding .add_value_for_strings .__name__ ,
796
809
lineno = lineno ,
797
810
),
798
- Instr ("ROT_THREE" , lineno = lineno ),
799
- Instr ("ROT_THREE" , lineno = lineno ),
800
- Instr ("LOAD_CONST" , function_name , lineno = lineno ),
801
- Instr ("CALL_METHOD" , 2 , lineno = lineno ),
802
- Instr ("POP_TOP" , lineno = lineno ),
811
+ ArtificialInstr ("ROT_THREE" , lineno = lineno ),
812
+ ArtificialInstr ("ROT_THREE" , lineno = lineno ),
813
+ ArtificialInstr ("LOAD_CONST" , function_name , lineno = lineno ),
814
+ ArtificialInstr ("CALL_METHOD" , 2 , lineno = lineno ),
815
+ ArtificialInstr ("POP_TOP" , lineno = lineno ),
803
816
]
804
817
self ._logger .info ("Instrumented string function" )
805
818
@@ -827,26 +840,30 @@ def _instrument_compare_op(self, block: BasicBlock) -> None:
827
840
"""
828
841
lineno = block [self ._COMPARE_OP_POS ].lineno
829
842
block [self ._COMPARE_OP_POS : self ._COMPARE_OP_POS ] = [
830
- Instr ("DUP_TOP_TWO" , lineno = lineno ),
831
- Instr ("LOAD_CONST" , self ._dynamic_constant_seeding , lineno = lineno ),
832
- Instr (
843
+ ArtificialInstr ("DUP_TOP_TWO" , lineno = lineno ),
844
+ ArtificialInstr (
845
+ "LOAD_CONST" , self ._dynamic_constant_seeding , lineno = lineno
846
+ ),
847
+ ArtificialInstr (
833
848
"LOAD_METHOD" ,
834
849
DynamicConstantSeeding .add_value .__name__ ,
835
850
lineno = lineno ,
836
851
),
837
- Instr ("ROT_THREE" , lineno = lineno ),
838
- Instr ("ROT_THREE" , lineno = lineno ),
839
- Instr ("CALL_METHOD" , 1 , lineno = lineno ),
840
- Instr ("POP_TOP" , lineno = lineno ),
841
- Instr ("LOAD_CONST" , self ._dynamic_constant_seeding , lineno = lineno ),
842
- Instr (
852
+ ArtificialInstr ("ROT_THREE" , lineno = lineno ),
853
+ ArtificialInstr ("ROT_THREE" , lineno = lineno ),
854
+ ArtificialInstr ("CALL_METHOD" , 1 , lineno = lineno ),
855
+ ArtificialInstr ("POP_TOP" , lineno = lineno ),
856
+ ArtificialInstr (
857
+ "LOAD_CONST" , self ._dynamic_constant_seeding , lineno = lineno
858
+ ),
859
+ ArtificialInstr (
843
860
"LOAD_METHOD" ,
844
861
DynamicConstantSeeding .add_value .__name__ ,
845
862
lineno = lineno ,
846
863
),
847
- Instr ("ROT_THREE" , lineno = lineno ),
848
- Instr ("ROT_THREE" , lineno = lineno ),
849
- Instr ("CALL_METHOD" , 1 , lineno = lineno ),
850
- Instr ("POP_TOP" , lineno = lineno ),
864
+ ArtificialInstr ("ROT_THREE" , lineno = lineno ),
865
+ ArtificialInstr ("ROT_THREE" , lineno = lineno ),
866
+ ArtificialInstr ("CALL_METHOD" , 1 , lineno = lineno ),
867
+ ArtificialInstr ("POP_TOP" , lineno = lineno ),
851
868
]
852
869
self ._logger .debug ("Instrumented compare_op" )
0 commit comments