summaryrefslogtreecommitdiffstats
path: root/Python/ceval.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/ceval.c')
-rw-r--r--Python/ceval.c67
1 files changed, 53 insertions, 14 deletions
diff --git a/Python/ceval.c b/Python/ceval.c
index bfdf568..3cf11b6 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -164,7 +164,7 @@ dump_stack(_PyInterpreterFrame *frame, _PyStackRef *stack_pointer)
PyErr_Clear();
}
// Don't call __repr__(), it might recurse into the interpreter.
- printf("<%s at %p>", Py_TYPE(obj)->tp_name, (void *)(ptr->bits));
+ printf("<%s at %p>", Py_TYPE(obj)->tp_name, PyStackRef_AsPyObjectBorrow(*ptr));
}
printf("]\n");
fflush(stdout);
@@ -805,7 +805,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
-#ifdef Py_DEBUG
+#if defined(Py_DEBUG) && !defined(Py_STACKREF_DEBUG)
/* Set these to invalid but identifiable values for debugging. */
entry_frame.f_funcobj = (_PyStackRef){.bits = 0xaaa0};
entry_frame.f_locals = (PyObject*)0xaaa1;
@@ -1810,27 +1810,48 @@ _PyEvalFramePushAndInit_Ex(PyThreadState *tstate, _PyStackRef func,
{
bool has_dict = (kwargs != NULL && PyDict_GET_SIZE(kwargs) > 0);
PyObject *kwnames = NULL;
- PyObject *const *newargs;
+ _PyStackRef *newargs;
+ PyObject *const *object_array = NULL;
+ _PyStackRef stack_array[8];
if (has_dict) {
- newargs = _PyStack_UnpackDict(tstate, _PyTuple_ITEMS(callargs), nargs, kwargs, &kwnames);
- if (newargs == NULL) {
+ object_array = _PyStack_UnpackDict(tstate, _PyTuple_ITEMS(callargs), nargs, kwargs, &kwnames);
+ if (object_array == NULL) {
PyStackRef_CLOSE(func);
goto error;
}
+ size_t total_args = nargs + PyDict_GET_SIZE(kwargs);
+ assert(sizeof(PyObject *) == sizeof(_PyStackRef));
+ newargs = (_PyStackRef *)object_array;
+ for (size_t i = 0; i < total_args; i++) {
+ newargs[i] = PyStackRef_FromPyObjectSteal(object_array[i]);
+ }
}
else {
- newargs = &PyTuple_GET_ITEM(callargs, 0);
- /* We need to incref all our args since the new frame steals the references. */
- for (Py_ssize_t i = 0; i < nargs; ++i) {
- Py_INCREF(PyTuple_GET_ITEM(callargs, i));
+ if (nargs <= 8) {
+ newargs = stack_array;
+ }
+ else {
+ newargs = PyMem_Malloc(sizeof(_PyStackRef) *nargs);
+ if (newargs == NULL) {
+ PyErr_NoMemory();
+ PyStackRef_CLOSE(func);
+ goto error;
+ }
+ }
+ /* We need to create a new reference for all our args since the new frame steals them. */
+ for (Py_ssize_t i = 0; i < nargs; i++) {
+ newargs[i] = PyStackRef_FromPyObjectNew(PyTuple_GET_ITEM(callargs, i));
}
}
_PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit(
tstate, func, locals,
- (_PyStackRef const *)newargs, nargs, kwnames, previous
+ newargs, nargs, kwnames, previous
);
if (has_dict) {
- _PyStack_UnpackDict_FreeNoDecRef(newargs, kwnames);
+ _PyStack_UnpackDict_FreeNoDecRef(object_array, kwnames);
+ }
+ else if (nargs > 8) {
+ PyMem_Free((void *)newargs);
}
/* No need to decref func here because the reference has been stolen by
_PyEvalFramePushAndInit.
@@ -1850,21 +1871,39 @@ _PyEval_Vector(PyThreadState *tstate, PyFunctionObject *func,
PyObject* const* args, size_t argcount,
PyObject *kwnames)
{
+ size_t total_args = argcount;
+ if (kwnames) {
+ total_args += PyTuple_GET_SIZE(kwnames);
+ }
+ _PyStackRef stack_array[8];
+ _PyStackRef *arguments;
+ if (total_args <= 8) {
+ arguments = stack_array;
+ }
+ else {
+ arguments = PyMem_Malloc(sizeof(_PyStackRef) * total_args);
+ if (arguments == NULL) {
+ return PyErr_NoMemory();
+ }
+ }
/* _PyEvalFramePushAndInit consumes the references
* to func, locals and all its arguments */
Py_XINCREF(locals);
for (size_t i = 0; i < argcount; i++) {
- Py_INCREF(args[i]);
+ arguments[i] = PyStackRef_FromPyObjectNew(args[i]);
}
if (kwnames) {
Py_ssize_t kwcount = PyTuple_GET_SIZE(kwnames);
for (Py_ssize_t i = 0; i < kwcount; i++) {
- Py_INCREF(args[i+argcount]);
+ arguments[i+argcount] = PyStackRef_FromPyObjectNew(args[i+argcount]);
}
}
_PyInterpreterFrame *frame = _PyEvalFramePushAndInit(
tstate, PyStackRef_FromPyObjectNew(func), locals,
- (_PyStackRef const *)args, argcount, kwnames, NULL);
+ arguments, argcount, kwnames, NULL);
+ if (total_args > 8) {
+ PyMem_Free(arguments);
+ }
if (frame == NULL) {
return NULL;
}