bpo-38644: Pass tstate to Py_EnterRecursiveCall() (GH-16997)
* Add _Py_EnterRecursiveCall() and _Py_LeaveRecursiveCall() which require a tstate argument. * Pass tstate to _Py_MakeRecCheck() and _Py_CheckRecursiveCall(). * Convert Py_EnterRecursiveCall() and Py_LeaveRecursiveCall() macros to static inline functions. _PyThreadState_GET() is the most efficient way to get the tstate, and so using it with _Py_EnterRecursiveCall() and _Py_LeaveRecursiveCall() should be a little bit more efficient than using Py_EnterRecursiveCall() and Py_LeaveRecursiveCall() which use the "slower" PyThreadState_GET().
This commit is contained in:
parent
f4b1e3d7c6
commit
be434dc038
|
@ -11,20 +11,31 @@ PyAPI_DATA(int) _Py_CheckRecursionLimit;
|
||||||
#ifdef USE_STACKCHECK
|
#ifdef USE_STACKCHECK
|
||||||
/* With USE_STACKCHECK macro defined, trigger stack checks in
|
/* With USE_STACKCHECK macro defined, trigger stack checks in
|
||||||
_Py_CheckRecursiveCall() on every 64th call to Py_EnterRecursiveCall. */
|
_Py_CheckRecursiveCall() on every 64th call to Py_EnterRecursiveCall. */
|
||||||
# define _Py_MakeRecCheck(x) \
|
static inline int _Py_MakeRecCheck(PyThreadState *tstate) {
|
||||||
(++(x) > _Py_CheckRecursionLimit || \
|
return (++tstate->recursion_depth > _Py_CheckRecursionLimit
|
||||||
++(PyThreadState_GET()->stackcheck_counter) > 64)
|
|| ++tstate->stackcheck_counter > 64);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
# define _Py_MakeRecCheck(x) (++(x) > _Py_CheckRecursionLimit)
|
static inline int _Py_MakeRecCheck(PyThreadState *tstate) {
|
||||||
|
return (++tstate->recursion_depth > _Py_CheckRecursionLimit);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
PyAPI_FUNC(int) _Py_CheckRecursiveCall(const char *where);
|
PyAPI_FUNC(int) _Py_CheckRecursiveCall(
|
||||||
|
PyThreadState *tstate,
|
||||||
|
const char *where);
|
||||||
|
|
||||||
#define _Py_EnterRecursiveCall_macro(where) \
|
static inline int _Py_EnterRecursiveCall(PyThreadState *tstate,
|
||||||
(_Py_MakeRecCheck(PyThreadState_GET()->recursion_depth) && \
|
const char *where) {
|
||||||
_Py_CheckRecursiveCall(where))
|
return (_Py_MakeRecCheck(tstate) && _Py_CheckRecursiveCall(tstate, where));
|
||||||
|
}
|
||||||
|
|
||||||
#define Py_EnterRecursiveCall(where) _Py_EnterRecursiveCall_macro(where)
|
static inline int _Py_EnterRecursiveCall_inline(const char *where) {
|
||||||
|
PyThreadState *tstate = PyThreadState_GET();
|
||||||
|
return _Py_EnterRecursiveCall(tstate, where);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define Py_EnterRecursiveCall(where) _Py_EnterRecursiveCall_inline(where)
|
||||||
|
|
||||||
|
|
||||||
/* Compute the "lower-water mark" for a recursion limit. When
|
/* Compute the "lower-water mark" for a recursion limit. When
|
||||||
|
@ -38,12 +49,18 @@ PyAPI_FUNC(int) _Py_CheckRecursiveCall(const char *where);
|
||||||
#define _Py_MakeEndRecCheck(x) \
|
#define _Py_MakeEndRecCheck(x) \
|
||||||
(--(x) < _Py_RecursionLimitLowerWaterMark(_Py_CheckRecursionLimit))
|
(--(x) < _Py_RecursionLimitLowerWaterMark(_Py_CheckRecursionLimit))
|
||||||
|
|
||||||
#define _Py_LeaveRecursiveCall_macro() \
|
static inline void _Py_LeaveRecursiveCall(PyThreadState *tstate) {
|
||||||
do{ if(_Py_MakeEndRecCheck(PyThreadState_GET()->recursion_depth)) \
|
if (_Py_MakeEndRecCheck(tstate->recursion_depth)) {
|
||||||
PyThreadState_GET()->overflowed = 0; \
|
tstate->overflowed = 0;
|
||||||
} while(0)
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#define Py_LeaveRecursiveCall() _Py_LeaveRecursiveCall_macro()
|
static inline void _Py_LeaveRecursiveCall_inline(void) {
|
||||||
|
PyThreadState *tstate = PyThreadState_GET();
|
||||||
|
_Py_LeaveRecursiveCall(tstate);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define Py_LeaveRecursiveCall() _Py_LeaveRecursiveCall_inline()
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/* Abstract Object Interface (many thanks to Jim Fulton) */
|
/* Abstract Object Interface (many thanks to Jim Fulton) */
|
||||||
|
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
|
#include "pycore_pyerrors.h"
|
||||||
#include "pycore_pystate.h"
|
#include "pycore_pystate.h"
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include "structmember.h" /* we need the offsetof() macro from there */
|
#include "structmember.h" /* we need the offsetof() macro from there */
|
||||||
|
@ -2459,8 +2460,8 @@ recursive_isinstance(PyObject *inst, PyObject *cls)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
static int
|
||||||
PyObject_IsInstance(PyObject *inst, PyObject *cls)
|
object_isinstance(PyThreadState *tstate, PyObject *inst, PyObject *cls)
|
||||||
{
|
{
|
||||||
_Py_IDENTIFIER(__instancecheck__);
|
_Py_IDENTIFIER(__instancecheck__);
|
||||||
PyObject *checker;
|
PyObject *checker;
|
||||||
|
@ -2475,34 +2476,31 @@ PyObject_IsInstance(PyObject *inst, PyObject *cls)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PyTuple_Check(cls)) {
|
if (PyTuple_Check(cls)) {
|
||||||
Py_ssize_t i;
|
if (_Py_EnterRecursiveCall(tstate, " in __instancecheck__")) {
|
||||||
Py_ssize_t n;
|
|
||||||
int r = 0;
|
|
||||||
|
|
||||||
if (Py_EnterRecursiveCall(" in __instancecheck__"))
|
|
||||||
return -1;
|
return -1;
|
||||||
n = PyTuple_GET_SIZE(cls);
|
}
|
||||||
for (i = 0; i < n; ++i) {
|
Py_ssize_t n = PyTuple_GET_SIZE(cls);
|
||||||
|
int r = 0;
|
||||||
|
for (Py_ssize_t i = 0; i < n; ++i) {
|
||||||
PyObject *item = PyTuple_GET_ITEM(cls, i);
|
PyObject *item = PyTuple_GET_ITEM(cls, i);
|
||||||
r = PyObject_IsInstance(inst, item);
|
r = object_isinstance(tstate, inst, item);
|
||||||
if (r != 0)
|
if (r != 0)
|
||||||
/* either found it, or got an error */
|
/* either found it, or got an error */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Py_LeaveRecursiveCall();
|
_Py_LeaveRecursiveCall(tstate);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
checker = _PyObject_LookupSpecial(cls, &PyId___instancecheck__);
|
checker = _PyObject_LookupSpecial(cls, &PyId___instancecheck__);
|
||||||
if (checker != NULL) {
|
if (checker != NULL) {
|
||||||
PyObject *res;
|
|
||||||
int ok = -1;
|
int ok = -1;
|
||||||
if (Py_EnterRecursiveCall(" in __instancecheck__")) {
|
if (_Py_EnterRecursiveCall(tstate, " in __instancecheck__")) {
|
||||||
Py_DECREF(checker);
|
Py_DECREF(checker);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
res = _PyObject_CallOneArg(checker, inst);
|
PyObject *res = _PyObject_CallOneArg(checker, inst);
|
||||||
Py_LeaveRecursiveCall();
|
_Py_LeaveRecursiveCall(tstate);
|
||||||
Py_DECREF(checker);
|
Py_DECREF(checker);
|
||||||
if (res != NULL) {
|
if (res != NULL) {
|
||||||
ok = PyObject_IsTrue(res);
|
ok = PyObject_IsTrue(res);
|
||||||
|
@ -2510,12 +2508,23 @@ PyObject_IsInstance(PyObject *inst, PyObject *cls)
|
||||||
}
|
}
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
else if (PyErr_Occurred())
|
else if (_PyErr_Occurred(tstate)) {
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Probably never reached anymore. */
|
/* Probably never reached anymore. */
|
||||||
return recursive_isinstance(inst, cls);
|
return recursive_isinstance(inst, cls);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
PyObject_IsInstance(PyObject *inst, PyObject *cls)
|
||||||
|
{
|
||||||
|
PyThreadState *tstate = _PyThreadState_GET();
|
||||||
|
return object_isinstance(tstate, inst, cls);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
recursive_issubclass(PyObject *derived, PyObject *cls)
|
recursive_issubclass(PyObject *derived, PyObject *cls)
|
||||||
{
|
{
|
||||||
|
@ -2534,8 +2543,8 @@ recursive_issubclass(PyObject *derived, PyObject *cls)
|
||||||
return abstract_issubclass(derived, cls);
|
return abstract_issubclass(derived, cls);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
static int
|
||||||
PyObject_IsSubclass(PyObject *derived, PyObject *cls)
|
object_issubclass(PyThreadState *tstate, PyObject *derived, PyObject *cls)
|
||||||
{
|
{
|
||||||
_Py_IDENTIFIER(__subclasscheck__);
|
_Py_IDENTIFIER(__subclasscheck__);
|
||||||
PyObject *checker;
|
PyObject *checker;
|
||||||
|
@ -2549,34 +2558,32 @@ PyObject_IsSubclass(PyObject *derived, PyObject *cls)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PyTuple_Check(cls)) {
|
if (PyTuple_Check(cls)) {
|
||||||
Py_ssize_t i;
|
|
||||||
Py_ssize_t n;
|
|
||||||
int r = 0;
|
|
||||||
|
|
||||||
if (Py_EnterRecursiveCall(" in __subclasscheck__"))
|
if (_Py_EnterRecursiveCall(tstate, " in __subclasscheck__")) {
|
||||||
return -1;
|
return -1;
|
||||||
n = PyTuple_GET_SIZE(cls);
|
}
|
||||||
for (i = 0; i < n; ++i) {
|
Py_ssize_t n = PyTuple_GET_SIZE(cls);
|
||||||
|
int r = 0;
|
||||||
|
for (Py_ssize_t i = 0; i < n; ++i) {
|
||||||
PyObject *item = PyTuple_GET_ITEM(cls, i);
|
PyObject *item = PyTuple_GET_ITEM(cls, i);
|
||||||
r = PyObject_IsSubclass(derived, item);
|
r = object_issubclass(tstate, derived, item);
|
||||||
if (r != 0)
|
if (r != 0)
|
||||||
/* either found it, or got an error */
|
/* either found it, or got an error */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Py_LeaveRecursiveCall();
|
_Py_LeaveRecursiveCall(tstate);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
checker = _PyObject_LookupSpecial(cls, &PyId___subclasscheck__);
|
checker = _PyObject_LookupSpecial(cls, &PyId___subclasscheck__);
|
||||||
if (checker != NULL) {
|
if (checker != NULL) {
|
||||||
PyObject *res;
|
|
||||||
int ok = -1;
|
int ok = -1;
|
||||||
if (Py_EnterRecursiveCall(" in __subclasscheck__")) {
|
if (_Py_EnterRecursiveCall(tstate, " in __subclasscheck__")) {
|
||||||
Py_DECREF(checker);
|
Py_DECREF(checker);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
res = _PyObject_CallOneArg(checker, derived);
|
PyObject *res = _PyObject_CallOneArg(checker, derived);
|
||||||
Py_LeaveRecursiveCall();
|
_Py_LeaveRecursiveCall(tstate);
|
||||||
Py_DECREF(checker);
|
Py_DECREF(checker);
|
||||||
if (res != NULL) {
|
if (res != NULL) {
|
||||||
ok = PyObject_IsTrue(res);
|
ok = PyObject_IsTrue(res);
|
||||||
|
@ -2584,12 +2591,23 @@ PyObject_IsSubclass(PyObject *derived, PyObject *cls)
|
||||||
}
|
}
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
else if (PyErr_Occurred())
|
else if (_PyErr_Occurred(tstate)) {
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Probably never reached anymore. */
|
/* Probably never reached anymore. */
|
||||||
return recursive_issubclass(derived, cls);
|
return recursive_issubclass(derived, cls);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
PyObject_IsSubclass(PyObject *derived, PyObject *cls)
|
||||||
|
{
|
||||||
|
PyThreadState *tstate = _PyThreadState_GET();
|
||||||
|
return object_issubclass(tstate, derived, cls);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
_PyObject_RealIsInstance(PyObject *inst, PyObject *cls)
|
_PyObject_RealIsInstance(PyObject *inst, PyObject *cls)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
#include "pycore_object.h"
|
#include "pycore_object.h"
|
||||||
|
#include "pycore_pyerrors.h"
|
||||||
#include "pycore_pystate.h"
|
#include "pycore_pystate.h"
|
||||||
#include "pycore_tupleobject.h"
|
#include "pycore_tupleobject.h"
|
||||||
#include "frameobject.h"
|
#include "frameobject.h"
|
||||||
|
@ -126,12 +127,15 @@ _PyObject_FastCallDict(PyObject *callable, PyObject *const *args,
|
||||||
PyObject *
|
PyObject *
|
||||||
_PyObject_MakeTpCall(PyObject *callable, PyObject *const *args, Py_ssize_t nargs, PyObject *keywords)
|
_PyObject_MakeTpCall(PyObject *callable, PyObject *const *args, Py_ssize_t nargs, PyObject *keywords)
|
||||||
{
|
{
|
||||||
|
PyThreadState *tstate = _PyThreadState_GET();
|
||||||
|
|
||||||
/* 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;
|
||||||
if (call == NULL) {
|
if (call == NULL) {
|
||||||
PyErr_Format(PyExc_TypeError, "'%.200s' object is not callable",
|
_PyErr_Format(tstate, PyExc_TypeError,
|
||||||
Py_TYPE(callable)->tp_name);
|
"'%.200s' object is not callable",
|
||||||
|
Py_TYPE(callable)->tp_name);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,10 +166,10 @@ _PyObject_MakeTpCall(PyObject *callable, PyObject *const *args, Py_ssize_t nargs
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject *result = NULL;
|
PyObject *result = NULL;
|
||||||
if (Py_EnterRecursiveCall(" while calling a Python object") == 0)
|
if (_Py_EnterRecursiveCall(tstate, " while calling a Python object") == 0)
|
||||||
{
|
{
|
||||||
result = call(callable, argstuple, kwdict);
|
result = call(callable, argstuple, kwdict);
|
||||||
Py_LeaveRecursiveCall();
|
_Py_LeaveRecursiveCall(tstate);
|
||||||
}
|
}
|
||||||
|
|
||||||
Py_DECREF(argstuple);
|
Py_DECREF(argstuple);
|
||||||
|
@ -220,13 +224,14 @@ PyVectorcall_Call(PyObject *callable, PyObject *tuple, PyObject *kwargs)
|
||||||
PyObject *
|
PyObject *
|
||||||
PyObject_Call(PyObject *callable, PyObject *args, PyObject *kwargs)
|
PyObject_Call(PyObject *callable, PyObject *args, PyObject *kwargs)
|
||||||
{
|
{
|
||||||
|
PyThreadState *tstate = _PyThreadState_GET();
|
||||||
ternaryfunc call;
|
ternaryfunc call;
|
||||||
PyObject *result;
|
PyObject *result;
|
||||||
|
|
||||||
/* PyObject_Call() must not be called with an exception set,
|
/* PyObject_Call() 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 */
|
||||||
assert(!PyErr_Occurred());
|
assert(!_PyErr_Occurred(tstate));
|
||||||
assert(PyTuple_Check(args));
|
assert(PyTuple_Check(args));
|
||||||
assert(kwargs == NULL || PyDict_Check(kwargs));
|
assert(kwargs == NULL || PyDict_Check(kwargs));
|
||||||
|
|
||||||
|
@ -236,17 +241,19 @@ PyObject_Call(PyObject *callable, PyObject *args, PyObject *kwargs)
|
||||||
else {
|
else {
|
||||||
call = callable->ob_type->tp_call;
|
call = callable->ob_type->tp_call;
|
||||||
if (call == NULL) {
|
if (call == NULL) {
|
||||||
PyErr_Format(PyExc_TypeError, "'%.200s' object is not callable",
|
_PyErr_Format(tstate, PyExc_TypeError,
|
||||||
callable->ob_type->tp_name);
|
"'%.200s' object is not callable",
|
||||||
|
callable->ob_type->tp_name);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Py_EnterRecursiveCall(" while calling a Python object"))
|
if (_Py_EnterRecursiveCall(tstate, " while calling a Python object")) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
result = (*call)(callable, args, kwargs);
|
result = (*call)(callable, args, kwargs);
|
||||||
|
|
||||||
Py_LeaveRecursiveCall();
|
_Py_LeaveRecursiveCall(tstate);
|
||||||
|
|
||||||
return _Py_CheckFunctionResult(callable, result, NULL);
|
return _Py_CheckFunctionResult(callable, result, NULL);
|
||||||
}
|
}
|
||||||
|
@ -266,30 +273,27 @@ static PyObject* _Py_HOT_FUNCTION
|
||||||
function_code_fastcall(PyCodeObject *co, PyObject *const *args, Py_ssize_t nargs,
|
function_code_fastcall(PyCodeObject *co, PyObject *const *args, Py_ssize_t nargs,
|
||||||
PyObject *globals)
|
PyObject *globals)
|
||||||
{
|
{
|
||||||
PyFrameObject *f;
|
|
||||||
PyThreadState *tstate = _PyThreadState_GET();
|
|
||||||
PyObject **fastlocals;
|
|
||||||
Py_ssize_t i;
|
|
||||||
PyObject *result;
|
|
||||||
|
|
||||||
assert(globals != NULL);
|
assert(globals != NULL);
|
||||||
|
|
||||||
|
PyThreadState *tstate = _PyThreadState_GET();
|
||||||
|
assert(tstate != NULL);
|
||||||
|
|
||||||
/* XXX Perhaps we should create a specialized
|
/* XXX Perhaps we should create a specialized
|
||||||
_PyFrame_New_NoTrack() that doesn't take locals, but does
|
_PyFrame_New_NoTrack() that doesn't take locals, but does
|
||||||
take builtins without sanity checking them.
|
take builtins without sanity checking them.
|
||||||
*/
|
*/
|
||||||
assert(tstate != NULL);
|
PyFrameObject *f = _PyFrame_New_NoTrack(tstate, co, globals, NULL);
|
||||||
f = _PyFrame_New_NoTrack(tstate, co, globals, NULL);
|
|
||||||
if (f == NULL) {
|
if (f == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
fastlocals = f->f_localsplus;
|
PyObject **fastlocals = f->f_localsplus;
|
||||||
|
|
||||||
for (i = 0; i < nargs; i++) {
|
for (Py_ssize_t i = 0; i < nargs; i++) {
|
||||||
Py_INCREF(*args);
|
Py_INCREF(*args);
|
||||||
fastlocals[i] = *args++;
|
fastlocals[i] = *args++;
|
||||||
}
|
}
|
||||||
result = PyEval_EvalFrameEx(f,0);
|
PyObject *result = PyEval_EvalFrameEx(f, 0);
|
||||||
|
|
||||||
if (Py_REFCNT(f) > 1) {
|
if (Py_REFCNT(f) > 1) {
|
||||||
Py_DECREF(f);
|
Py_DECREF(f);
|
||||||
|
|
|
@ -271,9 +271,9 @@ method_check_args(PyObject *func, PyObject *const *args, Py_ssize_t nargs, PyObj
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline funcptr
|
static inline funcptr
|
||||||
method_enter_call(PyObject *func)
|
method_enter_call(PyThreadState *tstate, PyObject *func)
|
||||||
{
|
{
|
||||||
if (Py_EnterRecursiveCall(" while calling a Python object")) {
|
if (_Py_EnterRecursiveCall(tstate, " while calling a Python object")) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return (funcptr)((PyMethodDescrObject *)func)->d_method->ml_meth;
|
return (funcptr)((PyMethodDescrObject *)func)->d_method->ml_meth;
|
||||||
|
@ -284,6 +284,7 @@ static PyObject *
|
||||||
method_vectorcall_VARARGS(
|
method_vectorcall_VARARGS(
|
||||||
PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
|
PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
|
||||||
{
|
{
|
||||||
|
PyThreadState *tstate = _PyThreadState_GET();
|
||||||
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
|
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
|
||||||
if (method_check_args(func, args, nargs, kwnames)) {
|
if (method_check_args(func, args, nargs, kwnames)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -292,14 +293,14 @@ method_vectorcall_VARARGS(
|
||||||
if (argstuple == NULL) {
|
if (argstuple == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
PyCFunction meth = (PyCFunction)method_enter_call(func);
|
PyCFunction meth = (PyCFunction)method_enter_call(tstate, func);
|
||||||
if (meth == NULL) {
|
if (meth == NULL) {
|
||||||
Py_DECREF(argstuple);
|
Py_DECREF(argstuple);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
PyObject *result = meth(args[0], argstuple);
|
PyObject *result = meth(args[0], argstuple);
|
||||||
Py_DECREF(argstuple);
|
Py_DECREF(argstuple);
|
||||||
Py_LeaveRecursiveCall();
|
_Py_LeaveRecursiveCall(tstate);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -307,6 +308,7 @@ static PyObject *
|
||||||
method_vectorcall_VARARGS_KEYWORDS(
|
method_vectorcall_VARARGS_KEYWORDS(
|
||||||
PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
|
PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
|
||||||
{
|
{
|
||||||
|
PyThreadState *tstate = _PyThreadState_GET();
|
||||||
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
|
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
|
||||||
if (method_check_args(func, args, nargs, NULL)) {
|
if (method_check_args(func, args, nargs, NULL)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -325,12 +327,12 @@ method_vectorcall_VARARGS_KEYWORDS(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PyCFunctionWithKeywords meth = (PyCFunctionWithKeywords)
|
PyCFunctionWithKeywords meth = (PyCFunctionWithKeywords)
|
||||||
method_enter_call(func);
|
method_enter_call(tstate, func);
|
||||||
if (meth == NULL) {
|
if (meth == NULL) {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
result = meth(args[0], argstuple, kwdict);
|
result = meth(args[0], argstuple, kwdict);
|
||||||
Py_LeaveRecursiveCall();
|
_Py_LeaveRecursiveCall(tstate);
|
||||||
exit:
|
exit:
|
||||||
Py_DECREF(argstuple);
|
Py_DECREF(argstuple);
|
||||||
Py_XDECREF(kwdict);
|
Py_XDECREF(kwdict);
|
||||||
|
@ -341,17 +343,18 @@ static PyObject *
|
||||||
method_vectorcall_FASTCALL(
|
method_vectorcall_FASTCALL(
|
||||||
PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
|
PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
|
||||||
{
|
{
|
||||||
|
PyThreadState *tstate = _PyThreadState_GET();
|
||||||
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
|
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
|
||||||
if (method_check_args(func, args, nargs, kwnames)) {
|
if (method_check_args(func, args, nargs, kwnames)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
_PyCFunctionFast meth = (_PyCFunctionFast)
|
_PyCFunctionFast meth = (_PyCFunctionFast)
|
||||||
method_enter_call(func);
|
method_enter_call(tstate, func);
|
||||||
if (meth == NULL) {
|
if (meth == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
PyObject *result = meth(args[0], args+1, nargs-1);
|
PyObject *result = meth(args[0], args+1, nargs-1);
|
||||||
Py_LeaveRecursiveCall();
|
_Py_LeaveRecursiveCall(tstate);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -359,17 +362,18 @@ static PyObject *
|
||||||
method_vectorcall_FASTCALL_KEYWORDS(
|
method_vectorcall_FASTCALL_KEYWORDS(
|
||||||
PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
|
PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
|
||||||
{
|
{
|
||||||
|
PyThreadState *tstate = _PyThreadState_GET();
|
||||||
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
|
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
|
||||||
if (method_check_args(func, args, nargs, NULL)) {
|
if (method_check_args(func, args, nargs, NULL)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
_PyCFunctionFastWithKeywords meth = (_PyCFunctionFastWithKeywords)
|
_PyCFunctionFastWithKeywords meth = (_PyCFunctionFastWithKeywords)
|
||||||
method_enter_call(func);
|
method_enter_call(tstate, func);
|
||||||
if (meth == NULL) {
|
if (meth == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
PyObject *result = meth(args[0], args+1, nargs-1, kwnames);
|
PyObject *result = meth(args[0], args+1, nargs-1, kwnames);
|
||||||
Py_LeaveRecursiveCall();
|
_Py_LeaveRecursiveCall(tstate);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -377,6 +381,7 @@ static PyObject *
|
||||||
method_vectorcall_NOARGS(
|
method_vectorcall_NOARGS(
|
||||||
PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
|
PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
|
||||||
{
|
{
|
||||||
|
PyThreadState *tstate = _PyThreadState_GET();
|
||||||
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
|
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
|
||||||
if (method_check_args(func, args, nargs, kwnames)) {
|
if (method_check_args(func, args, nargs, kwnames)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -386,12 +391,12 @@ method_vectorcall_NOARGS(
|
||||||
"%.200s() takes no arguments (%zd given)", get_name(func), nargs-1);
|
"%.200s() takes no arguments (%zd given)", get_name(func), nargs-1);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
PyCFunction meth = (PyCFunction)method_enter_call(func);
|
PyCFunction meth = (PyCFunction)method_enter_call(tstate, func);
|
||||||
if (meth == NULL) {
|
if (meth == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
PyObject *result = meth(args[0], NULL);
|
PyObject *result = meth(args[0], NULL);
|
||||||
Py_LeaveRecursiveCall();
|
_Py_LeaveRecursiveCall(tstate);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -399,6 +404,7 @@ static PyObject *
|
||||||
method_vectorcall_O(
|
method_vectorcall_O(
|
||||||
PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
|
PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
|
||||||
{
|
{
|
||||||
|
PyThreadState *tstate = _PyThreadState_GET();
|
||||||
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
|
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
|
||||||
if (method_check_args(func, args, nargs, kwnames)) {
|
if (method_check_args(func, args, nargs, kwnames)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -409,12 +415,12 @@ method_vectorcall_O(
|
||||||
get_name(func), nargs-1);
|
get_name(func), nargs-1);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
PyCFunction meth = (PyCFunction)method_enter_call(func);
|
PyCFunction meth = (PyCFunction)method_enter_call(tstate, func);
|
||||||
if (meth == NULL) {
|
if (meth == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
PyObject *result = meth(args[0], args[1]);
|
PyObject *result = meth(args[0], args[1]);
|
||||||
Py_LeaveRecursiveCall();
|
_Py_LeaveRecursiveCall(tstate);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
#include "pycore_object.h"
|
#include "pycore_object.h"
|
||||||
|
#include "pycore_pyerrors.h"
|
||||||
#include "pycore_pymem.h"
|
#include "pycore_pymem.h"
|
||||||
#include "pycore_pystate.h"
|
#include "pycore_pystate.h"
|
||||||
#include "structmember.h"
|
#include "structmember.h"
|
||||||
|
@ -344,22 +345,22 @@ get_name(PyObject *func)
|
||||||
typedef void (*funcptr)(void);
|
typedef void (*funcptr)(void);
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
cfunction_check_kwargs(PyObject *func, PyObject *kwnames)
|
cfunction_check_kwargs(PyThreadState *tstate, PyObject *func, PyObject *kwnames)
|
||||||
{
|
{
|
||||||
assert(!PyErr_Occurred());
|
assert(!_PyErr_Occurred(tstate));
|
||||||
assert(PyCFunction_Check(func));
|
assert(PyCFunction_Check(func));
|
||||||
if (kwnames && PyTuple_GET_SIZE(kwnames)) {
|
if (kwnames && PyTuple_GET_SIZE(kwnames)) {
|
||||||
PyErr_Format(PyExc_TypeError,
|
_PyErr_Format(tstate, PyExc_TypeError,
|
||||||
"%.200s() takes no keyword arguments", get_name(func));
|
"%.200s() takes no keyword arguments", get_name(func));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline funcptr
|
static inline funcptr
|
||||||
cfunction_enter_call(PyObject *func)
|
cfunction_enter_call(PyThreadState *tstate, PyObject *func)
|
||||||
{
|
{
|
||||||
if (Py_EnterRecursiveCall(" while calling a Python object")) {
|
if (_Py_EnterRecursiveCall(tstate, " while calling a Python object")) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return (funcptr)PyCFunction_GET_FUNCTION(func);
|
return (funcptr)PyCFunction_GET_FUNCTION(func);
|
||||||
|
@ -370,17 +371,18 @@ static PyObject *
|
||||||
cfunction_vectorcall_FASTCALL(
|
cfunction_vectorcall_FASTCALL(
|
||||||
PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
|
PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
|
||||||
{
|
{
|
||||||
if (cfunction_check_kwargs(func, kwnames)) {
|
PyThreadState *tstate = _PyThreadState_GET();
|
||||||
|
if (cfunction_check_kwargs(tstate, func, kwnames)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
|
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
|
||||||
_PyCFunctionFast meth = (_PyCFunctionFast)
|
_PyCFunctionFast meth = (_PyCFunctionFast)
|
||||||
cfunction_enter_call(func);
|
cfunction_enter_call(tstate, func);
|
||||||
if (meth == NULL) {
|
if (meth == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
PyObject *result = meth(PyCFunction_GET_SELF(func), args, nargs);
|
PyObject *result = meth(PyCFunction_GET_SELF(func), args, nargs);
|
||||||
Py_LeaveRecursiveCall();
|
_Py_LeaveRecursiveCall(tstate);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -388,14 +390,15 @@ static PyObject *
|
||||||
cfunction_vectorcall_FASTCALL_KEYWORDS(
|
cfunction_vectorcall_FASTCALL_KEYWORDS(
|
||||||
PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
|
PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
|
||||||
{
|
{
|
||||||
|
PyThreadState *tstate = _PyThreadState_GET();
|
||||||
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
|
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
|
||||||
_PyCFunctionFastWithKeywords meth = (_PyCFunctionFastWithKeywords)
|
_PyCFunctionFastWithKeywords meth = (_PyCFunctionFastWithKeywords)
|
||||||
cfunction_enter_call(func);
|
cfunction_enter_call(tstate, func);
|
||||||
if (meth == NULL) {
|
if (meth == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
PyObject *result = meth(PyCFunction_GET_SELF(func), args, nargs, kwnames);
|
PyObject *result = meth(PyCFunction_GET_SELF(func), args, nargs, kwnames);
|
||||||
Py_LeaveRecursiveCall();
|
_Py_LeaveRecursiveCall(tstate);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -403,21 +406,23 @@ static PyObject *
|
||||||
cfunction_vectorcall_NOARGS(
|
cfunction_vectorcall_NOARGS(
|
||||||
PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
|
PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
|
||||||
{
|
{
|
||||||
if (cfunction_check_kwargs(func, kwnames)) {
|
PyThreadState *tstate = _PyThreadState_GET();
|
||||||
|
if (cfunction_check_kwargs(tstate, func, kwnames)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
|
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
|
||||||
if (nargs != 0) {
|
if (nargs != 0) {
|
||||||
PyErr_Format(PyExc_TypeError,
|
_PyErr_Format(tstate, PyExc_TypeError,
|
||||||
"%.200s() takes no arguments (%zd given)", get_name(func), nargs);
|
"%.200s() takes no arguments (%zd given)",
|
||||||
|
get_name(func), nargs);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
PyCFunction meth = (PyCFunction)cfunction_enter_call(func);
|
PyCFunction meth = (PyCFunction)cfunction_enter_call(tstate, func);
|
||||||
if (meth == NULL) {
|
if (meth == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
PyObject *result = meth(PyCFunction_GET_SELF(func), NULL);
|
PyObject *result = meth(PyCFunction_GET_SELF(func), NULL);
|
||||||
Py_LeaveRecursiveCall();
|
_Py_LeaveRecursiveCall(tstate);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -425,22 +430,23 @@ static PyObject *
|
||||||
cfunction_vectorcall_O(
|
cfunction_vectorcall_O(
|
||||||
PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
|
PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
|
||||||
{
|
{
|
||||||
if (cfunction_check_kwargs(func, kwnames)) {
|
PyThreadState *tstate = _PyThreadState_GET();
|
||||||
|
if (cfunction_check_kwargs(tstate, func, kwnames)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
|
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
|
||||||
if (nargs != 1) {
|
if (nargs != 1) {
|
||||||
PyErr_Format(PyExc_TypeError,
|
_PyErr_Format(tstate, PyExc_TypeError,
|
||||||
"%.200s() takes exactly one argument (%zd given)",
|
"%.200s() takes exactly one argument (%zd given)",
|
||||||
get_name(func), nargs);
|
get_name(func), nargs);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
PyCFunction meth = (PyCFunction)cfunction_enter_call(func);
|
PyCFunction meth = (PyCFunction)cfunction_enter_call(tstate, func);
|
||||||
if (meth == NULL) {
|
if (meth == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
PyObject *result = meth(PyCFunction_GET_SELF(func), args[0]);
|
PyObject *result = meth(PyCFunction_GET_SELF(func), args[0]);
|
||||||
Py_LeaveRecursiveCall();
|
_Py_LeaveRecursiveCall(tstate);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,10 +2,11 @@
|
||||||
/* Generic object operations; and implementation of None */
|
/* Generic object operations; and implementation of None */
|
||||||
|
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
|
#include "pycore_context.h"
|
||||||
#include "pycore_initconfig.h"
|
#include "pycore_initconfig.h"
|
||||||
#include "pycore_object.h"
|
#include "pycore_object.h"
|
||||||
|
#include "pycore_pyerrors.h"
|
||||||
#include "pycore_pystate.h"
|
#include "pycore_pystate.h"
|
||||||
#include "pycore_context.h"
|
|
||||||
#include "frameobject.h"
|
#include "frameobject.h"
|
||||||
#include "interpreteridobject.h"
|
#include "interpreteridobject.h"
|
||||||
|
|
||||||
|
@ -525,31 +526,37 @@ PyObject_Repr(PyObject *v)
|
||||||
return PyUnicode_FromFormat("<%s object at %p>",
|
return PyUnicode_FromFormat("<%s object at %p>",
|
||||||
v->ob_type->tp_name, v);
|
v->ob_type->tp_name, v);
|
||||||
|
|
||||||
|
PyThreadState *tstate = _PyThreadState_GET();
|
||||||
#ifdef Py_DEBUG
|
#ifdef Py_DEBUG
|
||||||
/* PyObject_Repr() must not be called with an exception set,
|
/* PyObject_Repr() 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 */
|
||||||
assert(!PyErr_Occurred());
|
assert(!_PyErr_Occurred(tstate));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* It is possible for a type to have a tp_repr representation that loops
|
/* It is possible for a type to have a tp_repr representation that loops
|
||||||
infinitely. */
|
infinitely. */
|
||||||
if (Py_EnterRecursiveCall(" while getting the repr of an object"))
|
if (_Py_EnterRecursiveCall(tstate,
|
||||||
|
" while getting the repr of an object")) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
res = (*v->ob_type->tp_repr)(v);
|
res = (*v->ob_type->tp_repr)(v);
|
||||||
Py_LeaveRecursiveCall();
|
_Py_LeaveRecursiveCall(tstate);
|
||||||
if (res == NULL)
|
|
||||||
|
if (res == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
if (!PyUnicode_Check(res)) {
|
if (!PyUnicode_Check(res)) {
|
||||||
PyErr_Format(PyExc_TypeError,
|
_PyErr_Format(tstate, PyExc_TypeError,
|
||||||
"__repr__ returned non-string (type %.200s)",
|
"__repr__ returned non-string (type %.200s)",
|
||||||
res->ob_type->tp_name);
|
res->ob_type->tp_name);
|
||||||
Py_DECREF(res);
|
Py_DECREF(res);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
#ifndef Py_DEBUG
|
#ifndef Py_DEBUG
|
||||||
if (PyUnicode_READY(res) < 0)
|
if (PyUnicode_READY(res) < 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -579,31 +586,36 @@ PyObject_Str(PyObject *v)
|
||||||
if (Py_TYPE(v)->tp_str == NULL)
|
if (Py_TYPE(v)->tp_str == NULL)
|
||||||
return PyObject_Repr(v);
|
return PyObject_Repr(v);
|
||||||
|
|
||||||
|
PyThreadState *tstate = _PyThreadState_GET();
|
||||||
#ifdef Py_DEBUG
|
#ifdef Py_DEBUG
|
||||||
/* PyObject_Str() must not be called with an exception set,
|
/* PyObject_Str() 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 */
|
||||||
assert(!PyErr_Occurred());
|
assert(!_PyErr_Occurred(tstate));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* It is possible for a type to have a tp_str representation that loops
|
/* It is possible for a type to have a tp_str representation that loops
|
||||||
infinitely. */
|
infinitely. */
|
||||||
if (Py_EnterRecursiveCall(" while getting the str of an object"))
|
if (_Py_EnterRecursiveCall(tstate, " while getting the str of an object")) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
res = (*Py_TYPE(v)->tp_str)(v);
|
res = (*Py_TYPE(v)->tp_str)(v);
|
||||||
Py_LeaveRecursiveCall();
|
_Py_LeaveRecursiveCall(tstate);
|
||||||
if (res == NULL)
|
|
||||||
|
if (res == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
if (!PyUnicode_Check(res)) {
|
if (!PyUnicode_Check(res)) {
|
||||||
PyErr_Format(PyExc_TypeError,
|
_PyErr_Format(tstate, PyExc_TypeError,
|
||||||
"__str__ returned non-string (type %.200s)",
|
"__str__ returned non-string (type %.200s)",
|
||||||
Py_TYPE(res)->tp_name);
|
Py_TYPE(res)->tp_name);
|
||||||
Py_DECREF(res);
|
Py_DECREF(res);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
#ifndef Py_DEBUG
|
#ifndef Py_DEBUG
|
||||||
if (PyUnicode_READY(res) < 0)
|
if (PyUnicode_READY(res) < 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
assert(_PyUnicode_CheckConsistency(res, 1));
|
assert(_PyUnicode_CheckConsistency(res, 1));
|
||||||
return res;
|
return res;
|
||||||
|
@ -707,7 +719,7 @@ static const char * const opstrings[] = {"<", "<=", "==", "!=", ">", ">="};
|
||||||
/* Perform a rich comparison, raising TypeError when the requested comparison
|
/* Perform a rich comparison, raising TypeError when the requested comparison
|
||||||
operator is not supported. */
|
operator is not supported. */
|
||||||
static PyObject *
|
static PyObject *
|
||||||
do_richcompare(PyObject *v, PyObject *w, int op)
|
do_richcompare(PyThreadState *tstate, PyObject *v, PyObject *w, int op)
|
||||||
{
|
{
|
||||||
richcmpfunc f;
|
richcmpfunc f;
|
||||||
PyObject *res;
|
PyObject *res;
|
||||||
|
@ -744,11 +756,11 @@ do_richcompare(PyObject *v, PyObject *w, int op)
|
||||||
res = (v != w) ? Py_True : Py_False;
|
res = (v != w) ? Py_True : Py_False;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
PyErr_Format(PyExc_TypeError,
|
_PyErr_Format(tstate, PyExc_TypeError,
|
||||||
"'%s' not supported between instances of '%.100s' and '%.100s'",
|
"'%s' not supported between instances of '%.100s' and '%.100s'",
|
||||||
opstrings[op],
|
opstrings[op],
|
||||||
v->ob_type->tp_name,
|
v->ob_type->tp_name,
|
||||||
w->ob_type->tp_name);
|
w->ob_type->tp_name);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
Py_INCREF(res);
|
Py_INCREF(res);
|
||||||
|
@ -761,18 +773,20 @@ do_richcompare(PyObject *v, PyObject *w, int op)
|
||||||
PyObject *
|
PyObject *
|
||||||
PyObject_RichCompare(PyObject *v, PyObject *w, int op)
|
PyObject_RichCompare(PyObject *v, PyObject *w, int op)
|
||||||
{
|
{
|
||||||
PyObject *res;
|
PyThreadState *tstate = _PyThreadState_GET();
|
||||||
|
|
||||||
assert(Py_LT <= op && op <= Py_GE);
|
assert(Py_LT <= op && op <= Py_GE);
|
||||||
if (v == NULL || w == NULL) {
|
if (v == NULL || w == NULL) {
|
||||||
if (!PyErr_Occurred())
|
if (!_PyErr_Occurred(tstate)) {
|
||||||
PyErr_BadInternalCall();
|
PyErr_BadInternalCall();
|
||||||
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (Py_EnterRecursiveCall(" in comparison"))
|
if (_Py_EnterRecursiveCall(tstate, " in comparison")) {
|
||||||
return NULL;
|
return NULL;
|
||||||
res = do_richcompare(v, w, op);
|
}
|
||||||
Py_LeaveRecursiveCall();
|
PyObject *res = do_richcompare(tstate, v, w, op);
|
||||||
|
_Py_LeaveRecursiveCall(tstate);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -659,16 +659,15 @@ Py_SetRecursionLimit(int new_limit)
|
||||||
_Py_CheckRecursionLimit = ceval->recursion_limit;
|
_Py_CheckRecursionLimit = ceval->recursion_limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* the macro Py_EnterRecursiveCall() only calls _Py_CheckRecursiveCall()
|
/* The function _Py_EnterRecursiveCall() only calls _Py_CheckRecursiveCall()
|
||||||
if the recursion_depth reaches _Py_CheckRecursionLimit.
|
if the recursion_depth reaches _Py_CheckRecursionLimit.
|
||||||
If USE_STACKCHECK, the macro decrements _Py_CheckRecursionLimit
|
If USE_STACKCHECK, the macro decrements _Py_CheckRecursionLimit
|
||||||
to guarantee that _Py_CheckRecursiveCall() is regularly called.
|
to guarantee that _Py_CheckRecursiveCall() is regularly called.
|
||||||
Without USE_STACKCHECK, there is no need for this. */
|
Without USE_STACKCHECK, there is no need for this. */
|
||||||
int
|
int
|
||||||
_Py_CheckRecursiveCall(const char *where)
|
_Py_CheckRecursiveCall(PyThreadState *tstate, const char *where)
|
||||||
{
|
{
|
||||||
_PyRuntimeState *runtime = &_PyRuntime;
|
_PyRuntimeState *runtime = &_PyRuntime;
|
||||||
PyThreadState *tstate = _PyRuntimeState_GetThreadState(runtime);
|
|
||||||
int recursion_limit = runtime->ceval.recursion_limit;
|
int recursion_limit = runtime->ceval.recursion_limit;
|
||||||
|
|
||||||
#ifdef USE_STACKCHECK
|
#ifdef USE_STACKCHECK
|
||||||
|
@ -1073,8 +1072,9 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
|
||||||
/* Start of code */
|
/* Start of code */
|
||||||
|
|
||||||
/* push frame */
|
/* push frame */
|
||||||
if (Py_EnterRecursiveCall(""))
|
if (_Py_EnterRecursiveCall(tstate, "")) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
tstate->frame = f;
|
tstate->frame = f;
|
||||||
|
|
||||||
|
@ -3810,7 +3810,7 @@ exit_yielding:
|
||||||
exit_eval_frame:
|
exit_eval_frame:
|
||||||
if (PyDTrace_FUNCTION_RETURN_ENABLED())
|
if (PyDTrace_FUNCTION_RETURN_ENABLED())
|
||||||
dtrace_function_return(f);
|
dtrace_function_return(f);
|
||||||
Py_LeaveRecursiveCall();
|
_Py_LeaveRecursiveCall(tstate);
|
||||||
f->f_executing = 0;
|
f->f_executing = 0;
|
||||||
tstate->frame = f->f_back;
|
tstate->frame = f->f_back;
|
||||||
|
|
||||||
|
@ -5641,12 +5641,12 @@ maybe_dtrace_line(PyFrameObject *frame,
|
||||||
|
|
||||||
int Py_EnterRecursiveCall(const char *where)
|
int Py_EnterRecursiveCall(const char *where)
|
||||||
{
|
{
|
||||||
return _Py_EnterRecursiveCall_macro(where);
|
return _Py_EnterRecursiveCall_inline(where);
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef Py_LeaveRecursiveCall
|
#undef Py_LeaveRecursiveCall
|
||||||
|
|
||||||
void Py_LeaveRecursiveCall(void)
|
void Py_LeaveRecursiveCall(void)
|
||||||
{
|
{
|
||||||
_Py_LeaveRecursiveCall_macro();
|
_Py_LeaveRecursiveCall_inline();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue