Skip to content

Commit 2bc9ace

Browse files
committed
Get Py_STACKREF_DEBUG working again
1 parent d61e0bf commit 2bc9ace

File tree

3 files changed

+66
-14
lines changed

3 files changed

+66
-14
lines changed

Include/internal/pycore_stackref.h

+56-13
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ extern "C" {
55
#endif
66

77
// Define this to get precise tracking of stackrefs.
8-
// #define Py_STACKREF_DEBUG 1
8+
#define Py_STACKREF_DEBUG 1
99

1010
#ifndef Py_BUILD_CORE
1111
# error "this header requires Py_BUILD_CORE define"
@@ -144,6 +144,16 @@ PyStackRef_CLOSE(_PyStackRef ref)
144144
Py_DECREF(obj);
145145
}
146146

147+
static inline void
148+
PyStackRef_XCLOSE(_PyStackRef ref)
149+
{
150+
if (PyStackRef_IsNull(ref)) {
151+
return;
152+
}
153+
PyObject *obj = _Py_stackref_close(ref);
154+
Py_DECREF(obj);
155+
}
156+
147157
static inline _PyStackRef
148158
_PyStackRef_DUP(_PyStackRef ref, const char *filename, int linenumber)
149159
{
@@ -153,7 +163,47 @@ _PyStackRef_DUP(_PyStackRef ref, const char *filename, int linenumber)
153163
}
154164
#define PyStackRef_DUP(REF) _PyStackRef_DUP(REF, __FILE__, __LINE__)
155165

156-
#define PyStackRef_CLOSE_SPECIALIZED(stackref, dealloc) PyStackRef_CLOSE(stackref)
166+
extern void PyStackRef_CLOSE_SPECIALIZED(_PyStackRef ref, destructor destruct);
167+
168+
static inline _PyStackRef
169+
PyStackRef_MakeHeapSafe(_PyStackRef ref)
170+
{
171+
return ref;
172+
}
173+
174+
#define PyStackRef_CLEAR(REF) \
175+
do { \
176+
_PyStackRef *_tmp_op_ptr = &(REF); \
177+
_PyStackRef _tmp_old_op = (*_tmp_op_ptr); \
178+
*_tmp_op_ptr = PyStackRef_NULL; \
179+
PyStackRef_XCLOSE(_tmp_old_op); \
180+
} while (0)
181+
182+
183+
static inline _PyStackRef
184+
_PyStackRef_FromPyObjectStealMortal(PyObject *obj, const char *filename, int linenumber)
185+
{
186+
assert(!_Py_IsImmortal(obj));
187+
return _Py_stackref_create(obj, filename, linenumber);
188+
}
189+
#define PyStackRef_FromPyObjectStealMortal(obj) _PyStackRef_FromPyObjectStealMortal(_PyObject_CAST(obj), __FILE__, __LINE__)
190+
191+
static inline bool
192+
PyStackRef_IsMortal(_PyStackRef ref)
193+
{
194+
PyObject *obj = _Py_stackref_get_object(ref);
195+
if (obj == NULL) {
196+
return false;
197+
}
198+
return _Py_IsImmortal(obj);
199+
}
200+
201+
static inline int
202+
PyStackRef_IsHeapSafe(_PyStackRef ref)
203+
{
204+
return 1;
205+
}
206+
157207

158208
#else
159209

@@ -512,27 +562,20 @@ PyStackRef_XCLOSE(_PyStackRef ref)
512562
}
513563
}
514564

515-
#define PyStackRef_CLEAR(REF) \
516-
do { \
517-
_PyStackRef *_tmp_op_ptr = &(REF); \
518-
_PyStackRef _tmp_old_op = (*_tmp_op_ptr); \
519-
*_tmp_op_ptr = PyStackRef_NULL; \
520-
PyStackRef_XCLOSE(_tmp_old_op); \
521-
} while (0)
522565

523566
#endif // Py_GIL_DISABLED
524567

525568
// Note: this is a macro because MSVC (Windows) has trouble inlining it.
526569

527570
#define PyStackRef_Is(a, b) (((a).bits & (~Py_TAG_BITS)) == ((b).bits & (~Py_TAG_BITS)))
528571

529-
// Converts a PyStackRef back to a PyObject *, converting the
530-
// stackref to a new reference.
531-
#define PyStackRef_AsPyObjectNew(stackref) Py_NewRef(PyStackRef_AsPyObjectBorrow(stackref))
572+
#endif // !defined(Py_GIL_DISABLED) && defined(Py_STACKREF_DEBUG)
532573

533574
#define PyStackRef_TYPE(stackref) Py_TYPE(PyStackRef_AsPyObjectBorrow(stackref))
534575

535-
#endif // !defined(Py_GIL_DISABLED) && defined(Py_STACKREF_DEBUG)
576+
// Converts a PyStackRef back to a PyObject *, converting the
577+
// stackref to a new reference.
578+
#define PyStackRef_AsPyObjectNew(stackref) Py_NewRef(PyStackRef_AsPyObjectBorrow(stackref))
536579

537580
// StackRef type checks
538581

Python/ceval.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ dump_item(_PyStackRef item)
157157
PyErr_Clear();
158158
}
159159
// Don't call __repr__(), it might recurse into the interpreter.
160-
printf("<%s at %p>", Py_TYPE(obj)->tp_name, (void *)(item.bits));
160+
printf("<%s at %p>", Py_TYPE(obj)->tp_name, (void *)obj);
161161
}
162162

163163
static void

Python/stackrefs.c

+9
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11

22
#include "Python.h"
33

4+
#include "pycore_object.h"
45
#include "pycore_stackref.h"
56

67
#if !defined(Py_GIL_DISABLED) && defined(Py_STACKREF_DEBUG)
@@ -149,8 +150,16 @@ _Py_stackref_report_leaks(PyInterpreterState *interp)
149150
int leak = 0;
150151
_Py_hashtable_foreach(interp->stackref_debug_table, report_leak, &leak);
151152
if (leak) {
153+
fflush(stdout);
152154
Py_FatalError("Stackrefs leaked.");
153155
}
154156
}
155157

158+
void
159+
PyStackRef_CLOSE_SPECIALIZED(_PyStackRef ref, destructor destruct)
160+
{
161+
PyObject *obj = _Py_stackref_close(ref);
162+
_Py_DECREF_SPECIALIZED(obj, destruct);
163+
}
164+
156165
#endif

0 commit comments

Comments
 (0)