Skip to content

Commit 2a71001

Browse files
committed
Modernize CALL (not too happy with it)
1 parent a0d4ece commit 2a71001

File tree

3 files changed

+42
-29
lines changed

3 files changed

+42
-29
lines changed

Python/bytecodes.c

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2354,10 +2354,10 @@ dummy_func(
23542354

23552355
// Cache layout: counter/1, func_version/2, min_args/1
23562356
// Neither CALL_INTRINSIC_1 nor CALL_FUNCTION_EX are members!
2357-
// family(call, INLINE_CACHE_ENTRIES_CALL) = {
2358-
// CALL,
2359-
// CALL_BOUND_METHOD_EXACT_ARGS,
2360-
// CALL_PY_EXACT_ARGS,
2357+
family(call, INLINE_CACHE_ENTRIES_CALL) = {
2358+
CALL,
2359+
CALL_BOUND_METHOD_EXACT_ARGS,
2360+
CALL_PY_EXACT_ARGS,
23612361
// CALL_PY_WITH_DEFAULTS,
23622362
// CALL_NO_KW_TYPE_1,
23632363
// CALL_NO_KW_STR_1,
@@ -2373,10 +2373,15 @@ dummy_func(
23732373
// CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS,
23742374
// CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS,
23752375
// CALL_NO_KW_METHOD_DESCRIPTOR_FAST,
2376-
// };
2376+
};
23772377

2378-
// stack effect: (__0, __array[oparg] -- )
2379-
inst(CALL) {
2378+
// Stack is either
2379+
// [NULL, function, arg1, arg2, ...]
2380+
// or
2381+
// [method, self, arg1, arg2, ...]
2382+
// (Some args may be keywords, see KW_NAMES, which sets 'kwnames'.)
2383+
// It will be replaced with [result].
2384+
inst(CALL, (unused/1, unused/2, unused/1, thing1, thing2, unused[oparg] -- unused)) {
23802385
#if ENABLE_SPECIALIZATION
23812386
_PyCallCache *cache = (_PyCallCache *)next_instr;
23822387
if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {
@@ -2392,18 +2397,18 @@ dummy_func(
23922397
DECREMENT_ADAPTIVE_COUNTER(cache->counter);
23932398
#endif /* ENABLE_SPECIALIZATION */
23942399
int total_args, is_meth;
2395-
is_meth = is_method(stack_pointer, oparg);
2396-
PyObject *function = PEEK(oparg + 1);
2400+
is_meth = thing1 != NULL;
2401+
PyObject *function = thing2;
23972402
if (!is_meth && Py_TYPE(function) == &PyMethod_Type) {
23982403
PyObject *self = ((PyMethodObject *)function)->im_self;
2399-
PEEK(oparg+1) = Py_NewRef(self);
2404+
PEEK(oparg+1) = thing2 = Py_NewRef(self);
24002405
PyObject *meth = ((PyMethodObject *)function)->im_func;
2401-
PEEK(oparg+2) = Py_NewRef(meth);
2406+
PEEK(oparg+2) = thing1 = Py_NewRef(meth);
24022407
Py_DECREF(function);
24032408
is_meth = 1;
24042409
}
24052410
total_args = oparg + is_meth;
2406-
function = PEEK(total_args + 1);
2411+
function = is_meth ? thing1 : thing2;
24072412
int positional_args = total_args - KWNAMES_LEN();
24082413
// Check if the call can be inlined or not
24092414
if (Py_TYPE(function) == &PyFunction_Type &&
@@ -2412,13 +2417,14 @@ dummy_func(
24122417
{
24132418
int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(function))->co_flags;
24142419
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(function));
2420+
// Manipulate stack directly since we leave using DISPATCH_INLINED().
24152421
STACK_SHRINK(total_args);
24162422
_PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit(
24172423
tstate, (PyFunctionObject *)function, locals,
24182424
stack_pointer, positional_args, kwnames
24192425
);
24202426
kwnames = NULL;
2421-
STACK_SHRINK(2-is_meth);
2427+
STACK_SHRINK(2 - is_meth);
24222428
// The frame has stolen all the arguments from the stack,
24232429
// so there is no need to clean them up.
24242430
if (new_frame == NULL) {
@@ -2431,30 +2437,32 @@ dummy_func(
24312437
PyObject *res;
24322438
if (cframe.use_tracing) {
24332439
res = trace_call_function(
2434-
tstate, function, stack_pointer-total_args,
2440+
tstate, function, stack_pointer - total_args,
24352441
positional_args, kwnames);
24362442
}
24372443
else {
24382444
res = PyObject_Vectorcall(
2439-
function, stack_pointer-total_args,
2445+
function, stack_pointer - total_args,
24402446
positional_args | PY_VECTORCALL_ARGUMENTS_OFFSET,
24412447
kwnames);
24422448
}
24432449
kwnames = NULL;
24442450
assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
24452451
Py_DECREF(function);
2452+
// Manipulate stack directly since we leave using DISPATCH().
24462453
/* Clear the stack */
24472454
STACK_SHRINK(total_args);
24482455
for (int i = 0; i < total_args; i++) {
24492456
Py_DECREF(stack_pointer[i]);
24502457
}
2451-
STACK_SHRINK(2-is_meth);
2458+
STACK_SHRINK(2 - is_meth);
24522459
PUSH(res);
24532460
if (res == NULL) {
24542461
goto error;
24552462
}
24562463
JUMPBY(INLINE_CACHE_ENTRIES_CALL);
24572464
CHECK_EVAL_BREAKER();
2465+
DISPATCH(); // Prevents generator emitting the epologue.
24582466
}
24592467

24602468
// Start out with [NULL, method, arg1, arg2, ...]

Python/generated_cases.c.h

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

Python/opcode_metadata.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ _PyOpcode_num_popped(int opcode, int oparg, bool jump) {
287287
case KW_NAMES:
288288
return 0;
289289
case CALL:
290-
return -1;
290+
return oparg + 2;
291291
case CALL_BOUND_METHOD_EXACT_ARGS:
292292
return oparg + 2;
293293
case CALL_PY_EXACT_ARGS:
@@ -633,7 +633,7 @@ _PyOpcode_num_pushed(int opcode, int oparg, bool jump) {
633633
case KW_NAMES:
634634
return 0;
635635
case CALL:
636-
return -1;
636+
return 1;
637637
case CALL_BOUND_METHOD_EXACT_ARGS:
638638
return 1;
639639
case CALL_PY_EXACT_ARGS:
@@ -842,7 +842,7 @@ struct opcode_metadata {
842842
[LOAD_ATTR_METHOD_NO_DICT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC00000000 },
843843
[LOAD_ATTR_METHOD_LAZY_DICT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC00000000 },
844844
[KW_NAMES] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
845-
[CALL] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
845+
[CALL] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC000 },
846846
[CALL_BOUND_METHOD_EXACT_ARGS] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC000 },
847847
[CALL_PY_EXACT_ARGS] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC000 },
848848
[CALL_PY_WITH_DEFAULTS] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },

0 commit comments

Comments
 (0)