Skip to content
This repository was archived by the owner on Feb 13, 2025. It is now read-only.

Commit 13c8e1b

Browse files
authored
Stackless issue #290: bpo-36974, PEP 590 Vectorcall-protocol
Adapt Stackless Python to the new Vectorcall protocol introduced by upstream commit aacc77f. This changes changes the Stackless protocol to support Vectorcall functions. It also updates code in pricklpit.c to correctly initialize wrapper types. This avoids assertion failures introduced by upstream commit be718c3 (not yet merged).
1 parent 3eb9f00 commit 13c8e1b

13 files changed

Lines changed: 140 additions & 88 deletions

File tree

Include/cpython/abstract.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
# error "this header file must not be included directly"
33
#endif
44

5+
#include "stackless_api.h"
6+
57
#ifdef __cplusplus
68
extern "C" {
79
#endif
@@ -125,7 +127,10 @@ _PyObject_Vectorcall(PyObject *callable, PyObject *const *args,
125127
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
126128
return _PyObject_MakeTpCall(callable, args, nargs, kwnames);
127129
}
130+
STACKLESS_GETARG();
131+
STACKLESS_VECTORCALL_BEFORE(func);
128132
PyObject *res = func(callable, args, nargsf, kwnames);
133+
STACKLESS_VECTORCALL_AFTER(func);
129134
return _Py_CheckFunctionResult(callable, res, NULL);
130135
}
131136

Include/cpython/slp_structs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,7 @@ PyAPI_DATA(PyTypeObject) PyChannel_Type;
317317
******************************************************/
318318

319319
#ifndef _PyStackless_TRY_STACKLESS
320-
PyAPI_DATA(int * const) _PyStackless__TryStacklessPtr;
320+
PyAPI_DATA(intptr_t * const) _PyStackless__TryStacklessPtr;
321321
#define _PyStackless_TRY_STACKLESS (*_PyStackless__TryStacklessPtr)
322322
#endif
323323
#ifndef STACKLESS__GETARG_ASSERT

Include/internal/pycore_slp_pystate.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ struct _stackless_runtime_state {
7979
* As long as the GIL is shared between sub-interpreters,
8080
* try_stackless can be a field in the runtime state.
8181
*/
82-
int try_stackless;
82+
intptr_t try_stackless;
8383

8484
/* Used to manage free C-stack objects, see stacklesseval.c */
8585
int cstack_cachecount;

Include/stackless_api.h

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -462,26 +462,46 @@ STACKLESS_RETRACT()
462462

463463
#define STACKLESS_GETARG() \
464464
int stackless = (STACKLESS__GETARG_ASSERT, \
465-
stackless = _PyStackless_TRY_STACKLESS, \
465+
stackless = (1 == _PyStackless_TRY_STACKLESS), \
466466
_PyStackless_TRY_STACKLESS = 0, \
467467
stackless)
468468

469469
#define STACKLESS_PROMOTE_ALL() ((void)(_PyStackless_TRY_STACKLESS = stackless, NULL))
470470

471471
#define STACKLESS_PROMOTE_FLAG(flag) \
472-
(stackless ? (_PyStackless_TRY_STACKLESS = (flag)) : 0)
472+
(stackless ? (_PyStackless_TRY_STACKLESS = !!(flag)) : 0)
473473

474474
#define STACKLESS_RETRACT() (_PyStackless_TRY_STACKLESS = 0)
475475

476476
#define STACKLESS_ASSERT() assert(!_PyStackless_TRY_STACKLESS)
477477

478+
#define STACKLESS_VECTORCALL_GETARG(func) \
479+
int stackless = (STACKLESS__GETARG_ASSERT, \
480+
stackless = ((intptr_t)((void(*)(void))(func)) == _PyStackless_TRY_STACKLESS), \
481+
_PyStackless_TRY_STACKLESS = 0, \
482+
stackless)
483+
484+
#define STACKLESS_VECTORCALL_BEFORE(func) \
485+
(stackless ? (_PyStackless_TRY_STACKLESS = (intptr_t)((void(*)(void))(func))) : 0)
486+
487+
#define STACKLESS_VECTORCALL_AFTER(func) \
488+
do { \
489+
if (_PyStackless_TRY_STACKLESS) { \
490+
assert((intptr_t)((void(*)(void))(func)) == _PyStackless_TRY_STACKLESS); \
491+
_PyStackless_TRY_STACKLESS = 0; \
492+
} \
493+
} while(0)
494+
478495
#else /* STACKLESS */
479496
/* turn the stackless flag macros into dummies */
480497
#define STACKLESS_GETARG() int stackless = 0
481498
#define STACKLESS_PROMOTE_ALL() (stackless = 0)
482499
#define STACKLESS_PROMOTE_FLAG(flag) (stackless = 0)
483500
#define STACKLESS_RETRACT() assert(1)
484501
#define STACKLESS_ASSERT() assert(1)
502+
#define STACKLESS_VECTORCALL_GETARG(func) int stackless = 0
503+
#define STACKLESS_VECTORCALL_BEFORE(func) (stackless = 0)
504+
#define STACKLESS_VECTORCALL_AFTER(func) (stackless = 0)
485505
#endif
486506

487507
#define STACKLESS_PROMOTE_METHOD(obj, slot_name) \
@@ -494,6 +514,17 @@ STACKLESS_RETRACT()
494514
STACKLESS_PROMOTE_FLAG( \
495515
Py_TYPE(obj)->tp_flags & Py_TPFLAGS_HAVE_STACKLESS_CALL)
496516

517+
static inline PyObject *
518+
_slp_vectorcall(const int stackless, vectorcallfunc func, PyObject *callable, PyObject *const *args, size_t nargsf, PyObject *kwnames)
519+
{
520+
STACKLESS_VECTORCALL_BEFORE(func);
521+
PyObject * result = func(callable, args, nargsf, kwnames);
522+
STACKLESS_VECTORCALL_AFTER(func);
523+
return result;
524+
}
525+
526+
#define STACKLESS_VECTORCALL(func, callable, args, nargsf, kwnames) \
527+
_slp_vectorcall(stackless, (func), (callable), (args), (nargsf), (kwnames))
497528

498529
#ifdef STACKLESS
499530

0 commit comments

Comments
 (0)