bpo-38644: Add _PyObject_Call() (GH-17089)

* Add pycore_call.h internal header file.
* Add _PyObject_Call(): PyObject_Call() with tstate
* Add _PyObject_CallNoArgTstate(): _PyObject_CallNoArg() with tstate
* Add _PyObject_FastCallDictTstate(): _PyObject_FastCallDict()
  with tstate
* _PyObject_Call_Prepend() now takes tstate
* Replace _PyObject_FastCall() calls
  with _PyObject_VectorcallTstate() calls
This commit is contained in:
Victor Stinner 2019-11-14 13:36:21 +01:00 committed by GitHub
parent b9e681261c
commit 4d231bcc77
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 217 additions and 138 deletions

View File

@ -137,7 +137,8 @@ PyAPI_FUNC(PyObject *) PyVectorcall_Call(PyObject *callable, PyObject *tuple, Py
static inline PyObject * static inline PyObject *
_PyObject_FastCall(PyObject *func, PyObject *const *args, Py_ssize_t nargs) _PyObject_FastCall(PyObject *func, PyObject *const *args, Py_ssize_t nargs)
{ {
return _PyObject_Vectorcall(func, args, (size_t)nargs, NULL); PyThreadState *tstate = PyThreadState_GET();
return _PyObject_VectorcallTstate(tstate, func, args, (size_t)nargs, NULL);
} }
/* Call a callable without any arguments /* Call a callable without any arguments
@ -145,7 +146,8 @@ _PyObject_FastCall(PyObject *func, PyObject *const *args, Py_ssize_t nargs)
PyObject_CallNoArgs(). */ PyObject_CallNoArgs(). */
static inline PyObject * static inline PyObject *
_PyObject_CallNoArg(PyObject *func) { _PyObject_CallNoArg(PyObject *func) {
return _PyObject_Vectorcall(func, NULL, 0, NULL); PyThreadState *tstate = PyThreadState_GET();
return _PyObject_VectorcallTstate(tstate, func, NULL, 0, NULL);
} }
static inline PyObject * static inline PyObject *
@ -155,16 +157,11 @@ _PyObject_CallOneArg(PyObject *func, PyObject *arg)
PyObject *_args[2]; PyObject *_args[2];
PyObject **args = _args + 1; // For PY_VECTORCALL_ARGUMENTS_OFFSET PyObject **args = _args + 1; // For PY_VECTORCALL_ARGUMENTS_OFFSET
args[0] = arg; args[0] = arg;
return _PyObject_Vectorcall(func, args, PyThreadState *tstate = PyThreadState_GET();
1 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL); size_t nargsf = 1 | PY_VECTORCALL_ARGUMENTS_OFFSET;
return _PyObject_VectorcallTstate(tstate, func, args, nargsf, NULL);
} }
PyAPI_FUNC(PyObject *) _PyObject_Call_Prepend(
PyObject *callable,
PyObject *obj,
PyObject *args,
PyObject *kwargs);
PyAPI_FUNC(PyObject *) _PyObject_VectorcallMethod( PyAPI_FUNC(PyObject *) _PyObject_VectorcallMethod(
PyObject *name, PyObject *const *args, PyObject *name, PyObject *const *args,
size_t nargsf, PyObject *kwnames); size_t nargsf, PyObject *kwnames);

View File

@ -0,0 +1,39 @@
#ifndef Py_INTERNAL_CALL_H
#define Py_INTERNAL_CALL_H
#ifdef __cplusplus
extern "C" {
#endif
#ifndef Py_BUILD_CORE
# error "this header requires Py_BUILD_CORE define"
#endif
PyAPI_FUNC(PyObject *) _PyObject_Call_Prepend(
PyThreadState *tstate,
PyObject *callable,
PyObject *obj,
PyObject *args,
PyObject *kwargs);
PyAPI_FUNC(PyObject *) _PyObject_FastCallDictTstate(
PyThreadState *tstate,
PyObject *callable,
PyObject *const *args,
size_t nargsf,
PyObject *kwargs);
PyAPI_FUNC(PyObject *) _PyObject_Call(
PyThreadState *tstate,
PyObject *callable,
PyObject *args,
PyObject *kwargs);
static inline PyObject *
_PyObject_CallNoArgTstate(PyThreadState *tstate, PyObject *func) {
return _PyObject_VectorcallTstate(tstate, func, NULL, 0, NULL);
}
#ifdef __cplusplus
}
#endif
#endif /* !Py_INTERNAL_CALL_H */

View File

@ -1076,6 +1076,7 @@ PYTHON_HEADERS= \
\ \
$(srcdir)/Include/internal/pycore_accu.h \ $(srcdir)/Include/internal/pycore_accu.h \
$(srcdir)/Include/internal/pycore_atomic.h \ $(srcdir)/Include/internal/pycore_atomic.h \
$(srcdir)/Include/internal/pycore_call.h \
$(srcdir)/Include/internal/pycore_ceval.h \ $(srcdir)/Include/internal/pycore_ceval.h \
$(srcdir)/Include/internal/pycore_code.h \ $(srcdir)/Include/internal/pycore_code.h \
$(srcdir)/Include/internal/pycore_condvar.h \ $(srcdir)/Include/internal/pycore_condvar.h \

View File

@ -1,4 +1,5 @@
#include "Python.h" #include "Python.h"
#include "pycore_call.h"
#include "pycore_ceval.h" /* _PyEval_EvalFrame() */ #include "pycore_ceval.h" /* _PyEval_EvalFrame() */
#include "pycore_object.h" #include "pycore_object.h"
#include "pycore_pyerrors.h" #include "pycore_pyerrors.h"
@ -18,11 +19,12 @@ _PyStack_UnpackDict_Free(PyObject *const *stack, Py_ssize_t nargs,
static PyObject * static PyObject *
null_error(void) null_error(PyThreadState *tstate)
{ {
if (!PyErr_Occurred()) if (!_PyErr_Occurred(tstate)) {
PyErr_SetString(PyExc_SystemError, _PyErr_SetString(tstate, PyExc_SystemError,
"null argument to internal routine"); "null argument to internal routine");
}
return NULL; return NULL;
} }
@ -81,17 +83,18 @@ _Py_CheckFunctionResult(PyThreadState *tstate, PyObject *callable,
PyObject * PyObject *
PyObject_CallNoArgs(PyObject *func) PyObject_CallNoArgs(PyObject *func)
{ {
return _PyObject_CallNoArg(func); PyThreadState *tstate = _PyThreadState_GET();
return _PyObject_CallNoArgTstate(tstate, func);
} }
PyObject * PyObject *
_PyObject_FastCallDict(PyObject *callable, PyObject *const *args, _PyObject_FastCallDictTstate(PyThreadState *tstate, PyObject *callable,
size_t nargsf, PyObject *kwargs) PyObject *const *args, size_t nargsf,
PyObject *kwargs)
{ {
assert(callable != NULL); assert(callable != NULL);
PyThreadState *tstate = _PyThreadState_GET();
/* _PyObject_FastCallDict() must not be called with an exception set, /* _PyObject_FastCallDict() must not be called with an exception set,
because it can clear it (directly or indirectly) and so the because it can clear it (directly or indirectly) and so the
caller loses its exception */ caller loses its exception */
@ -129,11 +132,24 @@ _PyObject_FastCallDict(PyObject *callable, PyObject *const *args,
} }
PyObject *
_PyObject_FastCallDict(PyObject *callable, PyObject *const *args,
size_t nargsf, PyObject *kwargs)
{
PyThreadState *tstate = _PyThreadState_GET();
return _PyObject_FastCallDictTstate(tstate, callable, args, nargsf, kwargs);
}
PyObject * PyObject *
_PyObject_MakeTpCall(PyThreadState *tstate, PyObject *callable, _PyObject_MakeTpCall(PyThreadState *tstate, PyObject *callable,
PyObject *const *args, Py_ssize_t nargs, PyObject *const *args, Py_ssize_t nargs,
PyObject *keywords) PyObject *keywords)
{ {
assert(nargs >= 0);
assert(nargs == 0 || args != NULL);
assert(keywords == NULL || PyTuple_Check(keywords) || PyDict_Check(keywords));
/* Slow path: build a temporary tuple for positional arguments and a /* Slow path: build a temporary tuple for positional arguments and a
* temporary dictionary for keyword arguments (if any) */ * temporary dictionary for keyword arguments (if any) */
ternaryfunc call = Py_TYPE(callable)->tp_call; ternaryfunc call = Py_TYPE(callable)->tp_call;
@ -144,9 +160,6 @@ _PyObject_MakeTpCall(PyThreadState *tstate, PyObject *callable,
return NULL; return NULL;
} }
assert(nargs >= 0);
assert(nargs == 0 || args != NULL);
assert(keywords == NULL || PyTuple_Check(keywords) || PyDict_Check(keywords));
PyObject *argstuple = _PyTuple_FromArray(args, nargs); PyObject *argstuple = _PyTuple_FromArray(args, nargs);
if (argstuple == NULL) { if (argstuple == NULL) {
return NULL; return NULL;
@ -182,8 +195,7 @@ _PyObject_MakeTpCall(PyThreadState *tstate, PyObject *callable,
Py_DECREF(kwdict); Py_DECREF(kwdict);
} }
result = _Py_CheckFunctionResult(tstate, callable, result, NULL); return _Py_CheckFunctionResult(tstate, callable, result, NULL);
return result;
} }
@ -228,14 +240,15 @@ PyVectorcall_Call(PyObject *callable, PyObject *tuple, PyObject *kwargs)
PyObject *result = func(callable, args, PyObject *result = func(callable, args,
nargs | PY_VECTORCALL_ARGUMENTS_OFFSET, kwnames); nargs | PY_VECTORCALL_ARGUMENTS_OFFSET, kwnames);
_PyStack_UnpackDict_Free(args, nargs, kwnames); _PyStack_UnpackDict_Free(args, nargs, kwnames);
return _Py_CheckFunctionResult(tstate, callable, result, NULL); return _Py_CheckFunctionResult(tstate, callable, result, NULL);
} }
PyObject * PyObject *
PyObject_Call(PyObject *callable, PyObject *args, PyObject *kwargs) _PyObject_Call(PyThreadState *tstate, PyObject *callable,
PyObject *args, PyObject *kwargs)
{ {
PyThreadState *tstate = _PyThreadState_GET();
ternaryfunc call; ternaryfunc call;
PyObject *result; PyObject *result;
@ -270,11 +283,19 @@ PyObject_Call(PyObject *callable, PyObject *args, PyObject *kwargs)
} }
} }
PyObject *
PyObject_Call(PyObject *callable, PyObject *args, PyObject *kwargs)
{
PyThreadState *tstate = _PyThreadState_GET();
return _PyObject_Call(tstate, callable, args, kwargs);
}
PyObject * PyObject *
PyCFunction_Call(PyObject *callable, PyObject *args, PyObject *kwargs) PyCFunction_Call(PyObject *callable, PyObject *args, PyObject *kwargs)
{ {
return PyObject_Call(callable, args, kwargs); PyThreadState *tstate = _PyThreadState_GET();
return _PyObject_Call(tstate, callable, args, kwargs);
} }
@ -385,30 +406,31 @@ PyObject *
PyEval_CallObjectWithKeywords(PyObject *callable, PyEval_CallObjectWithKeywords(PyObject *callable,
PyObject *args, PyObject *kwargs) PyObject *args, PyObject *kwargs)
{ {
PyThreadState *tstate = _PyThreadState_GET();
#ifdef Py_DEBUG #ifdef Py_DEBUG
/* PyEval_CallObjectWithKeywords() must not be called with an exception /* PyEval_CallObjectWithKeywords() must not be called with an exception
set. It raises a new exception if parameters are invalid or if set. It raises a new exception if parameters are invalid or if
PyTuple_New() fails, and so the original exception is lost. */ PyTuple_New() fails, and so the original exception is lost. */
assert(!PyErr_Occurred()); assert(!_PyErr_Occurred(tstate));
#endif #endif
if (args != NULL && !PyTuple_Check(args)) { if (args != NULL && !PyTuple_Check(args)) {
PyErr_SetString(PyExc_TypeError, _PyErr_SetString(tstate, PyExc_TypeError,
"argument list must be a tuple"); "argument list must be a tuple");
return NULL; return NULL;
} }
if (kwargs != NULL && !PyDict_Check(kwargs)) { if (kwargs != NULL && !PyDict_Check(kwargs)) {
PyErr_SetString(PyExc_TypeError, _PyErr_SetString(tstate, PyExc_TypeError,
"keyword list must be a dictionary"); "keyword list must be a dictionary");
return NULL; return NULL;
} }
if (args == NULL) { if (args == NULL) {
return _PyObject_FastCallDict(callable, NULL, 0, kwargs); return _PyObject_FastCallDictTstate(tstate, callable, NULL, 0, kwargs);
} }
else { else {
return PyObject_Call(callable, args, kwargs); return _PyObject_Call(tstate, callable, args, kwargs);
} }
} }
@ -416,32 +438,31 @@ PyEval_CallObjectWithKeywords(PyObject *callable,
PyObject * PyObject *
PyObject_CallObject(PyObject *callable, PyObject *args) PyObject_CallObject(PyObject *callable, PyObject *args)
{ {
assert(!PyErr_Occurred()); PyThreadState *tstate = _PyThreadState_GET();
assert(!_PyErr_Occurred(tstate));
if (args == NULL) { if (args == NULL) {
return _PyObject_CallNoArg(callable); return _PyObject_CallNoArgTstate(tstate, callable);
} }
if (!PyTuple_Check(args)) { if (!PyTuple_Check(args)) {
PyErr_SetString(PyExc_TypeError, _PyErr_SetString(tstate, PyExc_TypeError,
"argument list must be a tuple"); "argument list must be a tuple");
return NULL; return NULL;
} }
return PyObject_Call(callable, args, NULL); return _PyObject_Call(tstate, callable, args, NULL);
} }
/* Call callable(obj, *args, **kwargs). */ /* Call callable(obj, *args, **kwargs). */
PyObject * PyObject *
_PyObject_Call_Prepend(PyObject *callable, _PyObject_Call_Prepend(PyThreadState *tstate, PyObject *callable,
PyObject *obj, PyObject *args, PyObject *kwargs) PyObject *obj, PyObject *args, PyObject *kwargs)
{ {
PyObject *small_stack[_PY_FASTCALL_SMALL_STACK];
PyObject **stack;
Py_ssize_t argcount;
PyObject *result;
assert(PyTuple_Check(args)); assert(PyTuple_Check(args));
argcount = PyTuple_GET_SIZE(args); PyObject *small_stack[_PY_FASTCALL_SMALL_STACK];
PyObject **stack;
Py_ssize_t argcount = PyTuple_GET_SIZE(args);
if (argcount + 1 <= (Py_ssize_t)Py_ARRAY_LENGTH(small_stack)) { if (argcount + 1 <= (Py_ssize_t)Py_ARRAY_LENGTH(small_stack)) {
stack = small_stack; stack = small_stack;
} }
@ -459,9 +480,9 @@ _PyObject_Call_Prepend(PyObject *callable,
_PyTuple_ITEMS(args), _PyTuple_ITEMS(args),
argcount * sizeof(PyObject *)); argcount * sizeof(PyObject *));
result = _PyObject_FastCallDict(callable, PyObject *result = _PyObject_FastCallDictTstate(tstate, callable,
stack, argcount + 1, stack, argcount + 1,
kwargs); kwargs);
if (stack != small_stack) { if (stack != small_stack) {
PyMem_Free(stack); PyMem_Free(stack);
} }
@ -472,8 +493,8 @@ _PyObject_Call_Prepend(PyObject *callable,
/* --- Call with a format string ---------------------------------- */ /* --- Call with a format string ---------------------------------- */
static PyObject * static PyObject *
_PyObject_CallFunctionVa(PyObject *callable, const char *format, _PyObject_CallFunctionVa(PyThreadState *tstate, PyObject *callable,
va_list va, int is_size_t) const char *format, va_list va, int is_size_t)
{ {
PyObject* small_stack[_PY_FASTCALL_SMALL_STACK]; PyObject* small_stack[_PY_FASTCALL_SMALL_STACK];
const Py_ssize_t small_stack_len = Py_ARRAY_LENGTH(small_stack); const Py_ssize_t small_stack_len = Py_ARRAY_LENGTH(small_stack);
@ -482,11 +503,11 @@ _PyObject_CallFunctionVa(PyObject *callable, const char *format,
PyObject *result; PyObject *result;
if (callable == NULL) { if (callable == NULL) {
return null_error(); return null_error(tstate);
} }
if (!format || !*format) { if (!format || !*format) {
return _PyObject_CallNoArg(callable); return _PyObject_CallNoArgTstate(tstate, callable);
} }
if (is_size_t) { if (is_size_t) {
@ -507,12 +528,14 @@ _PyObject_CallFunctionVa(PyObject *callable, const char *format,
- PyObject_CallFunction(func, "(OOO)", arg1, arg2, arg3) calls - PyObject_CallFunction(func, "(OOO)", arg1, arg2, arg3) calls
func(*(arg1, arg2, arg3)): func(arg1, arg2, arg3) */ func(*(arg1, arg2, arg3)): func(arg1, arg2, arg3) */
PyObject *args = stack[0]; PyObject *args = stack[0];
result = _PyObject_FastCall(callable, result = _PyObject_VectorcallTstate(tstate, callable,
_PyTuple_ITEMS(args), _PyTuple_ITEMS(args),
PyTuple_GET_SIZE(args)); PyTuple_GET_SIZE(args),
NULL);
} }
else { else {
result = _PyObject_FastCall(callable, stack, nargs); result = _PyObject_VectorcallTstate(tstate, callable,
stack, nargs, NULL);
} }
for (i = 0; i < nargs; ++i) { for (i = 0; i < nargs; ++i) {
@ -530,9 +553,10 @@ PyObject_CallFunction(PyObject *callable, const char *format, ...)
{ {
va_list va; va_list va;
PyObject *result; PyObject *result;
PyThreadState *tstate = _PyThreadState_GET();
va_start(va, format); va_start(va, format);
result = _PyObject_CallFunctionVa(callable, format, va, 0); result = _PyObject_CallFunctionVa(tstate, callable, format, va, 0);
va_end(va); va_end(va);
return result; return result;
@ -547,9 +571,10 @@ PyEval_CallFunction(PyObject *callable, const char *format, ...)
{ {
va_list va; va_list va;
PyObject *result; PyObject *result;
PyThreadState *tstate = _PyThreadState_GET();
va_start(va, format); va_start(va, format);
result = _PyObject_CallFunctionVa(callable, format, va, 0); result = _PyObject_CallFunctionVa(tstate, callable, format, va, 0);
va_end(va); va_end(va);
return result; return result;
@ -559,11 +584,11 @@ PyEval_CallFunction(PyObject *callable, const char *format, ...)
PyObject * PyObject *
_PyObject_CallFunction_SizeT(PyObject *callable, const char *format, ...) _PyObject_CallFunction_SizeT(PyObject *callable, const char *format, ...)
{ {
va_list va; PyThreadState *tstate = _PyThreadState_GET();
PyObject *result;
va_list va;
va_start(va, format); va_start(va, format);
result = _PyObject_CallFunctionVa(callable, format, va, 1); PyObject *result = _PyObject_CallFunctionVa(tstate, callable, format, va, 1);
va_end(va); va_end(va);
return result; return result;
@ -571,37 +596,37 @@ _PyObject_CallFunction_SizeT(PyObject *callable, const char *format, ...)
static PyObject* static PyObject*
callmethod(PyObject* callable, const char *format, va_list va, int is_size_t) callmethod(PyThreadState *tstate, PyObject* callable, const char *format, va_list va, int is_size_t)
{ {
assert(callable != NULL); assert(callable != NULL);
if (!PyCallable_Check(callable)) { if (!PyCallable_Check(callable)) {
PyErr_Format(PyExc_TypeError, _PyErr_Format(tstate, PyExc_TypeError,
"attribute of type '%.200s' is not callable", "attribute of type '%.200s' is not callable",
Py_TYPE(callable)->tp_name); Py_TYPE(callable)->tp_name);
return NULL; return NULL;
} }
return _PyObject_CallFunctionVa(callable, format, va, is_size_t); return _PyObject_CallFunctionVa(tstate, callable, format, va, is_size_t);
} }
PyObject * PyObject *
PyObject_CallMethod(PyObject *obj, const char *name, const char *format, ...) PyObject_CallMethod(PyObject *obj, const char *name, const char *format, ...)
{ {
va_list va; PyThreadState *tstate = _PyThreadState_GET();
PyObject *callable, *retval;
if (obj == NULL || name == NULL) { if (obj == NULL || name == NULL) {
return null_error(); return null_error(tstate);
} }
callable = PyObject_GetAttrString(obj, name); PyObject *callable = PyObject_GetAttrString(obj, name);
if (callable == NULL) if (callable == NULL) {
return NULL; return NULL;
}
va_list va;
va_start(va, format); va_start(va, format);
retval = callmethod(callable, format, va, 0); PyObject *retval = callmethod(tstate, callable, format, va, 0);
va_end(va); va_end(va);
Py_DECREF(callable); Py_DECREF(callable);
@ -615,19 +640,19 @@ PyObject_CallMethod(PyObject *obj, const char *name, const char *format, ...)
PyObject * PyObject *
PyEval_CallMethod(PyObject *obj, const char *name, const char *format, ...) PyEval_CallMethod(PyObject *obj, const char *name, const char *format, ...)
{ {
va_list va; PyThreadState *tstate = _PyThreadState_GET();
PyObject *callable, *retval;
if (obj == NULL || name == NULL) { if (obj == NULL || name == NULL) {
return null_error(); return null_error(tstate);
} }
callable = PyObject_GetAttrString(obj, name); PyObject *callable = PyObject_GetAttrString(obj, name);
if (callable == NULL) if (callable == NULL) {
return NULL; return NULL;
}
va_list va;
va_start(va, format); va_start(va, format);
retval = callmethod(callable, format, va, 0); PyObject *retval = callmethod(tstate, callable, format, va, 0);
va_end(va); va_end(va);
Py_DECREF(callable); Py_DECREF(callable);
@ -639,19 +664,19 @@ PyObject *
_PyObject_CallMethodId(PyObject *obj, _Py_Identifier *name, _PyObject_CallMethodId(PyObject *obj, _Py_Identifier *name,
const char *format, ...) const char *format, ...)
{ {
va_list va; PyThreadState *tstate = _PyThreadState_GET();
PyObject *callable, *retval;
if (obj == NULL || name == NULL) { if (obj == NULL || name == NULL) {
return null_error(); return null_error(tstate);
} }
callable = _PyObject_GetAttrId(obj, name); PyObject *callable = _PyObject_GetAttrId(obj, name);
if (callable == NULL) if (callable == NULL) {
return NULL; return NULL;
}
va_list va;
va_start(va, format); va_start(va, format);
retval = callmethod(callable, format, va, 0); PyObject *retval = callmethod(tstate, callable, format, va, 0);
va_end(va); va_end(va);
Py_DECREF(callable); Py_DECREF(callable);
@ -663,19 +688,19 @@ PyObject *
_PyObject_CallMethod_SizeT(PyObject *obj, const char *name, _PyObject_CallMethod_SizeT(PyObject *obj, const char *name,
const char *format, ...) const char *format, ...)
{ {
va_list va; PyThreadState *tstate = _PyThreadState_GET();
PyObject *callable, *retval;
if (obj == NULL || name == NULL) { if (obj == NULL || name == NULL) {
return null_error(); return null_error(tstate);
} }
callable = PyObject_GetAttrString(obj, name); PyObject *callable = PyObject_GetAttrString(obj, name);
if (callable == NULL) if (callable == NULL) {
return NULL; return NULL;
}
va_list va;
va_start(va, format); va_start(va, format);
retval = callmethod(callable, format, va, 1); PyObject *retval = callmethod(tstate, callable, format, va, 1);
va_end(va); va_end(va);
Py_DECREF(callable); Py_DECREF(callable);
@ -687,20 +712,19 @@ PyObject *
_PyObject_CallMethodId_SizeT(PyObject *obj, _Py_Identifier *name, _PyObject_CallMethodId_SizeT(PyObject *obj, _Py_Identifier *name,
const char *format, ...) const char *format, ...)
{ {
va_list va; PyThreadState *tstate = _PyThreadState_GET();
PyObject *callable, *retval;
if (obj == NULL || name == NULL) { if (obj == NULL || name == NULL) {
return null_error(); return null_error(tstate);
} }
callable = _PyObject_GetAttrId(obj, name); PyObject *callable = _PyObject_GetAttrId(obj, name);
if (callable == NULL) { if (callable == NULL) {
return NULL; return NULL;
} }
va_list va;
va_start(va, format); va_start(va, format);
retval = callmethod(callable, format, va, 1); PyObject *retval = callmethod(tstate, callable, format, va, 1);
va_end(va); va_end(va);
Py_DECREF(callable); Py_DECREF(callable);
@ -711,7 +735,8 @@ _PyObject_CallMethodId_SizeT(PyObject *obj, _Py_Identifier *name,
/* --- Call with "..." arguments ---------------------------------- */ /* --- Call with "..." arguments ---------------------------------- */
static PyObject * static PyObject *
object_vacall(PyObject *base, PyObject *callable, va_list vargs) object_vacall(PyThreadState *tstate, PyObject *base,
PyObject *callable, va_list vargs)
{ {
PyObject *small_stack[_PY_FASTCALL_SMALL_STACK]; PyObject *small_stack[_PY_FASTCALL_SMALL_STACK];
PyObject **stack; PyObject **stack;
@ -721,7 +746,7 @@ object_vacall(PyObject *base, PyObject *callable, va_list vargs)
va_list countva; va_list countva;
if (callable == NULL) { if (callable == NULL) {
return null_error(); return null_error(tstate);
} }
/* Count the number of arguments */ /* Count the number of arguments */
@ -758,7 +783,7 @@ object_vacall(PyObject *base, PyObject *callable, va_list vargs)
} }
/* Call the function */ /* Call the function */
result = _PyObject_FastCall(callable, stack, nargs); result = _PyObject_VectorcallTstate(tstate, callable, stack, nargs, NULL);
if (stack != small_stack) { if (stack != small_stack) {
PyMem_Free(stack); PyMem_Free(stack);
@ -804,8 +829,9 @@ _PyObject_VectorcallMethod(PyObject *name, PyObject *const *args,
PyObject * PyObject *
PyObject_CallMethodObjArgs(PyObject *obj, PyObject *name, ...) PyObject_CallMethodObjArgs(PyObject *obj, PyObject *name, ...)
{ {
PyThreadState *tstate = _PyThreadState_GET();
if (obj == NULL || name == NULL) { if (obj == NULL || name == NULL) {
return null_error(); return null_error(tstate);
} }
PyObject *callable = NULL; PyObject *callable = NULL;
@ -817,7 +843,7 @@ PyObject_CallMethodObjArgs(PyObject *obj, PyObject *name, ...)
va_list vargs; va_list vargs;
va_start(vargs, name); va_start(vargs, name);
PyObject *result = object_vacall(obj, callable, vargs); PyObject *result = object_vacall(tstate, obj, callable, vargs);
va_end(vargs); va_end(vargs);
Py_DECREF(callable); Py_DECREF(callable);
@ -829,8 +855,9 @@ PyObject *
_PyObject_CallMethodIdObjArgs(PyObject *obj, _PyObject_CallMethodIdObjArgs(PyObject *obj,
struct _Py_Identifier *name, ...) struct _Py_Identifier *name, ...)
{ {
PyThreadState *tstate = _PyThreadState_GET();
if (obj == NULL || name == NULL) { if (obj == NULL || name == NULL) {
return null_error(); return null_error(tstate);
} }
PyObject *oname = _PyUnicode_FromId(name); /* borrowed */ PyObject *oname = _PyUnicode_FromId(name); /* borrowed */
@ -847,7 +874,7 @@ _PyObject_CallMethodIdObjArgs(PyObject *obj,
va_list vargs; va_list vargs;
va_start(vargs, name); va_start(vargs, name);
PyObject *result = object_vacall(obj, callable, vargs); PyObject *result = object_vacall(tstate, obj, callable, vargs);
va_end(vargs); va_end(vargs);
Py_DECREF(callable); Py_DECREF(callable);
@ -858,11 +885,12 @@ _PyObject_CallMethodIdObjArgs(PyObject *obj,
PyObject * PyObject *
PyObject_CallFunctionObjArgs(PyObject *callable, ...) PyObject_CallFunctionObjArgs(PyObject *callable, ...)
{ {
PyThreadState *tstate = _PyThreadState_GET();
va_list vargs; va_list vargs;
PyObject *result; PyObject *result;
va_start(vargs, callable); va_start(vargs, callable);
result = object_vacall(NULL, callable, vargs); result = object_vacall(tstate, NULL, callable, vargs);
va_end(vargs); va_end(vargs);
return result; return result;

View File

@ -1,6 +1,7 @@
/* Type object implementation */ /* Type object implementation */
#include "Python.h" #include "Python.h"
#include "pycore_call.h"
#include "pycore_object.h" #include "pycore_object.h"
#include "pycore_pyerrors.h" #include "pycore_pyerrors.h"
#include "pycore_pystate.h" #include "pycore_pystate.h"
@ -6554,19 +6555,21 @@ slot_tp_hash(PyObject *self)
static PyObject * static PyObject *
slot_tp_call(PyObject *self, PyObject *args, PyObject *kwds) slot_tp_call(PyObject *self, PyObject *args, PyObject *kwds)
{ {
PyThreadState *tstate = _PyThreadState_GET();
_Py_IDENTIFIER(__call__); _Py_IDENTIFIER(__call__);
int unbound; int unbound;
PyObject *meth = lookup_method(self, &PyId___call__, &unbound); PyObject *meth = lookup_method(self, &PyId___call__, &unbound);
PyObject *res; if (meth == NULL) {
if (meth == NULL)
return NULL; return NULL;
}
PyObject *res;
if (unbound) { if (unbound) {
res = _PyObject_Call_Prepend(meth, self, args, kwds); res = _PyObject_Call_Prepend(tstate, meth, self, args, kwds);
} }
else { else {
res = PyObject_Call(meth, args, kwds); res = _PyObject_Call(tstate, meth, args, kwds);
} }
Py_DECREF(meth); Py_DECREF(meth);
@ -6688,17 +6691,16 @@ static PyObject *
slot_tp_richcompare(PyObject *self, PyObject *other, int op) slot_tp_richcompare(PyObject *self, PyObject *other, int op)
{ {
PyThreadState *tstate = _PyThreadState_GET(); PyThreadState *tstate = _PyThreadState_GET();
int unbound;
PyObject *func, *res;
func = lookup_maybe_method(self, &name_op[op], &unbound); int unbound;
PyObject *func = lookup_maybe_method(self, &name_op[op], &unbound);
if (func == NULL) { if (func == NULL) {
PyErr_Clear(); PyErr_Clear();
Py_RETURN_NOTIMPLEMENTED; Py_RETURN_NOTIMPLEMENTED;
} }
PyObject *stack[2] = {self, other}; PyObject *stack[2] = {self, other};
res = vectorcall_unbound(tstate, unbound, func, stack, 2); PyObject *res = vectorcall_unbound(tstate, unbound, func, stack, 2);
Py_DECREF(func); Py_DECREF(func);
return res; return res;
} }
@ -6793,18 +6795,21 @@ slot_tp_descr_set(PyObject *self, PyObject *target, PyObject *value)
static int static int
slot_tp_init(PyObject *self, PyObject *args, PyObject *kwds) slot_tp_init(PyObject *self, PyObject *args, PyObject *kwds)
{ {
PyThreadState *tstate = _PyThreadState_GET();
_Py_IDENTIFIER(__init__); _Py_IDENTIFIER(__init__);
int unbound; int unbound;
PyObject *meth = lookup_method(self, &PyId___init__, &unbound); PyObject *meth = lookup_method(self, &PyId___init__, &unbound);
PyObject *res; if (meth == NULL) {
if (meth == NULL)
return -1; return -1;
}
PyObject *res;
if (unbound) { if (unbound) {
res = _PyObject_Call_Prepend(meth, self, args, kwds); res = _PyObject_Call_Prepend(tstate, meth, self, args, kwds);
} }
else { else {
res = PyObject_Call(meth, args, kwds); res = _PyObject_Call(tstate, meth, args, kwds);
} }
Py_DECREF(meth); Py_DECREF(meth);
if (res == NULL) if (res == NULL)
@ -6823,6 +6828,7 @@ slot_tp_init(PyObject *self, PyObject *args, PyObject *kwds)
static PyObject * static PyObject *
slot_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) slot_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{ {
PyThreadState *tstate = _PyThreadState_GET();
PyObject *func, *result; PyObject *func, *result;
func = _PyObject_GetAttrId((PyObject *)type, &PyId___new__); func = _PyObject_GetAttrId((PyObject *)type, &PyId___new__);
@ -6830,7 +6836,7 @@ slot_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
return NULL; return NULL;
} }
result = _PyObject_Call_Prepend(func, (PyObject *)type, args, kwds); result = _PyObject_Call_Prepend(tstate, func, (PyObject *)type, args, kwds);
Py_DECREF(func); Py_DECREF(func);
return result; return result;
} }

View File

@ -160,6 +160,7 @@
<ClInclude Include="..\Include\import.h" /> <ClInclude Include="..\Include\import.h" />
<ClInclude Include="..\Include\internal\pycore_accu.h" /> <ClInclude Include="..\Include\internal\pycore_accu.h" />
<ClInclude Include="..\Include\internal\pycore_atomic.h" /> <ClInclude Include="..\Include\internal\pycore_atomic.h" />
<ClInclude Include="..\Include\internal\pycore_call.h" />
<ClInclude Include="..\Include\internal\pycore_ceval.h" /> <ClInclude Include="..\Include\internal\pycore_ceval.h" />
<ClInclude Include="..\Include\internal\pycore_code.h" /> <ClInclude Include="..\Include\internal\pycore_code.h" />
<ClInclude Include="..\Include\internal\pycore_condvar.h" /> <ClInclude Include="..\Include\internal\pycore_condvar.h" />

View File

@ -183,6 +183,9 @@
<ClInclude Include="..\Include\internal\pycore_atomic.h"> <ClInclude Include="..\Include\internal\pycore_atomic.h">
<Filter>Include</Filter> <Filter>Include</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\Include\internal\pycore_call.h">
<Filter>Include</Filter>
</ClInclude>
<ClInclude Include="..\Include\internal\pycore_code.h"> <ClInclude Include="..\Include\internal\pycore_code.h">
<Filter>Include</Filter> <Filter>Include</Filter>
</ClInclude> </ClInclude>

View File

@ -1,4 +1,5 @@
#include "Python.h" #include "Python.h"
#include "pycore_pyerrors.h"
#include "pycore_pystate.h" #include "pycore_pystate.h"
#include "frameobject.h" #include "frameobject.h"
#include "clinic/_warnings.c.h" #include "clinic/_warnings.c.h"
@ -27,10 +28,11 @@ static struct PyModuleDef warningsmodule;
static WarningsState * static WarningsState *
_Warnings_GetState() _Warnings_GetState()
{ {
PyThreadState *tstate = PyThreadState_GET(); PyThreadState *tstate = _PyThreadState_GET();
if (tstate == NULL) { if (tstate == NULL) {
PyErr_SetString(PyExc_RuntimeError, _PyErr_SetString(tstate, PyExc_RuntimeError,
"_Warnings_GetState: could not identify current interpreter"); "_Warnings_GetState: could not identify "
"current interpreter");
return NULL; return NULL;
} }
return &tstate->interp->warnings; return &tstate->interp->warnings;

View File

@ -4,6 +4,7 @@
#include <ctype.h> #include <ctype.h>
#include "ast.h" #include "ast.h"
#undef Yield /* undefine macro conflicting with <winbase.h> */ #undef Yield /* undefine macro conflicting with <winbase.h> */
#include "pycore_pyerrors.h"
#include "pycore_pystate.h" #include "pycore_pystate.h"
#include "pycore_tupleobject.h" #include "pycore_tupleobject.h"
@ -1254,23 +1255,23 @@ map_next(mapobject *lz)
{ {
PyObject *small_stack[_PY_FASTCALL_SMALL_STACK]; PyObject *small_stack[_PY_FASTCALL_SMALL_STACK];
PyObject **stack; PyObject **stack;
Py_ssize_t niters, nargs, i;
PyObject *result = NULL; PyObject *result = NULL;
PyThreadState *tstate = _PyThreadState_GET();
niters = PyTuple_GET_SIZE(lz->iters); const Py_ssize_t niters = PyTuple_GET_SIZE(lz->iters);
if (niters <= (Py_ssize_t)Py_ARRAY_LENGTH(small_stack)) { if (niters <= (Py_ssize_t)Py_ARRAY_LENGTH(small_stack)) {
stack = small_stack; stack = small_stack;
} }
else { else {
stack = PyMem_Malloc(niters * sizeof(stack[0])); stack = PyMem_Malloc(niters * sizeof(stack[0]));
if (stack == NULL) { if (stack == NULL) {
PyErr_NoMemory(); _PyErr_NoMemory(tstate);
return NULL; return NULL;
} }
} }
nargs = 0; Py_ssize_t nargs = 0;
for (i=0; i < niters; i++) { for (Py_ssize_t i=0; i < niters; i++) {
PyObject *it = PyTuple_GET_ITEM(lz->iters, i); PyObject *it = PyTuple_GET_ITEM(lz->iters, i);
PyObject *val = Py_TYPE(it)->tp_iternext(it); PyObject *val = Py_TYPE(it)->tp_iternext(it);
if (val == NULL) { if (val == NULL) {
@ -1280,10 +1281,10 @@ map_next(mapobject *lz)
nargs++; nargs++;
} }
result = _PyObject_FastCall(lz->func, stack, nargs); result = _PyObject_VectorcallTstate(tstate, lz->func, stack, nargs, NULL);
exit: exit:
for (i=0; i < nargs; i++) { for (Py_ssize_t i=0; i < nargs; i++) {
Py_DECREF(stack[i]); Py_DECREF(stack[i]);
} }
if (stack != small_stack) { if (stack != small_stack) {

View File

@ -10,6 +10,7 @@
#define PY_LOCAL_AGGRESSIVE #define PY_LOCAL_AGGRESSIVE
#include "Python.h" #include "Python.h"
#include "pycore_call.h"
#include "pycore_ceval.h" #include "pycore_ceval.h"
#include "pycore_code.h" #include "pycore_code.h"
#include "pycore_object.h" #include "pycore_object.h"
@ -4306,7 +4307,6 @@ fail: /* Jump here from prelude on failure */
current Python frame (f), the associated C stack is still in use, current Python frame (f), the associated C stack is still in use,
so recursion_depth must be boosted for the duration. so recursion_depth must be boosted for the duration.
*/ */
assert(tstate != NULL);
if (Py_REFCNT(f) > 1) { if (Py_REFCNT(f) > 1) {
Py_DECREF(f); Py_DECREF(f);
_PyObject_GC_TRACK(f); _PyObject_GC_TRACK(f);
@ -5024,10 +5024,11 @@ do_call_core(PyThreadState *tstate, PyObject *func, PyObject *callargs, PyObject
return NULL; return NULL;
} }
C_TRACE(result, _PyObject_FastCallDict(func, C_TRACE(result, _PyObject_FastCallDictTstate(
&_PyTuple_ITEMS(callargs)[1], tstate, func,
nargs - 1, &_PyTuple_ITEMS(callargs)[1],
kwdict)); nargs - 1,
kwdict));
Py_DECREF(func); Py_DECREF(func);
return result; return result;
} }