Skip to content

Commit 569c1d7

Browse files
committed
Modernize CALL (not too happy with it)
1 parent c6d56d4 commit 569c1d7

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
@@ -2366,10 +2366,10 @@ dummy_func(
23662366

23672367
// Cache layout: counter/1, func_version/2, min_args/1
23682368
// Neither CALL_INTRINSIC_1 nor CALL_FUNCTION_EX are members!
2369-
// family(call, INLINE_CACHE_ENTRIES_CALL) = {
2370-
// CALL,
2371-
// CALL_BOUND_METHOD_EXACT_ARGS,
2372-
// CALL_PY_EXACT_ARGS,
2369+
family(call, INLINE_CACHE_ENTRIES_CALL) = {
2370+
CALL,
2371+
CALL_BOUND_METHOD_EXACT_ARGS,
2372+
CALL_PY_EXACT_ARGS,
23732373
// CALL_PY_WITH_DEFAULTS,
23742374
// CALL_NO_KW_TYPE_1,
23752375
// CALL_NO_KW_STR_1,
@@ -2385,10 +2385,15 @@ dummy_func(
23852385
// CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS,
23862386
// CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS,
23872387
// CALL_NO_KW_METHOD_DESCRIPTOR_FAST,
2388-
// };
2388+
};
23892389

2390-
// stack effect: (__0, __array[oparg] -- )
2391-
inst(CALL) {
2390+
// Stack is either
2391+
// [NULL, function, arg1, arg2, ...]
2392+
// or
2393+
// [method, self, arg1, arg2, ...]
2394+
// (Some args may be keywords, see KW_NAMES, which sets 'kwnames'.)
2395+
// It will be replaced with [result].
2396+
inst(CALL, (unused/1, unused/2, unused/1, thing1, thing2, unused[oparg] -- unused)) {
23922397
#if ENABLE_SPECIALIZATION
23932398
_PyCallCache *cache = (_PyCallCache *)next_instr;
23942399
if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {
@@ -2404,18 +2409,18 @@ dummy_func(
24042409
DECREMENT_ADAPTIVE_COUNTER(cache->counter);
24052410
#endif /* ENABLE_SPECIALIZATION */
24062411
int total_args, is_meth;
2407-
is_meth = is_method(stack_pointer, oparg);
2408-
PyObject *function = PEEK(oparg + 1);
2412+
is_meth = thing1 != NULL;
2413+
PyObject *function = thing2;
24092414
if (!is_meth && Py_TYPE(function) == &PyMethod_Type) {
24102415
PyObject *self = ((PyMethodObject *)function)->im_self;
2411-
PEEK(oparg+1) = Py_NewRef(self);
2416+
PEEK(oparg+1) = thing2 = Py_NewRef(self);
24122417
PyObject *meth = ((PyMethodObject *)function)->im_func;
2413-
PEEK(oparg+2) = Py_NewRef(meth);
2418+
PEEK(oparg+2) = thing1 = Py_NewRef(meth);
24142419
Py_DECREF(function);
24152420
is_meth = 1;
24162421
}
24172422
total_args = oparg + is_meth;
2418-
function = PEEK(total_args + 1);
2423+
function = is_meth ? thing1 : thing2;
24192424
int positional_args = total_args - KWNAMES_LEN();
24202425
// Check if the call can be inlined or not
24212426
if (Py_TYPE(function) == &PyFunction_Type &&
@@ -2424,13 +2429,14 @@ dummy_func(
24242429
{
24252430
int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(function))->co_flags;
24262431
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(function));
2432+
// Manipulate stack directly since we leave using DISPATCH_INLINED().
24272433
STACK_SHRINK(total_args);
24282434
_PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit(
24292435
tstate, (PyFunctionObject *)function, locals,
24302436
stack_pointer, positional_args, kwnames
24312437
);
24322438
kwnames = NULL;
2433-
STACK_SHRINK(2-is_meth);
2439+
STACK_SHRINK(2 - is_meth);
24342440
// The frame has stolen all the arguments from the stack,
24352441
// so there is no need to clean them up.
24362442
if (new_frame == NULL) {
@@ -2443,30 +2449,32 @@ dummy_func(
24432449
PyObject *res;
24442450
if (cframe.use_tracing) {
24452451
res = trace_call_function(
2446-
tstate, function, stack_pointer-total_args,
2452+
tstate, function, stack_pointer - total_args,
24472453
positional_args, kwnames);
24482454
}
24492455
else {
24502456
res = PyObject_Vectorcall(
2451-
function, stack_pointer-total_args,
2457+
function, stack_pointer - total_args,
24522458
positional_args | PY_VECTORCALL_ARGUMENTS_OFFSET,
24532459
kwnames);
24542460
}
24552461
kwnames = NULL;
24562462
assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
24572463
Py_DECREF(function);
2464+
// Manipulate stack directly since we leave using DISPATCH().
24582465
/* Clear the stack */
24592466
STACK_SHRINK(total_args);
24602467
for (int i = 0; i < total_args; i++) {
24612468
Py_DECREF(stack_pointer[i]);
24622469
}
2463-
STACK_SHRINK(2-is_meth);
2470+
STACK_SHRINK(2 - is_meth);
24642471
PUSH(res);
24652472
if (res == NULL) {
24662473
goto error;
24672474
}
24682475
JUMPBY(INLINE_CACHE_ENTRIES_CALL);
24692476
CHECK_EVAL_BREAKER();
2477+
DISPATCH(); // Prevents generator emitting the epologue.
24702478
}
24712479

24722480
// 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)