Skip to content

Commit 8bf35e4

Browse files
authored
perf: avoid redundant validation in copy() and __iter__ (#193)
BaseInstr.copy() previously reconstructed instructions via __init__, triggering the full _set → _check_arg validation chain on every copy even though the source instruction is already known to be valid. Replace with object.__new__ + direct slot assignment to bypass validation entirely. _BaseBytecodeList.__iter__ ran _check_instr on every yielded item, but Bytecode.__iter__ (which calls this via super()) was already doing the same check — a redundant double-validation on every iteration. Profiling shows: - Instr._check_arg own time: 7.85% → 3.13% (−4.72%) - BaseInstr._set own time: 2.57% → 1.37% (−1.20%) - _BaseBytecodeList.__iter__ eliminated (was 2.18%)
1 parent 66584dc commit 8bf35e4

2 files changed

Lines changed: 6 additions & 7 deletions

File tree

src/bytecode/bytecode.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -164,12 +164,6 @@ def legalize(self) -> None:
164164
for i in reversed(lineno_pos):
165165
del self[i]
166166

167-
def __iter__(self) -> Iterator[U]:
168-
instructions = super().__iter__()
169-
for instr in instructions:
170-
self._check_instr(instr)
171-
yield instr
172-
173167
def _check_instr(self, instr):
174168
raise NotImplementedError()
175169

src/bytecode/instr.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -812,7 +812,12 @@ def pre_and_post_stack_effect(self, jump: Optional[bool] = None) -> tuple[int, i
812812
return (_effect, 0)
813813

814814
def copy(self: T) -> T:
815-
return self.__class__(self._name, self._arg, location=self._location)
815+
new = object.__new__(self.__class__)
816+
new._name = self._name
817+
new._opcode = self._opcode
818+
new._arg = self._arg
819+
new._location = self._location
820+
return new
816821

817822
def has_jump(self) -> bool:
818823
return self._has_jump(self._opcode)

0 commit comments

Comments
 (0)