Skip to content

Commit

Permalink
snapshot: 3.11
Browse files Browse the repository at this point in the history
  • Loading branch information
pulkin committed Feb 4, 2024
1 parent dfb769d commit a2a172b
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 18 deletions.
19 changes: 14 additions & 5 deletions pyteleport/bytecode/opcodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@
first of all, cache is stored right in the bytecode following some of the instructions. This means
that some instruction occupy more space (as opposed to two bytes per instruction before).
Second, all function calls are now processed through the CALL instruction, (CALL_FUNCTION_EX still avail).
Third, LOAD_GLOBAL falls victim to loading (non-)class methods which mess with NULLs on the value stack.
Third, LOAD_GLOBAL falls victim to loading (non-)class methods which mess with NULLs on the value stack
(it was LOAD_METHOD's job prior to this version).
"""
python_feature_pre_call = _python_version >= 0x030B
python_feature_cache = _python_version >= 0x030B
Expand All @@ -49,12 +50,20 @@
)
resuming = tuple(
opmap[i]
for i in (
"GEN_START", # 3.10+
)
for i in ("GEN_START",)
if i in opmap
)
call_function = tuple(
i
for name, i in opmap.items()
if "CALL_FUNCTION" in name
)
call_method = tuple(
opmap[i]
for i in ("CALL", "CALL_METHOD")
if i in opmap
)
del opmap # cleanup
del opmap


def guess_entering_stack_size(opcode: int) -> int:
Expand Down
19 changes: 6 additions & 13 deletions pyteleport/snapshot.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,8 @@
from .frame import FrameWrapper
from .bytecode import disassemble
from .util import log_bytecode
from .bytecode.opcodes import CALL_FUNCTION_EX, LOAD_CONST, YIELD_VALUE
from .bytecode.opcodes import CALL_FUNCTION_EX, LOAD_CONST, YIELD_VALUE, call_function, call_method, python_feature_block_stack
from .primitives import NULL
from .bytecode.opcodes import python_feature_pre_call

if python_feature_pre_call:
from .bytecode import CALL
else:
from .bytecode.opcodes import CALL_METHOD, CALL_FUNCTION, CALL_FUNCTION_KW


class FrameStackException(ValueError):
Expand Down Expand Up @@ -251,18 +245,17 @@ def snapshot(topmost_frame, stack_method="predict"):
stack_size = len(vstack)
called = None

elif fs.current_opcode is CALL_METHOD:
# ordinary frame, stack size unknown
# use bytecode heuristics
elif fs.current_opcode in call_method:
# TOS + 2 is a callable
stack_size = predict_stack_size(frame)
vstack = frame_wrapper.get_value_stack(stack_size + 2)
if vstack[-2] is not NULL:
called = vstack[-2] # bound method
else:
called = vstack[-1]

elif fs.current_opcode in (CALL_FUNCTION, CALL_FUNCTION_KW, CALL_FUNCTION_EX):
# same as above, TOS+1 is "guaranteed: to be callable
elif fs.current_opcode in call_function:
# TOS + 1 is a callable
stack_size = predict_stack_size(frame)
vstack = frame_wrapper.get_value_stack(stack_size + 1)
called = vstack[-1]
Expand All @@ -276,7 +269,7 @@ def snapshot(topmost_frame, stack_method="predict"):
v_stack=vstack[:stack_size],
v_locals=frame_wrapper.get_locals(),
v_cells=frame_wrapper.get_cells(),
block_stack=frame_wrapper.get_block_stack(),
block_stack=frame_wrapper.get_block_stack() if python_feature_block_stack else None,
tos_plus_one=called,
)

Expand Down

0 comments on commit a2a172b

Please sign in to comment.