@@ -2366,10 +2366,10 @@ dummy_func(
2366
2366
2367
2367
// Cache layout: counter/1, func_version/2, min_args/1
2368
2368
// 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 ,
2373
2373
// CALL_PY_WITH_DEFAULTS,
2374
2374
// CALL_NO_KW_TYPE_1,
2375
2375
// CALL_NO_KW_STR_1,
@@ -2385,10 +2385,15 @@ dummy_func(
2385
2385
// CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS,
2386
2386
// CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS,
2387
2387
// CALL_NO_KW_METHOD_DESCRIPTOR_FAST,
2388
- // };
2388
+ };
2389
2389
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 )) {
2392
2397
#if ENABLE_SPECIALIZATION
2393
2398
_PyCallCache * cache = (_PyCallCache * )next_instr ;
2394
2399
if (ADAPTIVE_COUNTER_IS_ZERO (cache -> counter )) {
@@ -2404,18 +2409,18 @@ dummy_func(
2404
2409
DECREMENT_ADAPTIVE_COUNTER (cache -> counter );
2405
2410
#endif /* ENABLE_SPECIALIZATION */
2406
2411
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 ;
2409
2414
if (!is_meth && Py_TYPE (function ) == & PyMethod_Type ) {
2410
2415
PyObject * self = ((PyMethodObject * )function )-> im_self ;
2411
- PEEK (oparg + 1 ) = Py_NewRef (self );
2416
+ PEEK (oparg + 1 ) = thing2 = Py_NewRef (self );
2412
2417
PyObject * meth = ((PyMethodObject * )function )-> im_func ;
2413
- PEEK (oparg + 2 ) = Py_NewRef (meth );
2418
+ PEEK (oparg + 2 ) = thing1 = Py_NewRef (meth );
2414
2419
Py_DECREF (function );
2415
2420
is_meth = 1 ;
2416
2421
}
2417
2422
total_args = oparg + is_meth ;
2418
- function = PEEK ( total_args + 1 ) ;
2423
+ function = is_meth ? thing1 : thing2 ;
2419
2424
int positional_args = total_args - KWNAMES_LEN ();
2420
2425
// Check if the call can be inlined or not
2421
2426
if (Py_TYPE (function ) == & PyFunction_Type &&
@@ -2424,13 +2429,14 @@ dummy_func(
2424
2429
{
2425
2430
int code_flags = ((PyCodeObject * )PyFunction_GET_CODE (function ))-> co_flags ;
2426
2431
PyObject * locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef (PyFunction_GET_GLOBALS (function ));
2432
+ // Manipulate stack directly since we leave using DISPATCH_INLINED().
2427
2433
STACK_SHRINK (total_args );
2428
2434
_PyInterpreterFrame * new_frame = _PyEvalFramePushAndInit (
2429
2435
tstate , (PyFunctionObject * )function , locals ,
2430
2436
stack_pointer , positional_args , kwnames
2431
2437
);
2432
2438
kwnames = NULL ;
2433
- STACK_SHRINK (2 - is_meth );
2439
+ STACK_SHRINK (2 - is_meth );
2434
2440
// The frame has stolen all the arguments from the stack,
2435
2441
// so there is no need to clean them up.
2436
2442
if (new_frame == NULL ) {
@@ -2443,30 +2449,32 @@ dummy_func(
2443
2449
PyObject * res ;
2444
2450
if (cframe .use_tracing ) {
2445
2451
res = trace_call_function (
2446
- tstate , function , stack_pointer - total_args ,
2452
+ tstate , function , stack_pointer - total_args ,
2447
2453
positional_args , kwnames );
2448
2454
}
2449
2455
else {
2450
2456
res = PyObject_Vectorcall (
2451
- function , stack_pointer - total_args ,
2457
+ function , stack_pointer - total_args ,
2452
2458
positional_args | PY_VECTORCALL_ARGUMENTS_OFFSET ,
2453
2459
kwnames );
2454
2460
}
2455
2461
kwnames = NULL ;
2456
2462
assert ((res != NULL ) ^ (_PyErr_Occurred (tstate ) != NULL ));
2457
2463
Py_DECREF (function );
2464
+ // Manipulate stack directly since we leave using DISPATCH().
2458
2465
/* Clear the stack */
2459
2466
STACK_SHRINK (total_args );
2460
2467
for (int i = 0 ; i < total_args ; i ++ ) {
2461
2468
Py_DECREF (stack_pointer [i ]);
2462
2469
}
2463
- STACK_SHRINK (2 - is_meth );
2470
+ STACK_SHRINK (2 - is_meth );
2464
2471
PUSH (res );
2465
2472
if (res == NULL ) {
2466
2473
goto error ;
2467
2474
}
2468
2475
JUMPBY (INLINE_CACHE_ENTRIES_CALL );
2469
2476
CHECK_EVAL_BREAKER ();
2477
+ DISPATCH (); // Prevents generator emitting the epologue.
2470
2478
}
2471
2479
2472
2480
// Start out with [NULL, method, arg1, arg2, ...]
0 commit comments