Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
56133bb
Split `CALL_PY_EXACT_ARGS` into uops
gvanrossum Aug 5, 2023
907ff95
Fix merge so it works again (I think)
gvanrossum Aug 9, 2023
2c6be6d
Split into finer-grained uops
gvanrossum Aug 9, 2023
6d78ff2
Fix type error in stacking.py
gvanrossum Aug 10, 2023
0d8e66c
Add test
gvanrossum Aug 10, 2023
b75f30e
Add comment explaining _PUSH_FRAME's unused output effect
gvanrossum Aug 10, 2023
61c2822
Make PUSH_FRAME special case a little less myterious
gvanrossum Aug 10, 2023
f73ea90
Rename Instruction.write to write_case_body
gvanrossum Aug 10, 2023
12910fc
Move next_instr update to a more logical place
gvanrossum Aug 10, 2023
2fafa2c
Don't recompute macro cache offset
gvanrossum Aug 10, 2023
2717b07
Fold and refactor long line in stacking.py
gvanrossum Aug 10, 2023
e487908
Fold long lines in generate_cases.py
gvanrossum Aug 10, 2023
1d549af
Don't emit static assert to executor cases
gvanrossum Aug 10, 2023
f40fb1f
Factor away write_case_body (formerly Instruction.write)
gvanrossum Aug 10, 2023
4f6f8f8
Fold long lines
gvanrossum Aug 11, 2023
6facc8d
Make less of a special case of _PUSH_FRAME
gvanrossum Aug 11, 2023
94630d4
Stop special-casing _PUSH_FRAME altogether
gvanrossum Aug 11, 2023
cf8e2c0
Call _Py_EnterRecursivePy in _FRAME_PUSH
gvanrossum Aug 15, 2023
1e62876
Merge remote-tracking branch 'upstream/main' into call-uops
gvanrossum Aug 15, 2023
05af848
Introduce SAVE_CURRENT_IP uop per Mark's proposal
gvanrossum Aug 16, 2023
f6a72ae
DO NOT MERGE: Always use -Xuops
gvanrossum Aug 9, 2023
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
Prev Previous commit
Next Next commit
Introduce SAVE_CURRENT_IP uop per Mark's proposal
  • Loading branch information
gvanrossum committed Aug 16, 2023
commit 05af84805a04747c1de7a5b843041b8d55c31bee
10 changes: 8 additions & 2 deletions Include/internal/pycore_opcode_metadata.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Python/abstract_interp_cases.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 12 additions & 1 deletion Python/bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -2991,7 +2991,7 @@ dummy_func(
// Eventually this should be the only occurrence of this code.
frame->return_offset = 0;
assert(tstate->interp->eval_frame == NULL);
SAVE_FRAME_STATE(); // Signals to the code generator
_PyFrame_SetStackPointer(frame, stack_pointer);
new_frame->previous = frame;
CALL_STAT_INC(inlined_py_calls);
#if TIER_ONE
Expand All @@ -3013,6 +3013,7 @@ dummy_func(
_CHECK_STACK_SPACE +
_INIT_CALL_PY_EXACT_ARGS +
SAVE_IP + // Tier 2 only; special-cased oparg
SAVE_CURRENT_IP + // Sets frame->prev_instr
_PUSH_FRAME;

inst(CALL_PY_WITH_DEFAULTS, (unused/1, func_version/2, callable, self_or_null, args[oparg] -- unused)) {
Expand Down Expand Up @@ -3775,6 +3776,16 @@ dummy_func(
frame->prev_instr = ip_offset + oparg;
}

op(SAVE_CURRENT_IP, (--)) {
#if TIER_ONE
frame->prev_instr = next_instr - 1;
#endif
#if TIER_TWO
// Relies on a preceding SAVE_IP
frame->prev_instr--;
#endif
}

op(EXIT_TRACE, (--)) {
frame->prev_instr--; // Back up to just before destination
_PyFrame_SetStackPointer(frame, stack_pointer);
Expand Down
9 changes: 2 additions & 7 deletions Python/ceval_macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,16 +103,11 @@
DISPATCH_GOTO(); \
}

#define SAVE_FRAME_STATE() \
do { \
frame->prev_instr = next_instr - 1; \
_PyFrame_SetStackPointer(frame, stack_pointer); \
} while (0)

#define DISPATCH_INLINED(NEW_FRAME) \
do { \
assert(tstate->interp->eval_frame == NULL); \
SAVE_FRAME_STATE(); \
_PyFrame_SetStackPointer(frame, stack_pointer); \
frame->prev_instr = next_instr - 1; \
(NEW_FRAME)->previous = frame; \
frame = cframe.current_frame = (NEW_FRAME); \
CALL_STAT_INC(inlined_py_calls); \
Expand Down
8 changes: 0 additions & 8 deletions Python/executor.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,6 @@
#undef ENABLE_SPECIALIZATION
#define ENABLE_SPECIALIZATION 0

#undef SAVE_FRAME_STATE
#define SAVE_FRAME_STATE() \
do { \
/* Assume preceding SAVE_IP has set frame->prev_instr */ \
frame->prev_instr--; \
_PyFrame_SetStackPointer(frame, stack_pointer); \
} while (0)


_PyInterpreterFrame *
_PyUopExecute(_PyExecutorObject *executor, _PyInterpreterFrame *frame, PyObject **stack_pointer)
Expand Down
13 changes: 12 additions & 1 deletion Python/executor_cases.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 12 additions & 2 deletions Python/generated_cases.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Tools/cases_generator/flags.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ def variable_used_unspecialized(node: parsing.Node, name: str) -> bool:
if text == "#if":
if (
i + 1 < len(node.tokens)
and node.tokens[i + 1].text == "ENABLE_SPECIALIZATION"
and node.tokens[i + 1].text in ("ENABLE_SPECIALIZATION", "TIER_ONE")
):
skipping = True
elif text in ("#else", "#endif"):
Expand Down
4 changes: 1 addition & 3 deletions Tools/cases_generator/instructions.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ class Instruction:

# Computed by constructor
always_exits: str # If the block always exits, its last line; else ""
save_frame_state: bool # Whether the instruction uses SAVE_FRAME_STATE()
has_deopt: bool
cache_offset: int
cache_effects: list[parsing.CacheEffect]
Expand All @@ -84,7 +83,6 @@ def __init__(self, inst: parsing.InstDef):
self.block
)
self.always_exits = always_exits(self.block_text)
self.save_frame_state = variable_used(self.inst, "SAVE_FRAME_STATE")
self.has_deopt = variable_used(self.inst, "DEOPT_IF")
self.cache_effects = [
effect for effect in inst.inputs if isinstance(effect, parsing.CacheEffect)
Expand Down Expand Up @@ -122,7 +120,7 @@ def __init__(self, inst: parsing.InstDef):
def is_viable_uop(self) -> bool:
"""Whether this instruction is viable as a uop."""
dprint: typing.Callable[..., None] = lambda *args, **kwargs: None
if "PUSH_FRAME" in self.name:
if "FRAME" in self.name:
dprint = print

if self.name == "EXIT_TRACE":
Expand Down
16 changes: 11 additions & 5 deletions Tools/cases_generator/stacking.py
Original file line number Diff line number Diff line change
Expand Up @@ -324,10 +324,10 @@ def write_macro_instr(
out.emit(f"PREDICTED({mac.name});")
out.static_assert_family_size(mac.name, family, mac.cache_offset)
try:
write_components(parts, out, TIER_ONE, mac.cache_offset)
next_instr_is_set = write_components(parts, out, TIER_ONE, mac.cache_offset)
except AssertionError as err:
raise AssertionError(f"Error writing macro {mac.name}") from err
if not parts[-1].instr.always_exits and not parts[-1].instr.save_frame_state:
if not parts[-1].instr.always_exits and not next_instr_is_set:
if mac.cache_offset:
out.emit(f"next_instr += {mac.cache_offset};")
out.emit("DISPATCH();")
Expand All @@ -338,7 +338,7 @@ def write_components(
out: Formatter,
tier: Tiers,
cache_offset: int,
) -> None:
) -> bool:
managers = get_managers(parts)

all_vars: dict[str, StackEffect] = {}
Expand All @@ -359,6 +359,7 @@ def write_components(
for name, eff in all_vars.items():
out.declare(eff, None)

next_instr_is_set = False
for mgr in managers:
if len(parts) > 1:
out.emit(f"// {mgr.instr.name}")
Expand All @@ -379,11 +380,14 @@ def write_components(
poke.as_stack_effect(lax=True),
)

if mgr.instr.save_frame_state:
if mgr.instr.name == "_PUSH_FRAME":
# Adjust stack to min_offset (input effects materialized)
out.stack_adjust(mgr.min_offset.deep, mgr.min_offset.high)
# Use clone() since adjust_inverse() mutates final_offset
mgr.adjust_inverse(mgr.final_offset.clone())

if mgr.instr.name == "SAVE_CURRENT_IP":
next_instr_is_set = True
if cache_offset:
out.emit(f"next_instr += {cache_offset};")

Expand All @@ -393,7 +397,7 @@ def write_components(
with out.block(""):
mgr.instr.write_body(out, -4, mgr.active_caches, tier)

if mgr is managers[-1] and not mgr.instr.save_frame_state:
if mgr is managers[-1] and not next_instr_is_set:
# TODO: Explain why this adjustment is needed.
out.stack_adjust(mgr.final_offset.deep, mgr.final_offset.high)
# Use clone() since adjust_inverse() mutates final_offset
Expand All @@ -406,6 +410,8 @@ def write_components(
poke.effect,
)

return next_instr_is_set


def write_single_instr_for_abstract_interp(
instr: Instruction, out: Formatter
Expand Down