From 7b483f5ef8d2b785cda9973221db25f701b59753 Mon Sep 17 00:00:00 2001 From: "Gabriele N. Tornetta" Date: Fri, 8 May 2026 18:30:48 +0100 Subject: [PATCH] perf: bypass validation for trusted InstrLocation and Instr construction MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add two fast-path factory methods that skip validation by using object.__new__ + direct slot assignment, for call sites where the inputs are already known to be valid: **InstrLocation._from_tuple** — replaces InstrLocation(...) at four internal sites where positions come from trusted sources (existing InstrLocation.lineno, SetLineno.lineno, first_lineno): - ConcreteBytecode.to_bytecode (fallback lineno-only location) - ConcreteBytecode._pack_location (propagated from existing location) - _ConvertBytecodeToConcrete.concrete_instructions (first_lineno seed and SetLineno-derived locations) **BaseInstr._from_trusted** — replaces Instr(name, arg, location=loc) in ConcreteBytecode.to_bytecode, where name/opcode/arg/location are all derived from already-validated ConcreteInstr objects. CPU own-time profile data: | Hotspot | Before | After | |---|---|---| | `ConcreteBytecode.to_bytecode` | 5.98% | 5.07% | | `Instr._check_arg` | 2.87% | eliminated | | `BaseInstr._set` (via to_bytecode) | 1.48% | eliminated | | `BaseInstr._from_trusted` | — | <1% (not in top 20) | Throughput (Bytecode.from_code().to_code() on dis module's code object, 1 second timed window, 5 runs): | | r/s range | |---|---| | Before | 103–108 | | After | 109–114 | --- src/bytecode/concrete.py | 18 +++++++++++++----- src/bytecode/instr.py | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/src/bytecode/concrete.py b/src/bytecode/concrete.py index 6a21d186..f00a8f10 100644 --- a/src/bytecode/concrete.py +++ b/src/bytecode/concrete.py @@ -575,7 +575,9 @@ def _assemble_locations( _, size, lineno, old_location = next(iter_in) # Infer the line if location is None - old_location = old_location or InstrLocation(lineno, None, None, None) + old_location = old_location or InstrLocation._from_tuple( + lineno, None, None, None + ) lineno = first_lineno # We track the last set lineno to be able to compute deltas @@ -930,14 +932,18 @@ def to_bytecode( else: arg = c_arg - location = c_instr.location or InstrLocation(lineno, None, None, None) + location = c_instr.location or InstrLocation._from_tuple( + lineno, None, None, None + ) if jump_target is not None: arg = PLACEHOLDER_LABEL instr_index = len(instructions) jumps.append((instr_index, jump_target)) - instructions.append(Instr(c_instr.name, arg, location=location)) + instructions.append( + Instr._from_trusted(c_instr._name, c_instr._opcode, arg, location) + ) # We now insert the TryEnd entries if current_instr_offset in ex_end: @@ -1030,7 +1036,9 @@ def add(names: list[str], name: str) -> int: return index def concrete_instructions(self) -> None: - location = InstrLocation(self.bytecode.first_lineno, None, None, None) + location = InstrLocation._from_tuple( + self.bytecode.first_lineno, None, None, None + ) # Track instruction (index) using cell vars and free vars to be able to update # the index used once all the names are known. cell_instrs: list[int] = [] @@ -1086,7 +1094,7 @@ def concrete_instructions(self) -> None: continue if isinstance(instr, SetLineno): - location = InstrLocation(instr.lineno, None, None, None) + location = InstrLocation._from_tuple(instr.lineno, None, None, None) continue if isinstance(instr, TryBegin): diff --git a/src/bytecode/instr.py b/src/bytecode/instr.py index 9e043f3e..56240eac 100644 --- a/src/bytecode/instr.py +++ b/src/bytecode/instr.py @@ -621,6 +621,22 @@ def from_positions(cls, position: dis.Positions) -> InstrLocation: # type: igno position.end_col_offset, ) + @classmethod + def _from_tuple( + cls, + lineno: Optional[int], + end_lineno: Optional[int], + col_offset: Optional[int], + end_col_offset: Optional[int], + ) -> InstrLocation: + """Fast path for trusted position data (e.g. from co_positions()).""" + new = object.__new__(cls) + object.__setattr__(new, "lineno", lineno) + object.__setattr__(new, "end_lineno", end_lineno) + object.__setattr__(new, "col_offset", col_offset) + object.__setattr__(new, "end_col_offset", end_col_offset) + return new + class SetLineno: __slots__ = ("_lineno",) @@ -819,6 +835,22 @@ def copy(self: T) -> T: new._location = self._location return new + @classmethod + def _from_trusted( + cls: type[T], + name: str, + opcode: int, + arg: A, + location: Optional[InstrLocation], + ) -> T: + """Fast path for internal construction from already-validated data.""" + new = object.__new__(cls) + new._name = name + new._opcode = opcode + new._arg = arg + new._location = location + return new + def has_jump(self) -> bool: return self._has_jump(self._opcode)