Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b9432ba

Browse files
committed
Cleanup CALL
1 parent 6407369 commit b9432ba

2 files changed

Lines changed: 79 additions & 89 deletions

File tree

Python/bytecodes.c

Lines changed: 38 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -2374,56 +2374,58 @@ dummy_func(
23742374
CALL_NO_KW_METHOD_DESCRIPTOR_FAST,
23752375
};
23762376

2377-
// Stack is either
2378-
// [NULL, function, arg1, arg2, ...]
2377+
// On entry, the stack is either
2378+
// [NULL, callable, arg1, arg2, ...]
23792379
// or
2380-
// [method, self, arg1, arg2, ...]
2380+
// [method, self, arg1, arg2, ...]
23812381
// (Some args may be keywords, see KW_NAMES, which sets 'kwnames'.)
2382-
// It will be replaced with [result].
2383-
inst(CALL, (unused/1, unused/2, unused/1, thing1, thing2, unused[oparg] -- unused)) {
2382+
// On exit, the stack is [result].
2383+
// When calling Python, inline the call using DISPATCH_INLINED().
2384+
inst(CALL, (unused/1, unused/2, unused/1, method, callable, args[oparg] -- res)) {
2385+
int is_meth = method != NULL;
2386+
int total_args = oparg;
2387+
if (is_meth) {
2388+
callable = method;
2389+
args--;
2390+
total_args++;
2391+
}
23842392
#if ENABLE_SPECIALIZATION
23852393
_PyCallCache *cache = (_PyCallCache *)next_instr;
23862394
if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {
23872395
assert(cframe.use_tracing == 0);
2388-
int is_meth = thing1 != NULL;
2389-
int nargs = oparg + is_meth;
2390-
PyObject *callable = PEEK(nargs + 1);
23912396
next_instr--;
2392-
_Py_Specialize_Call(callable, next_instr, nargs, kwnames);
2397+
_Py_Specialize_Call(callable, next_instr, total_args, kwnames);
23932398
DISPATCH_SAME_OPARG();
23942399
}
23952400
STAT_INC(CALL, deferred);
23962401
DECREMENT_ADAPTIVE_COUNTER(cache->counter);
23972402
#endif /* ENABLE_SPECIALIZATION */
2398-
int total_args, is_meth;
2399-
is_meth = thing1 != NULL;
2400-
PyObject *function = thing2;
2401-
if (!is_meth && Py_TYPE(function) == &PyMethod_Type) {
2402-
PyObject *self = ((PyMethodObject *)function)->im_self;
2403-
PEEK(oparg+1) = thing2 = Py_NewRef(self);
2404-
PyObject *meth = ((PyMethodObject *)function)->im_func;
2405-
PEEK(oparg+2) = thing1 = Py_NewRef(meth);
2406-
Py_DECREF(function);
2407-
is_meth = 1;
2408-
}
2409-
total_args = oparg + is_meth;
2410-
function = is_meth ? thing1 : thing2;
2403+
if (!is_meth && Py_TYPE(callable) == &PyMethod_Type) {
2404+
is_meth = 1; // For consistenct; it's dead, though
2405+
args--;
2406+
total_args++;
2407+
PyObject *self = ((PyMethodObject *)callable)->im_self;
2408+
args[0] = Py_NewRef(self);
2409+
method = ((PyMethodObject *)callable)->im_func;
2410+
args[-1] = Py_NewRef(method);
2411+
Py_DECREF(callable);
2412+
callable = method;
2413+
}
24112414
int positional_args = total_args - KWNAMES_LEN();
24122415
// Check if the call can be inlined or not
2413-
if (Py_TYPE(function) == &PyFunction_Type &&
2416+
if (Py_TYPE(callable) == &PyFunction_Type &&
24142417
tstate->interp->eval_frame == NULL &&
2415-
((PyFunctionObject *)function)->vectorcall == _PyFunction_Vectorcall)
2418+
((PyFunctionObject *)callable)->vectorcall == _PyFunction_Vectorcall)
24162419
{
2417-
int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(function))->co_flags;
2418-
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(function));
2419-
// Manipulate stack directly since we leave using DISPATCH_INLINED().
2420-
STACK_SHRINK(total_args);
2420+
int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable))->co_flags;
2421+
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable));
24212422
_PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit(
2422-
tstate, (PyFunctionObject *)function, locals,
2423-
stack_pointer, positional_args, kwnames
2423+
tstate, (PyFunctionObject *)callable, locals,
2424+
args, positional_args, kwnames
24242425
);
24252426
kwnames = NULL;
2426-
STACK_SHRINK(2 - is_meth);
2427+
// Manipulate stack directly since we leave using DISPATCH_INLINED().
2428+
STACK_SHRINK(oparg + 2);
24272429
// The frame has stolen all the arguments from the stack,
24282430
// so there is no need to clean them up.
24292431
if (new_frame == NULL) {
@@ -2433,35 +2435,25 @@ dummy_func(
24332435
DISPATCH_INLINED(new_frame);
24342436
}
24352437
/* Callable is not a normal Python function */
2436-
PyObject *res;
24372438
if (cframe.use_tracing) {
24382439
res = trace_call_function(
2439-
tstate, function, stack_pointer - total_args,
2440+
tstate, callable, args,
24402441
positional_args, kwnames);
24412442
}
24422443
else {
24432444
res = PyObject_Vectorcall(
2444-
function, stack_pointer - total_args,
2445+
callable, args,
24452446
positional_args | PY_VECTORCALL_ARGUMENTS_OFFSET,
24462447
kwnames);
24472448
}
24482449
kwnames = NULL;
24492450
assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
2450-
Py_DECREF(function);
2451-
// Manipulate stack directly since we leave using DISPATCH().
2452-
/* Clear the stack */
2453-
STACK_SHRINK(total_args);
2451+
Py_DECREF(callable);
24542452
for (int i = 0; i < total_args; i++) {
2455-
Py_DECREF(stack_pointer[i]);
2456-
}
2457-
STACK_SHRINK(2 - is_meth);
2458-
PUSH(res);
2459-
if (res == NULL) {
2460-
goto error;
2453+
Py_DECREF(args[i]);
24612454
}
2462-
JUMPBY(INLINE_CACHE_ENTRIES_CALL);
2455+
ERROR_IF(res == NULL, error);
24632456
CHECK_EVAL_BREAKER();
2464-
DISPATCH(); // Prevents generator emitting the epologue.
24652457
}
24662458

24672459
// Start out with [NULL, bound_method, arg1, arg2, ...]

Python/generated_cases.c.h

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

0 commit comments

Comments
 (0)