Skip to content

Commit 70e0a28

Browse files
authored
GH-103082: Turn on branch events for FOR_ITER instructions. (#103507)
Turn on branch events for FOR_ITER instructions.
1 parent 59e0de4 commit 70e0a28

File tree

2 files changed

+73
-0
lines changed

2 files changed

+73
-0
lines changed

Lib/test/test_monitoring.py

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1011,6 +1011,77 @@ def func3():
10111011
('line', 'func3', 6)])
10121012

10131013

1014+
def line_from_offset(code, offset):
1015+
for start, end, line in code.co_lines():
1016+
if start <= offset < end:
1017+
return line - code.co_firstlineno
1018+
return -1
1019+
1020+
class JumpRecorder:
1021+
1022+
event_type = E.JUMP
1023+
name = "jump"
1024+
1025+
def __init__(self, events):
1026+
self.events = events
1027+
1028+
def __call__(self, code, from_, to):
1029+
from_line = line_from_offset(code, from_)
1030+
to_line = line_from_offset(code, to)
1031+
self.events.append((self.name, code.co_name, from_line, to_line))
1032+
1033+
1034+
class BranchRecorder(JumpRecorder):
1035+
1036+
event_type = E.BRANCH
1037+
name = "branch"
1038+
1039+
1040+
JUMP_AND_BRANCH_RECORDERS = JumpRecorder, BranchRecorder
1041+
JUMP_BRANCH_AND_LINE_RECORDERS = JumpRecorder, BranchRecorder, LineRecorder
1042+
1043+
class TestBranchAndJumpEvents(CheckEvents):
1044+
maxDiff = None
1045+
1046+
def test_loop(self):
1047+
1048+
def func():
1049+
x = 1
1050+
for a in range(2):
1051+
if a:
1052+
x = 4
1053+
else:
1054+
x = 6
1055+
1056+
self.check_events(func, recorders = JUMP_AND_BRANCH_RECORDERS, expected = [
1057+
('branch', 'func', 2, 2),
1058+
('branch', 'func', 3, 6),
1059+
('jump', 'func', 6, 2),
1060+
('branch', 'func', 2, 2),
1061+
('branch', 'func', 3, 4),
1062+
('jump', 'func', 4, 2),
1063+
('branch', 'func', 2, 2)])
1064+
1065+
1066+
self.check_events(func, recorders = JUMP_BRANCH_AND_LINE_RECORDERS, expected = [
1067+
('line', 'check_events', 10),
1068+
('line', 'func', 1),
1069+
('line', 'func', 2),
1070+
('branch', 'func', 2, 2),
1071+
('line', 'func', 3),
1072+
('branch', 'func', 3, 6),
1073+
('line', 'func', 6),
1074+
('jump', 'func', 6, 2),
1075+
('branch', 'func', 2, 2),
1076+
('line', 'func', 3),
1077+
('branch', 'func', 3, 4),
1078+
('line', 'func', 4),
1079+
('jump', 'func', 4, 2),
1080+
('branch', 'func', 2, 2),
1081+
('line', 'func', 2),
1082+
('line', 'check_events', 11)])
1083+
1084+
10141085
class TestSetGetEvents(MonitoringTestBase, unittest.TestCase):
10151086

10161087
def test_global(self):

Python/instrumentation.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ static const uint8_t INSTRUMENTED_OPCODES[256] = {
105105
[INSTRUMENTED_END_FOR] = INSTRUMENTED_END_FOR,
106106
[END_SEND] = INSTRUMENTED_END_SEND,
107107
[INSTRUMENTED_END_SEND] = INSTRUMENTED_END_SEND,
108+
[FOR_ITER] = INSTRUMENTED_FOR_ITER,
109+
[INSTRUMENTED_FOR_ITER] = INSTRUMENTED_FOR_ITER,
108110

109111
[INSTRUMENTED_LINE] = INSTRUMENTED_LINE,
110112
[INSTRUMENTED_INSTRUCTION] = INSTRUMENTED_INSTRUCTION,

0 commit comments

Comments
 (0)