Visitar URL original
Stackless issue #290: bpo-36974, PEP 590 Vectorcall-protocol · akruis/cpython@e9d9b3d · GitHub
Skip to content

Commit e9d9b3d

Browse files
committed
Stackless issue python#290: bpo-36974, PEP 590 Vectorcall-protocol
Re-add support for the Stackless protocol to C-API functions. All Vectorcall functions are called without soft switching. Therefore many Stackless test cases still fail.
1 parent 7a4aeef commit e9d9b3d

4 files changed

Lines changed: 52 additions & 75 deletions

File tree

‎Include/cpython/abstract.h‎

Lines changed: 3 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,6 +127,7 @@ _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();
128131
PyObject *res = func(callable, args, nargsf, kwnames);
129132
return _Py_CheckFunctionResult(callable, res, NULL);
130133
}

‎Objects/call.c‎

Lines changed: 43 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,6 @@ PyObject *
9191
_PyObject_FastCallDict(PyObject *callable, PyObject *const *args,
9292
size_t nargsf, PyObject *kwargs)
9393
{
94-
STACKLESS_GETARG();
95-
PyObject *result;
9694
/* _PyObject_FastCallDict() must not be called with an exception set,
9795
because it can clear it (directly or indirectly) and so the
9896
caller loses its exception */
@@ -110,6 +108,7 @@ _PyObject_FastCallDict(PyObject *callable, PyObject *const *args,
110108
return _PyObject_MakeTpCall(callable, args, nargs, kwargs);
111109
}
112110

111+
STACKLESS_GETARG();
113112
PyObject *res;
114113
if (kwargs == NULL) {
115114
res = func(callable, args, nargsf, NULL);
@@ -137,6 +136,7 @@ _PyObject_FastCallDict(PyObject *callable, PyObject *const *args,
137136
PyObject *
138137
_PyObject_MakeTpCall(PyObject *callable, PyObject *const *args, Py_ssize_t nargs, PyObject *keywords)
139138
{
139+
STACKLESS_GETARG();
140140
/* Slow path: build a temporary tuple for positional arguments and a
141141
* temporary dictionary for keyword arguments (if any) */
142142
ternaryfunc call = Py_TYPE(callable)->tp_call;
@@ -173,11 +173,19 @@ _PyObject_MakeTpCall(PyObject *callable, PyObject *const *args, Py_ssize_t nargs
173173
}
174174

175175
PyObject *result = NULL;
176-
if (Py_EnterRecursiveCall(" while calling a Python object") == 0)
176+
/* only do recursion adjustment if there is no danger of soft-switching.
177+
* Were a soft-switch to occur, the re-adjustment of the recursion depth
178+
* would happen for the wrong frame.
179+
*/
180+
if (stackless ||
181+
Py_EnterRecursiveCall(" while calling a Python object") == 0)
177182
{
183+
STACKLESS_PROMOTE(callable);
178184
result = call(callable, argstuple, kwdict);
179-
Py_LeaveRecursiveCall();
185+
if(!stackless)
186+
Py_LeaveRecursiveCall();
180187
}
188+
STACKLESS_ASSERT();
181189

182190
Py_DECREF(argstuple);
183191
if (kwdict != keywords) {
@@ -192,6 +200,7 @@ _PyObject_MakeTpCall(PyObject *callable, PyObject *const *args, Py_ssize_t nargs
192200
PyObject *
193201
PyVectorcall_Call(PyObject *callable, PyObject *tuple, PyObject *kwargs)
194202
{
203+
STACKLESS_GETARG();
195204
vectorcallfunc func = _PyVectorcall_Function(callable);
196205
if (func == NULL) {
197206
PyErr_Format(PyExc_TypeError, "'%.200s' object does not support vectorcall",
@@ -222,7 +231,6 @@ PyVectorcall_Call(PyObject *callable, PyObject *tuple, PyObject *kwargs)
222231
PyObject *
223232
PyObject_Call(PyObject *callable, PyObject *args, PyObject *kwargs)
224233
{
225-
STACKLESS_GETARG();
226234
ternaryfunc call;
227235
PyObject *result;
228236

@@ -242,37 +250,27 @@ PyObject_Call(PyObject *callable, PyObject *args, PyObject *kwargs)
242250
return cfunction_call_varargs(callable, args, kwargs);
243251
}
244252
else {
253+
STACKLESS_GETARG();
245254
call = callable->ob_type->tp_call;
246255
if (call == NULL) {
247256
PyErr_Format(PyExc_TypeError, "'%.200s' object is not callable",
248257
callable->ob_type->tp_name);
249258
return NULL;
250259
}
251260

252-
#ifdef STACKLESS
253-
/* only do recursion adjustment if there is no danger
254-
* of soft-switching, i.e. if we are not being called by
255-
* run_cframe. Were a soft-switch to occur, the re-adjustment
256-
* of the recursion depth would happen for the wrong frame.
261+
/* only do recursion adjustment if there is no danger of soft-switching.
262+
* Were a soft-switch to occur, the re-adjustment of the recursion depth
263+
* would happen for the wrong frame.
257264
*/
258-
if (!stackless)
259-
#endif
260-
if (Py_EnterRecursiveCall(" while calling a Python object"))
265+
if (!stackless && Py_EnterRecursiveCall(" while calling a Python object"))
261266
return NULL;
262267

263268
STACKLESS_PROMOTE(callable);
264269
result = (*call)(callable, args, kwargs);
265270
STACKLESS_ASSERT();
266271

267-
#ifdef STACKLESS
268-
/* only do recursion adjustment if there is no danger
269-
* of soft-switching, i.e. if we are not being called by
270-
* run_cframe. Were a soft-switch to occur, the re-adjustment
271-
* of the recursion depth would happen for the wrong frame.
272-
*/
273272
if (!stackless)
274-
#endif
275-
Py_LeaveRecursiveCall();
273+
Py_LeaveRecursiveCall();
276274

277275
return _Py_CheckFunctionResult(callable, result, NULL);
278276
}
@@ -526,15 +524,12 @@ _PyMethodDef_RawFastCallDict(PyMethodDef *method, PyObject *self,
526524
int flags = method->ml_flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_STACKLESS);
527525
PyObject *result = NULL;
528526

529-
#ifdef STACKLESS
530-
/* only do recursion adjustment if there is no danger
531-
* of soft-switching, i.e. if we are not being called by
532-
* run_cframe. Were a soft-switch to occur, the re-adjustment
533-
* of the recursion depth would happen for the wrong frame.
527+
/* only do recursion adjustment if there is no danger of soft-switching.
528+
* Were a soft-switch to occur, the re-adjustment of the recursion depth
529+
* would happen for the wrong frame.
534530
*/
535-
if (!stackless)
536-
#endif
537-
if (Py_EnterRecursiveCall(" while calling a Python object")) {
531+
if (!stackless &&
532+
Py_EnterRecursiveCall(" while calling a Python object")) {
538533
return NULL;
539534
}
540535

@@ -647,15 +642,8 @@ _PyMethodDef_RawFastCallDict(PyMethodDef *method, PyObject *self,
647642
method->ml_name);
648643

649644
exit:
650-
#ifdef STACKLESS
651-
/* only do recursion adjustment if there is no danger
652-
* of soft-switching, i.e. if we are not being called by
653-
* run_cframe. Were a soft-switch to occur, the re-adjustment
654-
* of the recursion depth would happen for the wrong frame.
655-
*/
656645
if (!stackless)
657-
#endif
658-
Py_LeaveRecursiveCall();
646+
Py_LeaveRecursiveCall();
659647
return result;
660648
}
661649

@@ -700,15 +688,12 @@ _PyMethodDef_RawFastCallKeywords(PyMethodDef *method, PyObject *self,
700688
Py_ssize_t nkwargs = kwnames == NULL ? 0 : PyTuple_GET_SIZE(kwnames);
701689
PyObject *result = NULL;
702690

703-
#ifdef STACKLESS
704-
/* only do recursion adjustment if there is no danger
705-
* of soft-switching, i.e. if we are not being called by
706-
* run_cframe. Were a soft-switch to occur, the re-adjustment
707-
* of the recursion depth would happen for the wrong frame.
691+
/* only do recursion adjustment if there is no danger of soft-switching.
692+
* Were a soft-switch to occur, the re-adjustment of the recursion depth
693+
* would happen for the wrong frame.
708694
*/
709-
if (!stackless)
710-
#endif
711-
if (Py_EnterRecursiveCall(" while calling a Python object")) {
695+
if (!stackless &&
696+
Py_EnterRecursiveCall(" while calling a Python object")) {
712697
return NULL;
713698
}
714699

@@ -819,15 +804,8 @@ _PyMethodDef_RawFastCallKeywords(PyMethodDef *method, PyObject *self,
819804
method->ml_name);
820805

821806
exit:
822-
#ifdef STACKLESS
823-
/* only do recursion adjustment if there is no danger
824-
* of soft-switching, i.e. if we are not being called by
825-
* run_cframe. Were a soft-switch to occur, the re-adjustment
826-
* of the recursion depth would happen for the wrong frame.
827-
*/
828807
if (!stackless)
829-
#endif
830-
Py_LeaveRecursiveCall();
808+
Py_LeaveRecursiveCall();
831809
return result;
832810
}
833811

@@ -864,26 +842,21 @@ cfunction_call_varargs(PyObject *func, PyObject *args, PyObject *kwargs)
864842

865843
assert(PyCFunction_GET_FLAGS(func) & METH_VARARGS);
866844
if (PyCFunction_GET_FLAGS(func) & METH_KEYWORDS) {
867-
#ifdef STACKLESS
868-
/* only do recursion adjustment if there is no danger
869-
* of soft-switching, i.e. if we are not being called by
870-
* run_cframe. Were a soft-switch to occur, the re-adjustment
871-
* of the recursion depth would happen for the wrong frame.
845+
/* only do recursion adjustment if there is no danger of soft-switching.
846+
* Were a soft-switch to occur, the re-adjustment of the recursion depth
847+
* would happen for the wrong frame.
872848
*/
873-
if (!stackless)
874-
#endif
875-
if (Py_EnterRecursiveCall(" while calling a Python object")) {
849+
if (!stackless &&
850+
Py_EnterRecursiveCall(" while calling a Python object")) {
876851
return NULL;
877852
}
878853

879854
STACKLESS_PROMOTE_FLAG(PyCFunction_GET_FLAGS(func) & METH_STACKLESS);
880855
result = (*(PyCFunctionWithKeywords)(void(*)(void))meth)(self, args, kwargs);
881856
STACKLESS_ASSERT();
882857

883-
#ifdef STACKLESS
884858
if (!stackless)
885-
#endif
886-
Py_LeaveRecursiveCall();
859+
Py_LeaveRecursiveCall();
887860
}
888861
else {
889862
if (kwargs != NULL && PyDict_GET_SIZE(kwargs) != 0) {
@@ -892,26 +865,21 @@ cfunction_call_varargs(PyObject *func, PyObject *args, PyObject *kwargs)
892865
return NULL;
893866
}
894867

895-
#ifdef STACKLESS
896-
/* only do recursion adjustment if there is no danger
897-
* of soft-switching, i.e. if we are not being called by
898-
* run_cframe. Were a soft-switch to occur, the re-adjustment
899-
* of the recursion depth would happen for the wrong frame.
868+
/* only do recursion adjustment if there is no danger of soft-switching.
869+
* Were a soft-switch to occur, the re-adjustment of the recursion depth
870+
* would happen for the wrong frame.
900871
*/
901-
if (!stackless)
902-
#endif
903-
if (Py_EnterRecursiveCall(" while calling a Python object")) {
872+
if (!stackless &&
873+
Py_EnterRecursiveCall(" while calling a Python object")) {
904874
return NULL;
905875
}
906876

907877
STACKLESS_PROMOTE_FLAG(PyCFunction_GET_FLAGS(func) & METH_STACKLESS);
908878
result = (*meth)(self, args);
909879
STACKLESS_ASSERT();
910880

911-
#ifdef STACKLESS
912881
if (!stackless)
913-
#endif
914-
Py_LeaveRecursiveCall();
882+
Py_LeaveRecursiveCall();
915883
}
916884

917885
return _Py_CheckFunctionResult(func, result, NULL);

‎Objects/classobject.c‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ method_vectorcall(PyObject *method, PyObject *const *args,
6767
Py_ssize_t totalargs = nargs + nkwargs;
6868
newargs = PyMem_Malloc((totalargs+1) * sizeof(PyObject *));
6969
if (newargs == NULL) {
70+
STACKLESS_GETARG();
7071
PyErr_NoMemory();
7172
return NULL;
7273
}

‎Python/ceval.c‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5355,6 +5355,7 @@ trace_call_function(PyThreadState *tstate,
53555355
return x;
53565356
}
53575357
else if (Py_TYPE(func) == &PyMethodDescr_Type && nargs > 0) {
5358+
STACKLESS_GETARG();
53585359
/* We need to create a temporary bound method as argument
53595360
for profiling.
53605361
@@ -5367,9 +5368,11 @@ trace_call_function(PyThreadState *tstate,
53675368
if (func == NULL) {
53685369
return NULL;
53695370
}
5371+
STACKLESS_PROMOTE_ALL();
53705372
C_TRACE(x, _PyCFunction_FastCallKeywords(func,
53715373
args+1, nargs-1,
53725374
kwnames));
5375+
STACKLESS_ASSERT();
53735376
Py_DECREF(func);
53745377
return x;
53755378
}
@@ -5388,12 +5391,14 @@ call_function(PyThreadState *tstate, PyObject ***pp_stack, Py_ssize_t oparg, PyO
53885391
Py_ssize_t nargs = oparg - nkwargs;
53895392
PyObject **stack = (*pp_stack) - nargs - nkwargs;
53905393

5394+
STACKLESS_PROPOSE_ALL(tstate);
53915395
if (tstate->use_tracing) {
53925396
x = trace_call_function(tstate, func, stack, nargs, kwnames);
53935397
}
53945398
else {
53955399
x = _PyObject_Vectorcall(func, stack, nargs | PY_VECTORCALL_ARGUMENTS_OFFSET, kwnames);
53965400
}
5401+
STACKLESS_ASSERT();
53975402

53985403
assert((STACKLESS_RETVAL(tstate, x) != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
53995404

0 commit comments

Comments
 (0)