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