pFad - Phone/Frame/Anonymizer/Declutterfier! Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

URL: http://github.com/python/cpython/commit/7e433733175e76627d46ed9bdab543860cd1452d

b48faa60c69660fa.css" /> bpo-38644: Add _PyObject_VectorcallTstate() (GH-17052) · python/cpython@7e43373 · GitHub
Skip to content

Commit 7e43373

Browse files
authored
bpo-38644: Add _PyObject_VectorcallTstate() (GH-17052)
* Add _PyObject_VectorcallTstate() function: similar to _PyObject_Vectorcall(), but with tstate parameter * Add tstate parameter to _PyObject_MakeTpCall()
1 parent befa032 commit 7e43373

6 files changed

Lines changed: 94 additions & 50 deletions

File tree

Include/cpython/abstract.h

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ PyAPI_FUNC(PyObject *) _Py_CheckFunctionResult(
4949
or _PyObject_FastCallDict() (both forms are supported),
5050
except that nargs is plainly the number of arguments without flags. */
5151
PyAPI_FUNC(PyObject *) _PyObject_MakeTpCall(
52+
PyThreadState *tstate,
5253
PyObject *callable,
5354
PyObject *const *args, Py_ssize_t nargs,
5455
PyObject *keywords);
@@ -95,22 +96,31 @@ _PyVectorcall_Function(PyObject *callable)
9596
Return the result on success. Raise an exception and return NULL on
9697
error. */
9798
static inline PyObject *
98-
_PyObject_Vectorcall(PyObject *callable, PyObject *const *args,
99-
size_t nargsf, PyObject *kwnames)
99+
_PyObject_VectorcallTstate(PyThreadState *tstate, PyObject *callable,
100+
PyObject *const *args, size_t nargsf,
101+
PyObject *kwnames)
100102
{
101103
assert(kwnames == NULL || PyTuple_Check(kwnames));
102104
assert(args != NULL || PyVectorcall_NARGS(nargsf) == 0);
103105

104-
PyThreadState *tstate = PyThreadState_GET();
105106
vectorcallfunc func = _PyVectorcall_Function(callable);
106107
if (func == NULL) {
107108
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
108-
return _PyObject_MakeTpCall(callable, args, nargs, kwnames);
109+
return _PyObject_MakeTpCall(tstate, callable, args, nargs, kwnames);
109110
}
110111
PyObject *res = func(callable, args, nargsf, kwnames);
111112
return _Py_CheckFunctionResult(tstate, callable, res, NULL);
112113
}
113114

115+
static inline PyObject *
116+
_PyObject_Vectorcall(PyObject *callable, PyObject *const *args,
117+
size_t nargsf, PyObject *kwnames)
118+
{
119+
PyThreadState *tstate = PyThreadState_GET();
120+
return _PyObject_VectorcallTstate(tstate, callable,
121+
args, nargsf, kwnames);
122+
}
123+
114124
/* Same as _PyObject_Vectorcall except that keyword arguments are passed as
115125
dict, which may be NULL if there are no keyword arguments. */
116126
PyAPI_FUNC(PyObject *) _PyObject_FastCallDict(

Modules/_functoolsmodule.c

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -132,21 +132,25 @@ partial_dealloc(partialobject *pto)
132132
* if we would need to do that, we stop using vectorcall and fall back
133133
* to using partial_call() instead. */
134134
_Py_NO_INLINE static PyObject *
135-
partial_vectorcall_fallback(partialobject *pto, PyObject *const *args,
136-
size_t nargsf, PyObject *kwnames)
135+
partial_vectorcall_fallback(PyThreadState *tstate, partialobject *pto,
136+
PyObject *const *args, size_t nargsf,
137+
PyObject *kwnames)
137138
{
138139
pto->vectorcall = NULL;
139140
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
140-
return _PyObject_MakeTpCall((PyObject *)pto, args, nargs, kwnames);
141+
return _PyObject_MakeTpCall(tstate, (PyObject *)pto,
142+
args, nargs, kwnames);
141143
}
142144

143145
static PyObject *
144146
partial_vectorcall(partialobject *pto, PyObject *const *args,
145147
size_t nargsf, PyObject *kwnames)
146148
{
149+
PyThreadState *tstate = _PyThreadState_GET();
150+
147151
/* pto->kw is mutable, so need to check every time */
148152
if (PyDict_GET_SIZE(pto->kw)) {
149-
return partial_vectorcall_fallback(pto, args, nargsf, kwnames);
153+
return partial_vectorcall_fallback(tstate, pto, args, nargsf, kwnames);
150154
}
151155

152156
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
@@ -160,7 +164,8 @@ partial_vectorcall(partialobject *pto, PyObject *const *args,
160164

161165
/* Fast path if we're called without arguments */
162166
if (nargs_total == 0) {
163-
return _PyObject_Vectorcall(pto->fn, pto_args, pto_nargs, NULL);
167+
return _PyObject_VectorcallTstate(tstate, pto->fn,
168+
pto_args, pto_nargs, NULL);
164169
}
165170

166171
/* Fast path using PY_VECTORCALL_ARGUMENTS_OFFSET to prepend a single
@@ -169,7 +174,8 @@ partial_vectorcall(partialobject *pto, PyObject *const *args,
169174
PyObject **newargs = (PyObject **)args - 1;
170175
PyObject *tmp = newargs[0];
171176
newargs[0] = pto_args[0];
172-
PyObject *ret = _PyObject_Vectorcall(pto->fn, newargs, nargs + 1, kwnames);
177+
PyObject *ret = _PyObject_VectorcallTstate(tstate, pto->fn,
178+
newargs, nargs + 1, kwnames);
173179
newargs[0] = tmp;
174180
return ret;
175181
}
@@ -195,7 +201,8 @@ partial_vectorcall(partialobject *pto, PyObject *const *args,
195201
memcpy(stack, pto_args, pto_nargs * sizeof(PyObject*));
196202
memcpy(stack + pto_nargs, args, nargs_total * sizeof(PyObject*));
197203

198-
ret = _PyObject_Vectorcall(pto->fn, stack, pto_nargs + nargs, kwnames);
204+
ret = _PyObject_VectorcallTstate(tstate, pto->fn,
205+
stack, pto_nargs + nargs, kwnames);
199206
if (stack != small_stack) {
200207
PyMem_Free(stack);
201208
}

Objects/call.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ _PyObject_FastCallDict(PyObject *callable, PyObject *const *args,
104104
vectorcallfunc func = _PyVectorcall_Function(callable);
105105
if (func == NULL) {
106106
/* Use tp_call instead */
107-
return _PyObject_MakeTpCall(callable, args, nargs, kwargs);
107+
return _PyObject_MakeTpCall(tstate, callable, args, nargs, kwargs);
108108
}
109109

110110
PyObject *res;
@@ -129,10 +129,10 @@ _PyObject_FastCallDict(PyObject *callable, PyObject *const *args,
129129

130130

131131
PyObject *
132-
_PyObject_MakeTpCall(PyObject *callable, PyObject *const *args, Py_ssize_t nargs, PyObject *keywords)
132+
_PyObject_MakeTpCall(PyThreadState *tstate, PyObject *callable,
133+
PyObject *const *args, Py_ssize_t nargs,
134+
PyObject *keywords)
133135
{
134-
PyThreadState *tstate = _PyThreadState_GET();
135-
136136
/* Slow path: build a temporary tuple for positional arguments and a
137137
* temporary dictionary for keyword arguments (if any) */
138138
ternaryfunc call = Py_TYPE(callable)->tp_call;
@@ -774,6 +774,7 @@ _PyObject_VectorcallMethod(PyObject *name, PyObject *const *args,
774774
assert(args != NULL);
775775
assert(PyVectorcall_NARGS(nargsf) >= 1);
776776

777+
PyThreadState *tstate = _PyThreadState_GET();
777778
PyObject *callable = NULL;
778779
/* Use args[0] as "self" argument */
779780
int unbound = _PyObject_GetMethod(args[0], name, &callable);
@@ -792,7 +793,8 @@ _PyObject_VectorcallMethod(PyObject *name, PyObject *const *args,
792793
args++;
793794
nargsf--;
794795
}
795-
PyObject *result = _PyObject_Vectorcall(callable, args, nargsf, kwnames);
796+
PyObject *result = _PyObject_VectorcallTstate(tstate, callable,
797+
args, nargsf, kwnames);
796798
Py_DECREF(callable);
797799
return result;
798800
}

Objects/classobject.c

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include "Python.h"
44
#include "pycore_object.h"
5+
#include "pycore_pyerrors.h"
56
#include "pycore_pymem.h"
67
#include "pycore_pystate.h"
78
#include "structmember.h"
@@ -37,25 +38,28 @@ method_vectorcall(PyObject *method, PyObject *const *args,
3738
size_t nargsf, PyObject *kwnames)
3839
{
3940
assert(Py_TYPE(method) == &PyMethod_Type);
40-
PyObject *self, *func, *result;
41-
self = PyMethod_GET_SELF(method);
42-
func = PyMethod_GET_FUNCTION(method);
41+
42+
PyThreadState *tstate = _PyThreadState_GET();
43+
PyObject *self = PyMethod_GET_SELF(method);
44+
PyObject *func = PyMethod_GET_FUNCTION(method);
4345
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
4446

47+
PyObject *result;
4548
if (nargsf & PY_VECTORCALL_ARGUMENTS_OFFSET) {
4649
/* PY_VECTORCALL_ARGUMENTS_OFFSET is set, so we are allowed to mutate the vector */
4750
PyObject **newargs = (PyObject**)args - 1;
4851
nargs += 1;
4952
PyObject *tmp = newargs[0];
5053
newargs[0] = self;
51-
result = _PyObject_Vectorcall(func, newargs, nargs, kwnames);
54+
result = _PyObject_VectorcallTstate(tstate, func, newargs,
55+
nargs, kwnames);
5256
newargs[0] = tmp;
5357
}
5458
else {
5559
Py_ssize_t nkwargs = (kwnames == NULL) ? 0 : PyTuple_GET_SIZE(kwnames);
5660
Py_ssize_t totalargs = nargs + nkwargs;
5761
if (totalargs == 0) {
58-
return _PyObject_Vectorcall(func, &self, 1, NULL);
62+
return _PyObject_VectorcallTstate(tstate, func, &self, 1, NULL);
5963
}
6064

6165
PyObject *newargs_stack[_PY_FASTCALL_SMALL_STACK];
@@ -66,7 +70,7 @@ method_vectorcall(PyObject *method, PyObject *const *args,
6670
else {
6771
newargs = PyMem_Malloc((totalargs+1) * sizeof(PyObject *));
6872
if (newargs == NULL) {
69-
PyErr_NoMemory();
73+
_PyErr_NoMemory(tstate);
7074
return NULL;
7175
}
7276
}
@@ -77,7 +81,8 @@ method_vectorcall(PyObject *method, PyObject *const *args,
7781
* undefined behaviour. */
7882
assert(args != NULL);
7983
memcpy(newargs + 1, args, totalargs * sizeof(PyObject *));
80-
result = _PyObject_Vectorcall(func, newargs, nargs+1, kwnames);
84+
result = _PyObject_VectorcallTstate(tstate, func,
85+
newargs, nargs+1, kwnames);
8186
if (newargs != newargs_stack) {
8287
PyMem_Free(newargs);
8388
}

Objects/typeobject.c

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1445,7 +1445,7 @@ lookup_method(PyObject *self, _Py_Identifier *attrid, int *unbound)
14451445

14461446

14471447
static inline PyObject*
1448-
vectorcall_unbound(int unbound, PyObject *func,
1448+
vectorcall_unbound(PyThreadState *tstate, int unbound, PyObject *func,
14491449
PyObject *const *args, Py_ssize_t nargs)
14501450
{
14511451
size_t nargsf = nargs;
@@ -1455,7 +1455,7 @@ vectorcall_unbound(int unbound, PyObject *func,
14551455
args++;
14561456
nargsf = nargsf - 1 + PY_VECTORCALL_ARGUMENTS_OFFSET;
14571457
}
1458-
return _PyObject_Vectorcall(func, args, nargsf, NULL);
1458+
return _PyObject_VectorcallTstate(tstate, func, args, nargsf, NULL);
14591459
}
14601460

14611461
static PyObject*
@@ -1479,24 +1479,27 @@ vectorcall_method(_Py_Identifier *name,
14791479
PyObject *const *args, Py_ssize_t nargs)
14801480
{
14811481
assert(nargs >= 1);
1482+
1483+
PyThreadState *tstate = _PyThreadState_GET();
14821484
int unbound;
14831485
PyObject *self = args[0];
14841486
PyObject *func = lookup_method(self, name, &unbound);
14851487
if (func == NULL) {
14861488
return NULL;
14871489
}
1488-
PyObject *retval = vectorcall_unbound(unbound, func, args, nargs);
1490+
PyObject *retval = vectorcall_unbound(tstate, unbound, func, args, nargs);
14891491
Py_DECREF(func);
14901492
return retval;
14911493
}
14921494

14931495
/* Clone of vectorcall_method() that returns NotImplemented
14941496
* when the lookup fails. */
14951497
static PyObject *
1496-
vectorcall_maybe(_Py_Identifier *name,
1498+
vectorcall_maybe(PyThreadState *tstate, _Py_Identifier *name,
14971499
PyObject *const *args, Py_ssize_t nargs)
14981500
{
14991501
assert(nargs >= 1);
1502+
15001503
int unbound;
15011504
PyObject *self = args[0];
15021505
PyObject *func = lookup_maybe_method(self, name, &unbound);
@@ -1505,7 +1508,7 @@ vectorcall_maybe(_Py_Identifier *name,
15051508
Py_RETURN_NOTIMPLEMENTED;
15061509
return NULL;
15071510
}
1508-
PyObject *retval = vectorcall_unbound(unbound, func, args, nargs);
1511+
PyObject *retval = vectorcall_unbound(tstate, unbound, func, args, nargs);
15091512
Py_DECREF(func);
15101513
return retval;
15111514
}
@@ -6177,6 +6180,7 @@ static PyObject * \
61776180
FUNCNAME(PyObject *self, PyObject *other) \
61786181
{ \
61796182
PyObject* stack[2]; \
6183+
PyThreadState *tstate = _PyThreadState_GET(); \
61806184
_Py_static_string(op_id, OPSTR); \
61816185
_Py_static_string(rop_id, ROPSTR); \
61826186
int do_other = Py_TYPE(self) != Py_TYPE(other) && \
@@ -6193,7 +6197,7 @@ FUNCNAME(PyObject *self, PyObject *other) \
61936197
if (ok) { \
61946198
stack[0] = other; \
61956199
stack[1] = self; \
6196-
r = vectorcall_maybe(&rop_id, stack, 2); \
6200+
r = vectorcall_maybe(tstate, &rop_id, stack, 2); \
61976201
if (r != Py_NotImplemented) \
61986202
return r; \
61996203
Py_DECREF(r); \
@@ -6202,7 +6206,7 @@ FUNCNAME(PyObject *self, PyObject *other) \
62026206
} \
62036207
stack[0] = self; \
62046208
stack[1] = other; \
6205-
r = vectorcall_maybe(&op_id, stack, 2); \
6209+
r = vectorcall_maybe(tstate, &op_id, stack, 2); \
62066210
if (r != Py_NotImplemented || \
62076211
Py_TYPE(other) == Py_TYPE(self)) \
62086212
return r; \
@@ -6211,7 +6215,7 @@ FUNCNAME(PyObject *self, PyObject *other) \
62116215
if (do_other) { \
62126216
stack[0] = other; \
62136217
stack[1] = self; \
6214-
return vectorcall_maybe(&rop_id, stack, 2); \
6218+
return vectorcall_maybe(tstate, &rop_id, stack, 2); \
62156219
} \
62166220
Py_RETURN_NOTIMPLEMENTED; \
62176221
}
@@ -6293,6 +6297,7 @@ slot_sq_ass_item(PyObject *self, Py_ssize_t index, PyObject *value)
62936297
static int
62946298
slot_sq_contains(PyObject *self, PyObject *value)
62956299
{
6300+
PyThreadState *tstate = _PyThreadState_GET();
62966301
PyObject *func, *res;
62976302
int result = -1, unbound;
62986303
_Py_IDENTIFIER(__contains__);
@@ -6307,7 +6312,7 @@ slot_sq_contains(PyObject *self, PyObject *value)
63076312
}
63086313
if (func != NULL) {
63096314
PyObject *args[2] = {self, value};
6310-
res = vectorcall_unbound(unbound, func, args, 2);
6315+
res = vectorcall_unbound(tstate, unbound, func, args, 2);
63116316
Py_DECREF(func);
63126317
if (res != NULL) {
63136318
result = PyObject_IsTrue(res);
@@ -6682,6 +6687,7 @@ static _Py_Identifier name_op[] = {
66826687
static PyObject *
66836688
slot_tp_richcompare(PyObject *self, PyObject *other, int op)
66846689
{
6690+
PyThreadState *tstate = _PyThreadState_GET();
66856691
int unbound;
66866692
PyObject *func, *res;
66876693

@@ -6692,7 +6698,7 @@ slot_tp_richcompare(PyObject *self, PyObject *other, int op)
66926698
}
66936699

66946700
PyObject *stack[2] = {self, other};
6695-
res = vectorcall_unbound(unbound, func, stack, 2);
6701+
res = vectorcall_unbound(tstate, unbound, func, stack, 2);
66966702
Py_DECREF(func);
66976703
return res;
66986704
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.





Check this box to remove all script contents from the fetched content.



Check this box to remove all images from the fetched content.


Check this box to remove all CSS styles from the fetched content.


Check this box to keep images inefficiently compressed and original size.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy