mirror of
https://github.com/python/cpython.git
synced 2025-08-04 08:59:19 +00:00
GH-127705: Add debug mode for _PyStackRef
s inspired by HPy debug mode (GH-128121)
This commit is contained in:
parent
78ffba4221
commit
128cc47fbd
12 changed files with 395 additions and 33 deletions
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue