aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Python/ceval.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/ceval.c')
-rw-r--r--Python/ceval.c183
1 files changed, 122 insertions, 61 deletions
diff --git a/Python/ceval.c b/Python/ceval.c
index d36e15e55f5..2412256ace8 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -39,6 +39,7 @@
#include "opcode.h"
#include "pydtrace.h"
#include "setobject.h"
+#include "pycore_stackref.h"
#include <stdbool.h> // bool
@@ -104,33 +105,34 @@
#ifdef LLTRACE
static void
-dump_stack(_PyInterpreterFrame *frame, PyObject **stack_pointer)
+dump_stack(_PyInterpreterFrame *frame, _PyStackRef *stack_pointer)
{
- PyObject **stack_base = _PyFrame_Stackbase(frame);
+ _PyStackRef *stack_base = _PyFrame_Stackbase(frame);
PyObject *exc = PyErr_GetRaisedException();
printf(" stack=[");
- for (PyObject **ptr = stack_base; ptr < stack_pointer; ptr++) {
+ for (_PyStackRef *ptr = stack_base; ptr < stack_pointer; ptr++) {
if (ptr != stack_base) {
printf(", ");
}
- if (*ptr == NULL) {
+ PyObject *obj = PyStackRef_AsPyObjectBorrow(*ptr);
+ if (obj == NULL) {
printf("<nil>");
continue;
}
if (
- *ptr == Py_None
- || PyBool_Check(*ptr)
- || PyLong_CheckExact(*ptr)
- || PyFloat_CheckExact(*ptr)
- || PyUnicode_CheckExact(*ptr)
+ obj == Py_None
+ || PyBool_Check(obj)
+ || PyLong_CheckExact(obj)
+ || PyFloat_CheckExact(obj)
+ || PyUnicode_CheckExact(obj)
) {
- if (PyObject_Print(*ptr, stdout, 0) == 0) {
+ if (PyObject_Print(obj, stdout, 0) == 0) {
continue;
}
PyErr_Clear();
}
// Don't call __repr__(), it might recurse into the interpreter.
- printf("<%s at %p>", Py_TYPE(*ptr)->tp_name, (void *)(*ptr));
+ printf("<%s at %p>", Py_TYPE(obj)->tp_name, (void *)(ptr->bits));
}
printf("]\n");
fflush(stdout);
@@ -139,7 +141,7 @@ dump_stack(_PyInterpreterFrame *frame, PyObject **stack_pointer)
static void
lltrace_instruction(_PyInterpreterFrame *frame,
- PyObject **stack_pointer,
+ _PyStackRef *stack_pointer,
_Py_CODEUNIT *next_instr,
int opcode,
int oparg)
@@ -695,6 +697,35 @@ extern void _PyUOpPrint(const _PyUOpInstruction *uop);
#endif
+PyObject **
+_PyObjectArray_FromStackRefArray(_PyStackRef *input, Py_ssize_t nargs, PyObject **scratch)
+{
+ PyObject **result;
+ if (nargs > MAX_STACKREF_SCRATCH) {
+ // +1 in case PY_VECTORCALL_ARGUMENTS_OFFSET is set.
+ result = PyMem_Malloc((nargs + 1) * sizeof(PyObject *));
+ if (result == NULL) {
+ return NULL;
+ }
+ result++;
+ }
+ else {
+ result = scratch;
+ }
+ for (int i = 0; i < nargs; i++) {
+ result[i] = PyStackRef_AsPyObjectBorrow(input[i]);
+ }
+ return result;
+}
+
+void
+_PyObjectArray_Free(PyObject **array, PyObject **scratch)
+{
+ if (array != scratch) {
+ PyMem_Free(array);
+ }
+}
+
/* _PyEval_EvalFrameDefault() is a *big* function,
* so consume 3 units of C stack */
#define PY_EVAL_C_STACK_UNITS 2
@@ -773,7 +804,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
/* Local "register" variables.
* These are cached values from the frame and code object. */
_Py_CODEUNIT *next_instr;
- PyObject **stack_pointer;
+ _PyStackRef *stack_pointer;
#if defined(_Py_TIER2) && !defined(_Py_JIT)
/* Tier 2 interpreter state */
@@ -916,10 +947,9 @@ exception_unwind:
assert(_PyErr_Occurred(tstate));
/* Pop remaining stack entries. */
- PyObject **stackbase = _PyFrame_Stackbase(frame);
+ _PyStackRef *stackbase = _PyFrame_Stackbase(frame);
while (stack_pointer > stackbase) {
- PyObject *o = POP();
- Py_XDECREF(o);
+ PyStackRef_XCLOSE(POP());
}
assert(STACK_LEVEL() == 0);
_PyFrame_SetStackPointer(frame, stack_pointer);
@@ -928,10 +958,9 @@ exception_unwind:
}
assert(STACK_LEVEL() >= level);
- PyObject **new_top = _PyFrame_Stackbase(frame) + level;
+ _PyStackRef *new_top = _PyFrame_Stackbase(frame) + level;
while (stack_pointer > new_top) {
- PyObject *v = POP();
- Py_XDECREF(v);
+ PyStackRef_XCLOSE(POP());
}
if (lasti) {
int frame_lasti = _PyInterpreterFrame_LASTI(frame);
@@ -939,7 +968,7 @@ exception_unwind:
if (lasti == NULL) {
goto exception_unwind;
}
- PUSH(lasti);
+ PUSH(PyStackRef_FromPyObjectSteal(lasti));
}
/* Make the raw exception data
@@ -947,7 +976,7 @@ exception_unwind:
so a program can emulate the
Python main loop. */
PyObject *exc = _PyErr_GetRaisedException(tstate);
- PUSH(exc);
+ PUSH(PyStackRef_FromPyObjectSteal(exc));
next_instr = _PyCode_CODE(_PyFrame_GetCode(frame)) + handler;
if (monitor_handled(tstate, frame, next_instr, exc) < 0) {
@@ -1217,7 +1246,7 @@ format_missing(PyThreadState *tstate, const char *kind,
static void
missing_arguments(PyThreadState *tstate, PyCodeObject *co,
Py_ssize_t missing, Py_ssize_t defcount,
- PyObject **localsplus, PyObject *qualname)
+ _PyStackRef *localsplus, PyObject *qualname)
{
Py_ssize_t i, j = 0;
Py_ssize_t start, end;
@@ -1238,7 +1267,7 @@ missing_arguments(PyThreadState *tstate, PyCodeObject *co,
end = start + co->co_kwonlyargcount;
}
for (i = start; i < end; i++) {
- if (localsplus[i] == NULL) {
+ if (PyStackRef_IsNull(localsplus[i])) {
PyObject *raw = PyTuple_GET_ITEM(co->co_localsplusnames, i);
PyObject *name = PyObject_Repr(raw);
if (name == NULL) {
@@ -1256,7 +1285,7 @@ missing_arguments(PyThreadState *tstate, PyCodeObject *co,
static void
too_many_positional(PyThreadState *tstate, PyCodeObject *co,
Py_ssize_t given, PyObject *defaults,
- PyObject **localsplus, PyObject *qualname)
+ _PyStackRef *localsplus, PyObject *qualname)
{
int plural;
Py_ssize_t kwonly_given = 0;
@@ -1267,7 +1296,7 @@ too_many_positional(PyThreadState *tstate, PyCodeObject *co,
assert((co->co_flags & CO_VARARGS) == 0);
/* Count missing keyword-only args. */
for (i = co_argcount; i < co_argcount + co->co_kwonlyargcount; i++) {
- if (localsplus[i] != NULL) {
+ if (PyStackRef_AsPyObjectBorrow(localsplus[i]) != NULL) {
kwonly_given++;
}
}
@@ -1445,7 +1474,7 @@ get_exception_handler(PyCodeObject *code, int index, int *level, int *handler, i
static int
initialize_locals(PyThreadState *tstate, PyFunctionObject *func,
- PyObject **localsplus, PyObject *const *args,
+ _PyStackRef *localsplus, _PyStackRef const *args,
Py_ssize_t argcount, PyObject *kwnames)
{
PyCodeObject *co = (PyCodeObject*)func->func_code;
@@ -1463,8 +1492,8 @@ initialize_locals(PyThreadState *tstate, PyFunctionObject *func,
if (co->co_flags & CO_VARARGS) {
i++;
}
- assert(localsplus[i] == NULL);
- localsplus[i] = kwdict;
+ assert(PyStackRef_IsNull(localsplus[i]));
+ localsplus[i] = PyStackRef_FromPyObjectSteal(kwdict);
}
else {
kwdict = NULL;
@@ -1479,9 +1508,8 @@ initialize_locals(PyThreadState *tstate, PyFunctionObject *func,
n = argcount;
}
for (j = 0; j < n; j++) {
- PyObject *x = args[j];
- assert(localsplus[j] == NULL);
- localsplus[j] = x;
+ assert(PyStackRef_IsNull(localsplus[j]));
+ localsplus[j] = args[j];
}
/* Pack other positional arguments into the *args argument */
@@ -1492,18 +1520,23 @@ initialize_locals(PyThreadState *tstate, PyFunctionObject *func,
}
else {
assert(args != NULL);
- u = _PyTuple_FromArraySteal(args + n, argcount - n);
+ STACKREFS_TO_PYOBJECTS((_PyStackRef *)args, argcount, args_o);
+ if (args_o == NULL) {
+ goto fail_pre_positional;
+ }
+ u = _PyTuple_FromArraySteal((args_o + n), argcount - n);
+ STACKREFS_TO_PYOBJECTS_CLEANUP(args_o);
}
if (u == NULL) {
goto fail_post_positional;
}
- assert(localsplus[total_args] == NULL);
- localsplus[total_args] = u;
+ assert(PyStackRef_AsPyObjectBorrow(localsplus[total_args]) == NULL);
+ localsplus[total_args] = PyStackRef_FromPyObjectSteal(u);
}
else if (argcount > n) {
/* Too many positional args. Error is reported later */
for (j = n; j < argcount; j++) {
- Py_DECREF(args[j]);
+ PyStackRef_CLOSE(args[j]);
}
}
@@ -1513,7 +1546,7 @@ initialize_locals(PyThreadState *tstate, PyFunctionObject *func,
for (i = 0; i < kwcount; i++) {
PyObject **co_varnames;
PyObject *keyword = PyTuple_GET_ITEM(kwnames, i);
- PyObject *value = args[i+argcount];
+ _PyStackRef value_stackref = args[i+argcount];
Py_ssize_t j;
if (keyword == NULL || !PyUnicode_Check(keyword)) {
@@ -1586,27 +1619,26 @@ initialize_locals(PyThreadState *tstate, PyFunctionObject *func,
goto kw_fail;
}
- if (PyDict_SetItem(kwdict, keyword, value) == -1) {
+ if (PyDict_SetItem(kwdict, keyword, PyStackRef_AsPyObjectSteal(value_stackref)) == -1) {
goto kw_fail;
}
- Py_DECREF(value);
+ PyStackRef_CLOSE(value_stackref);
continue;
kw_fail:
for (;i < kwcount; i++) {
- PyObject *value = args[i+argcount];
- Py_DECREF(value);
+ PyStackRef_CLOSE(args[i+argcount]);
}
goto fail_post_args;
kw_found:
- if (localsplus[j] != NULL) {
+ if (PyStackRef_AsPyObjectBorrow(localsplus[j]) != NULL) {
_PyErr_Format(tstate, PyExc_TypeError,
"%U() got multiple values for argument '%S'",
func->func_qualname, keyword);
goto kw_fail;
}
- localsplus[j] = value;
+ localsplus[j] = value_stackref;
}
}
@@ -1623,7 +1655,7 @@ initialize_locals(PyThreadState *tstate, PyFunctionObject *func,
Py_ssize_t m = co->co_argcount - defcount;
Py_ssize_t missing = 0;
for (i = argcount; i < m; i++) {
- if (localsplus[i] == NULL) {
+ if (PyStackRef_IsNull(localsplus[i])) {
missing++;
}
}
@@ -1639,9 +1671,9 @@ initialize_locals(PyThreadState *tstate, PyFunctionObject *func,
if (defcount) {
PyObject **defs = &PyTuple_GET_ITEM(func->func_defaults, 0);
for (; i < defcount; i++) {
- if (localsplus[m+i] == NULL) {
+ if (PyStackRef_AsPyObjectBorrow(localsplus[m+i]) == NULL) {
PyObject *def = defs[i];
- localsplus[m+i] = Py_NewRef(def);
+ localsplus[m+i] = PyStackRef_FromPyObjectNew(def);
}
}
}
@@ -1651,7 +1683,7 @@ initialize_locals(PyThreadState *tstate, PyFunctionObject *func,
if (co->co_kwonlyargcount > 0) {
Py_ssize_t missing = 0;
for (i = co->co_argcount; i < total_args; i++) {
- if (localsplus[i] != NULL)
+ if (PyStackRef_AsPyObjectBorrow(localsplus[i]) != NULL)
continue;
PyObject *varname = PyTuple_GET_ITEM(co->co_localsplusnames, i);
if (func->func_kwdefaults != NULL) {
@@ -1660,7 +1692,7 @@ initialize_locals(PyThreadState *tstate, PyFunctionObject *func,
goto fail_post_args;
}
if (def) {
- localsplus[i] = def;
+ localsplus[i] = PyStackRef_FromPyObjectSteal(def);
continue;
}
}
@@ -1676,14 +1708,14 @@ initialize_locals(PyThreadState *tstate, PyFunctionObject *func,
fail_pre_positional:
for (j = 0; j < argcount; j++) {
- Py_DECREF(args[j]);
+ PyStackRef_CLOSE(args[j]);
}
/* fall through */
fail_post_positional:
if (kwnames) {
Py_ssize_t kwcount = PyTuple_GET_SIZE(kwnames);
for (j = argcount; j < argcount+kwcount; j++) {
- Py_DECREF(args[j]);
+ PyStackRef_CLOSE(args[j]);
}
}
/* fall through */
@@ -1738,7 +1770,7 @@ _PyEval_FrameClearAndPop(PyThreadState *tstate, _PyInterpreterFrame * frame)
/* Consumes references to func, locals and all the args */
_PyInterpreterFrame *
_PyEvalFramePushAndInit(PyThreadState *tstate, PyFunctionObject *func,
- PyObject *locals, PyObject* const* args,
+ PyObject *locals, _PyStackRef const* args,
size_t argcount, PyObject *kwnames)
{
PyCodeObject * code = (PyCodeObject *)func->func_code;
@@ -1759,18 +1791,45 @@ fail:
Py_DECREF(func);
Py_XDECREF(locals);
for (size_t i = 0; i < argcount; i++) {
- Py_DECREF(args[i]);
+ PyStackRef_CLOSE(args[i]);
}
if (kwnames) {
Py_ssize_t kwcount = PyTuple_GET_SIZE(kwnames);
for (Py_ssize_t i = 0; i < kwcount; i++) {
- Py_DECREF(args[i+argcount]);
+ PyStackRef_CLOSE(args[i+argcount]);
}
}
PyErr_NoMemory();
return NULL;
}
+static _PyInterpreterFrame *
+_PyEvalFramePushAndInit_UnTagged(PyThreadState *tstate, PyFunctionObject *func,
+ PyObject *locals, PyObject *const* args,
+ size_t argcount, PyObject *kwnames)
+{
+#if defined(Py_GIL_DISABLED)
+ size_t kw_count = kwnames == NULL ? 0 : PyTuple_GET_SIZE(kwnames);
+ size_t total_argcount = argcount + kw_count;
+ _PyStackRef *tagged_args_buffer = PyMem_Malloc(sizeof(_PyStackRef) * total_argcount);
+ if (tagged_args_buffer == NULL) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+ for (size_t i = 0; i < argcount; i++) {
+ tagged_args_buffer[i] = PyStackRef_FromPyObjectSteal(args[i]);
+ }
+ for (size_t i = 0; i < kw_count; i++) {
+ tagged_args_buffer[argcount + i] = PyStackRef_FromPyObjectSteal(args[argcount + i]);
+ }
+ _PyInterpreterFrame *res = _PyEvalFramePushAndInit(tstate, func, locals, (_PyStackRef const *)tagged_args_buffer, argcount, kwnames);
+ PyMem_Free(tagged_args_buffer);
+ return res;
+#else
+ return _PyEvalFramePushAndInit(tstate, func, locals, (_PyStackRef const *)args, argcount, kwnames);
+#endif
+}
+
/* Same as _PyEvalFramePushAndInit but takes an args tuple and kwargs dict.
Steals references to func, callargs and kwargs.
*/
@@ -1795,7 +1854,7 @@ _PyEvalFramePushAndInit_Ex(PyThreadState *tstate, PyFunctionObject *func,
Py_INCREF(PyTuple_GET_ITEM(callargs, i));
}
}
- _PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit(
+ _PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit_UnTagged(
tstate, (PyFunctionObject *)func, locals,
newargs, nargs, kwnames
);
@@ -1833,7 +1892,7 @@ _PyEval_Vector(PyThreadState *tstate, PyFunctionObject *func,
Py_INCREF(args[i+argcount]);
}
}
- _PyInterpreterFrame *frame = _PyEvalFramePushAndInit(
+ _PyInterpreterFrame *frame = _PyEvalFramePushAndInit_UnTagged(
tstate, func, locals, args, argcount, kwnames);
if (frame == NULL) {
return NULL;
@@ -2085,8 +2144,8 @@ _PyEval_ExceptionGroupMatch(PyObject* exc_value, PyObject *match_type,
*/
int
-_PyEval_UnpackIterable(PyThreadState *tstate, PyObject *v,
- int argcnt, int argcntafter, PyObject **sp)
+_PyEval_UnpackIterableStackRef(PyThreadState *tstate, _PyStackRef v_stackref,
+ int argcnt, int argcntafter, _PyStackRef *sp)
{
int i = 0, j = 0;
Py_ssize_t ll = 0;
@@ -2094,6 +2153,7 @@ _PyEval_UnpackIterable(PyThreadState *tstate, PyObject *v,
PyObject *w;
PyObject *l = NULL; /* variable list */
+ PyObject *v = PyStackRef_AsPyObjectBorrow(v_stackref);
assert(v != NULL);
it = PyObject_GetIter(v);
@@ -2128,7 +2188,7 @@ _PyEval_UnpackIterable(PyThreadState *tstate, PyObject *v,
}
goto Error;
}
- *--sp = w;
+ *--sp = PyStackRef_FromPyObjectSteal(w);
}
if (argcntafter == -1) {
@@ -2150,7 +2210,7 @@ _PyEval_UnpackIterable(PyThreadState *tstate, PyObject *v,
l = PySequence_List(it);
if (l == NULL)
goto Error;
- *--sp = l;
+ *--sp = PyStackRef_FromPyObjectSteal(l);
i++;
ll = PyList_GET_SIZE(l);
@@ -2163,7 +2223,7 @@ _PyEval_UnpackIterable(PyThreadState *tstate, PyObject *v,
/* Pop the "after-variable" args off the list. */
for (j = argcntafter; j > 0; j--, i++) {
- *--sp = PyList_GET_ITEM(l, ll - j);
+ *--sp = PyStackRef_FromPyObjectSteal(PyList_GET_ITEM(l, ll - j));
}
/* Resize the list. */
Py_SET_SIZE(l, ll - argcntafter);
@@ -2171,8 +2231,9 @@ _PyEval_UnpackIterable(PyThreadState *tstate, PyObject *v,
return 1;
Error:
- for (; i > 0; i--, sp++)
- Py_DECREF(*sp);
+ for (; i > 0; i--, sp++) {
+ PyStackRef_CLOSE(*sp);
+ }
Py_XDECREF(it);
return 0;
}