Skip to content

Commit 56133bb

Browse files
committed
Split CALL_PY_EXACT_ARGS into uops
This is only the first step for doing `CALL` in Tier 2. The next step involves tracing into the called code object. After that we'll have to do the remaining `CALL` specialization. Finally we'll have to tweak various things like `KW_NAMES`, and possibly move the `NULL` (for method calls) *above* the callable. But those are things for future PRs. Note: this moves setting `frame->return_offset` directly in front of `DISPATCH_INLINED()`, to make it easier to move it into `_PUSH_FRAME`.
1 parent a9caf9c commit 56133bb

File tree

9 files changed

+220
-60
lines changed

9 files changed

+220
-60
lines changed

Include/internal/pycore_opcode_metadata.h

Lines changed: 12 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/bytecodes.c

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -957,13 +957,13 @@ dummy_func(
957957
{
958958
PyGenObject *gen = (PyGenObject *)receiver;
959959
_PyInterpreterFrame *gen_frame = (_PyInterpreterFrame *)gen->gi_iframe;
960-
frame->return_offset = oparg;
961960
STACK_SHRINK(1);
962961
_PyFrame_StackPush(gen_frame, v);
963962
gen->gi_frame_state = FRAME_EXECUTING;
964963
gen->gi_exc_state.previous_item = tstate->exc_info;
965964
tstate->exc_info = &gen->gi_exc_state;
966965
SKIP_OVER(INLINE_CACHE_ENTRIES_SEND);
966+
frame->return_offset = oparg;
967967
DISPATCH_INLINED(gen_frame);
968968
}
969969
if (Py_IsNone(v) && PyIter_Check(receiver)) {
@@ -996,13 +996,13 @@ dummy_func(
996996
DEOPT_IF(gen->gi_frame_state >= FRAME_EXECUTING, SEND);
997997
STAT_INC(SEND, hit);
998998
_PyInterpreterFrame *gen_frame = (_PyInterpreterFrame *)gen->gi_iframe;
999-
frame->return_offset = oparg;
1000999
STACK_SHRINK(1);
10011000
_PyFrame_StackPush(gen_frame, v);
10021001
gen->gi_frame_state = FRAME_EXECUTING;
10031002
gen->gi_exc_state.previous_item = tstate->exc_info;
10041003
tstate->exc_info = &gen->gi_exc_state;
10051004
SKIP_OVER(INLINE_CACHE_ENTRIES_SEND);
1005+
frame->return_offset = oparg;
10061006
DISPATCH_INLINED(gen_frame);
10071007
}
10081008

@@ -2586,14 +2586,14 @@ dummy_func(
25862586
DEOPT_IF(gen->gi_frame_state >= FRAME_EXECUTING, FOR_ITER);
25872587
STAT_INC(FOR_ITER, hit);
25882588
_PyInterpreterFrame *gen_frame = (_PyInterpreterFrame *)gen->gi_iframe;
2589-
frame->return_offset = oparg;
25902589
_PyFrame_StackPush(gen_frame, Py_None);
25912590
gen->gi_frame_state = FRAME_EXECUTING;
25922591
gen->gi_exc_state.previous_item = tstate->exc_info;
25932592
tstate->exc_info = &gen->gi_exc_state;
25942593
SKIP_OVER(INLINE_CACHE_ENTRIES_FOR_ITER);
25952594
assert(next_instr[oparg].op.code == END_FOR ||
25962595
next_instr[oparg].op.code == INSTRUMENTED_END_FOR);
2596+
frame->return_offset = oparg;
25972597
DISPATCH_INLINED(gen_frame);
25982598
}
25992599

@@ -2944,7 +2944,7 @@ dummy_func(
29442944
GO_TO_INSTRUCTION(CALL_PY_EXACT_ARGS);
29452945
}
29462946

2947-
inst(CALL_PY_EXACT_ARGS, (unused/1, func_version/2, callable, self_or_null, args[oparg] -- unused)) {
2947+
op(_CHECK_CALL_PY_EXACT_ARGS, (func_version/2, callable, self_or_null, unused[oparg] -- method, callable, unused[oparg])) {
29482948
ASSERT_KWNAMES_IS_NULL();
29492949
DEOPT_IF(tstate->interp->eval_frame, CALL);
29502950
int argcount = oparg;
@@ -2958,19 +2958,36 @@ dummy_func(
29582958
PyCodeObject *code = (PyCodeObject *)func->func_code;
29592959
DEOPT_IF(code->co_argcount != argcount, CALL);
29602960
DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize), CALL);
2961+
}
2962+
2963+
op(_INIT_CALL_PY_EXACT_ARGS, (method, callable, args[oparg] -- new_frame: _PyInterpreterFrame*)) {
2964+
int is_meth = method != NULL;
2965+
int argcount = oparg;
2966+
if (is_meth) {
2967+
callable = method;
2968+
args--;
2969+
argcount++;
2970+
}
29612971
STAT_INC(CALL, hit);
2962-
_PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(tstate, func, argcount);
2972+
PyFunctionObject *func = (PyFunctionObject *)callable;
2973+
new_frame = _PyFrame_PushUnchecked(tstate, func, argcount);
29632974
for (int i = 0; i < argcount; i++) {
29642975
new_frame->localsplus[i] = args[i];
29652976
}
2966-
// Manipulate stack directly since we leave using DISPATCH_INLINED().
2967-
STACK_SHRINK(oparg + 2);
2968-
SKIP_OVER(INLINE_CACHE_ENTRIES_CALL);
2977+
}
2978+
2979+
op(_PUSH_FRAME, (new_frame: _PyInterpreterFrame* -- unused)) {
29692980
frame->return_offset = 0;
29702981
DISPATCH_INLINED(new_frame);
29712982
}
29722983

2973-
inst(CALL_PY_WITH_DEFAULTS, (unused/1, func_version/2, callable, self_or_null, args[oparg] -- unused)) {
2984+
macro(CALL_PY_EXACT_ARGS) =
2985+
unused/1 + // Skip over the counter
2986+
_CHECK_CALL_PY_EXACT_ARGS +
2987+
_INIT_CALL_PY_EXACT_ARGS +
2988+
_PUSH_FRAME;
2989+
2990+
inst(CALL_PY_WITH_DEFAULTS, (unused/1, func_version/2, method, callable, args[oparg] -- unused)) {
29742991
ASSERT_KWNAMES_IS_NULL();
29752992
DEOPT_IF(tstate->interp->eval_frame, CALL);
29762993
int argcount = oparg;

Python/executor.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,19 @@
3030
#undef ENABLE_SPECIALIZATION
3131
#define ENABLE_SPECIALIZATION 0
3232

33+
#undef DISPATCH_INLINED
34+
#define DISPATCH_INLINED(NEW_FRAME) \
35+
do { \
36+
assert(tstate->interp->eval_frame == NULL); \
37+
_PyFrame_SetStackPointer(frame, stack_pointer); \
38+
frame->prev_instr -= 1; \
39+
(NEW_FRAME)->previous = frame; \
40+
frame = tstate->cframe->current_frame = (NEW_FRAME); \
41+
CALL_STAT_INC(inlined_py_calls); \
42+
stack_pointer = _PyFrame_GetStackPointer(frame); \
43+
ip_offset = (_Py_CODEUNIT *)_PyFrame_GetCode(frame)->co_code_adaptive; \
44+
} while (0)
45+
3346

3447
_PyInterpreterFrame *
3548
_PyUopExecute(_PyExecutorObject *executor, _PyInterpreterFrame *frame, PyObject **stack_pointer)

Python/executor_cases.c.h

Lines changed: 61 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/generated_cases.c.h

Lines changed: 53 additions & 32 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)