Skip to content

Commit e2039d0

Browse files
committed
refactor: less redundancy in branch_trails
The old list structure could have multiple equal entries in the list. Reversing and using a dict lets us build the set of offsets directly.
1 parent c177731 commit e2039d0

File tree

2 files changed

+22
-21
lines changed

2 files changed

+22
-21
lines changed

coverage/bytecode.py

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
from __future__ import annotations
77

8+
import collections
89
import dis
910

1011
from types import CodeType
@@ -98,7 +99,9 @@ def walk(
9899

99100

100101
TBranchTrail = tuple[set[TOffset], Optional[TArc]]
101-
TBranchTrails = dict[TOffset, list[TBranchTrail]]
102+
#TBranchTrails = dict[TOffset, list[TBranchTrail]]
103+
104+
TBranchTrails = dict[TOffset, dict[Optional[TArc], set[TOffset]]]
102105

103106

104107
def branch_trails(code: CodeType) -> TBranchTrails:
@@ -117,7 +120,7 @@ def branch_trails(code: CodeType) -> TBranchTrails:
117120
arc from the original instruction's line to the new source line.
118121
119122
"""
120-
the_trails: TBranchTrails = {}
123+
the_trails: TBranchTrails = collections.defaultdict(lambda:collections.defaultdict(set))
121124
iwalker = InstructionWalker(code)
122125
for inst in iwalker.walk(follow_jumps=False):
123126
if not inst.jump_target:
@@ -131,7 +134,7 @@ def branch_trails(code: CodeType) -> TBranchTrails:
131134
if from_line is None:
132135
continue
133136

134-
def walk_one_branch(start_at: TOffset) -> TBranchTrail:
137+
def walk_one_branch(start_at: TOffset) -> tuple[Optional[TArc], set[TOffset]]:
135138
# pylint: disable=cell-var-from-loop
136139
inst_offsets: set[TOffset] = set()
137140
to_line = None
@@ -146,27 +149,26 @@ def walk_one_branch(start_at: TOffset) -> TBranchTrail:
146149
to_line = -code.co_firstlineno
147150
break
148151
if to_line is not None:
149-
return inst_offsets, (from_line, to_line)
152+
return (from_line, to_line), inst_offsets
150153
else:
151-
return set(), None
154+
return None, set()
152155

153156
# Calculate two trails: one from the next instruction, and one from the
154157
# jump_target instruction.
155-
trails = [
156-
walk_one_branch(start_at=inst.offset + 2),
157-
walk_one_branch(start_at=inst.jump_target),
158-
]
158+
trails = collections.defaultdict(set)
159+
arc, offsets = walk_one_branch(start_at=inst.offset + 2)
160+
trails[arc].update(offsets)
161+
arc, offsets = walk_one_branch(start_at=inst.jump_target)
162+
trails[arc].update(offsets)
159163
the_trails[inst.offset] = trails
160164

161165
# Sometimes we get BRANCH_RIGHT or BRANCH_LEFT events from instructions
162166
# other than the original jump possibility instruction. Register each
163167
# trail under all of their offsets so we can pick up in the middle of a
164168
# trail if need be.
165-
for trail in trails:
166-
for offset in trail[0]:
167-
if offset not in the_trails:
168-
the_trails[offset] = []
169-
the_trails[offset].append(trail)
169+
for arc, offsets in trails.items():
170+
for offset in offsets:
171+
the_trails[offset][arc].update(offsets)
170172

171173
return the_trails
172174

coverage/sysmon.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -176,12 +176,11 @@ class CodeInfo:
176176
byte_to_line: dict[TOffset, TLineNo] | None
177177

178178
# Keys are start instruction offsets for branches.
179-
# Values are lists:
180-
# [
181-
# ([offset, offset, ...], (from_line, to_line)),
182-
# ([offset, offset, ...], (from_line, to_line)),
183-
# ]
184-
# Two possible trails from the branch point, left and right.
179+
# Values are dicts:
180+
# {
181+
# (from_line, to_line): {offset, offset, ...},
182+
# (from_line, to_line): {offset, offset, ...},
183+
# }
185184
branch_trails: TBranchTrails
186185

187186
# Always-jumps are bytecode offsets that do no work but move
@@ -449,7 +448,7 @@ def sysmon_branch_either(
449448

450449
# log(f"{dest_info = }")
451450
if dest_info is not None:
452-
for offsets, arc in dest_info:
451+
for arc, offsets in dest_info.items():
453452
if arc is None:
454453
continue
455454
if dests & offsets:

0 commit comments

Comments
 (0)