Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions src/bytecode/concrete.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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] = []
Expand Down Expand Up @@ -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):
Expand Down
32 changes: 32 additions & 0 deletions src/bytecode/instr.py
Original file line number Diff line number Diff line change
Expand Up @@ -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",)
Expand Down Expand Up @@ -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)

Expand Down