Skip to content

Commit 1d223c3

Browse files
committed
Add support for Py_STACKREF_DEBUG
1 parent ba30e9a commit 1d223c3

File tree

4 files changed

+61
-15
lines changed

4 files changed

+61
-15
lines changed

Include/internal/pycore_stackref.h

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,11 @@ extern void _Py_stackref_associate(PyInterpreterState *interp, PyObject *obj, _P
6363

6464
static const _PyStackRef PyStackRef_NULL = { .index = 0 };
6565

66-
#define PyStackRef_None ((_PyStackRef){ .index = 1 } )
67-
#define PyStackRef_False ((_PyStackRef){ .index = 2 })
68-
#define PyStackRef_True ((_PyStackRef){ .index = 3 })
66+
#define PyStackRef_None ((_PyStackRef){ .index = 2 } )
67+
#define PyStackRef_False ((_PyStackRef){ .index = 4 })
68+
#define PyStackRef_True ((_PyStackRef){ .index = 6 })
6969

70-
#define LAST_PREDEFINED_STACKREF_INDEX 3
70+
#define LAST_PREDEFINED_STACKREF_INDEX 6
7171

7272
static inline int
7373
PyStackRef_IsNull(_PyStackRef ref)
@@ -96,6 +96,7 @@ PyStackRef_IsNone(_PyStackRef ref)
9696
static inline PyObject *
9797
_PyStackRef_AsPyObjectBorrow(_PyStackRef ref, const char *filename, int linenumber)
9898
{
99+
assert((ref.index & 1) == 0);
99100
_Py_stackref_record_borrow(ref, filename, linenumber);
100101
return _Py_stackref_get_object(ref);
101102
}
@@ -132,31 +133,45 @@ _PyStackRef_FromPyObjectImmortal(PyObject *obj, const char *filename, int linenu
132133
}
133134
#define PyStackRef_FromPyObjectImmortal(obj) _PyStackRef_FromPyObjectImmortal(_PyObject_CAST(obj), __FILE__, __LINE__)
134135

136+
static inline bool
137+
is_tagged_int(_PyStackRef ref)
138+
{
139+
return (ref.index & 1) == 1;
140+
}
141+
135142
static inline void
136143
_PyStackRef_CLOSE(_PyStackRef ref, const char *filename, int linenumber)
137144
{
145+
if (is_tagged_int(ref)) {
146+
return;
147+
}
138148
PyObject *obj = _Py_stackref_close(ref, filename, linenumber);
139149
Py_DECREF(obj);
140150
}
141151
#define PyStackRef_CLOSE(REF) _PyStackRef_CLOSE((REF), __FILE__, __LINE__)
142152

153+
143154
static inline void
144155
_PyStackRef_XCLOSE(_PyStackRef ref, const char *filename, int linenumber)
145156
{
146157
if (PyStackRef_IsNull(ref)) {
147158
return;
148159
}
149-
PyObject *obj = _Py_stackref_close(ref, filename, linenumber);
150-
Py_DECREF(obj);
160+
_PyStackRef_CLOSE(ref, filename, linenumber);
151161
}
152162
#define PyStackRef_XCLOSE(REF) _PyStackRef_XCLOSE((REF), __FILE__, __LINE__)
153163

154164
static inline _PyStackRef
155165
_PyStackRef_DUP(_PyStackRef ref, const char *filename, int linenumber)
156166
{
157-
PyObject *obj = _Py_stackref_get_object(ref);
158-
Py_INCREF(obj);
159-
return _Py_stackref_create(obj, filename, linenumber);
167+
if (ref.index & 1) {
168+
return ref;
169+
}
170+
else {
171+
PyObject *obj = _Py_stackref_get_object(ref);
172+
Py_INCREF(obj);
173+
return _Py_stackref_create(obj, filename, linenumber);
174+
}
160175
}
161176
#define PyStackRef_DUP(REF) _PyStackRef_DUP(REF, __FILE__, __LINE__)
162177

@@ -210,8 +225,15 @@ _PyStackRef_FromPyObjectNewMortal(PyObject *obj, const char *filename, int linen
210225

211226
extern int PyStackRef_Is(_PyStackRef a, _PyStackRef b);
212227

228+
extern bool PyStackRef_IsTaggedInt(_PyStackRef ref);
229+
230+
extern intptr_t PyStackRef_UntagInt(_PyStackRef ref);
231+
213232
extern _PyStackRef PyStackRef_TagInt(intptr_t i);
214233

234+
extern bool
235+
PyStackRef_IsNullOrInt(_PyStackRef ref);
236+
215237
#else
216238

217239
#define Py_INT_TAG 3

Python/gc_free_threading.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ frame_disable_deferred_refcounting(_PyInterpreterFrame *frame)
265265

266266
frame->f_funcobj = PyStackRef_AsStrongReference(frame->f_funcobj);
267267
for (_PyStackRef *ref = frame->localsplus; ref < frame->stackpointer; ref++) {
268-
if (!PyStackRef_IsNull(*ref) && PyStackRef_IsDeferred(*ref)) {
268+
if (!PyStackRef_IsNullOrInt(*ref) && PyStackRef_IsDeferred(*ref)) {
269269
*ref = PyStackRef_AsStrongReference(*ref);
270270
}
271271
}
@@ -420,7 +420,7 @@ gc_visit_heaps(PyInterpreterState *interp, mi_block_visit_fun *visitor,
420420
static inline void
421421
gc_visit_stackref(_PyStackRef stackref)
422422
{
423-
if (PyStackRef_IsDeferred(stackref) && !PyStackRef_IsNull(stackref)) {
423+
if (PyStackRef_IsDeferred(stackref) && !PyStackRef_IsNullOrInt(stackref)) {
424424
PyObject *obj = PyStackRef_AsPyObjectBorrow(stackref);
425425
if (_PyObject_GC_IS_TRACKED(obj) && !gc_is_frozen(obj)) {
426426
gc_add_refs(obj, 1);
@@ -817,7 +817,7 @@ gc_abort_mark_alive(PyInterpreterState *interp,
817817
static int
818818
gc_visit_stackref_mark_alive(gc_mark_args_t *args, _PyStackRef stackref)
819819
{
820-
if (!PyStackRef_IsNull(stackref)) {
820+
if (!PyStackRef_IsNullOrInt(stackref)) {
821821
PyObject *op = PyStackRef_AsPyObjectBorrow(stackref);
822822
if (gc_mark_enqueue(op, args) < 0) {
823823
return -1;

Python/pystate.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -673,7 +673,7 @@ init_interpreter(PyInterpreterState *interp,
673673
interp->dtoa = (struct _dtoa_state)_dtoa_state_INIT(interp);
674674
}
675675
#if !defined(Py_GIL_DISABLED) && defined(Py_STACKREF_DEBUG)
676-
interp->next_stackref = 1;
676+
interp->next_stackref = 2;
677677
_Py_hashtable_allocator_t alloc = {
678678
.malloc = malloc,
679679
.free = free,

Python/stackrefs.c

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,8 @@ _Py_stackref_create(PyObject *obj, const char *filename, int linenumber)
113113
Py_FatalError("Cannot create a stackref for NULL");
114114
}
115115
PyInterpreterState *interp = PyInterpreterState_Get();
116-
uint64_t new_id = interp->next_stackref++;
116+
uint64_t new_id = interp->next_stackref;
117+
interp->next_stackref = new_id + 2;
117118
TableEntry *entry = make_table_entry(obj, filename, linenumber);
118119
if (entry == NULL) {
119120
Py_FatalError("No memory left for stackref debug table");
@@ -152,7 +153,7 @@ void
152153
_Py_stackref_associate(PyInterpreterState *interp, PyObject *obj, _PyStackRef ref)
153154
{
154155
assert(interp->next_stackref >= ref.index);
155-
interp->next_stackref = ref.index+1;
156+
interp->next_stackref = ref.index+2;
156157
TableEntry *entry = make_table_entry(obj, "builtin-object", 0);
157158
if (entry == NULL) {
158159
Py_FatalError("No memory left for stackref debug table");
@@ -197,4 +198,27 @@ _PyStackRef_CLOSE_SPECIALIZED(_PyStackRef ref, destructor destruct, const char *
197198
_Py_DECREF_SPECIALIZED(obj, destruct);
198199
}
199200

201+
_PyStackRef PyStackRef_TagInt(intptr_t i)
202+
{
203+
return (_PyStackRef){ .index = (i << 1) + 1 };
204+
}
205+
206+
intptr_t
207+
PyStackRef_UntagInt(_PyStackRef i)
208+
{
209+
assert(is_tagged_int(i));
210+
return Py_ARITHMETIC_RIGHT_SHIFT(intptr_t, i.index, 1);
211+
}
212+
213+
bool PyStackRef_IsTaggedInt(_PyStackRef ref)
214+
{
215+
return is_tagged_int(ref);
216+
}
217+
218+
bool
219+
PyStackRef_IsNullOrInt(_PyStackRef ref)
220+
{
221+
return PyStackRef_IsNull(ref) || PyStackRef_IsTaggedInt(ref);
222+
}
223+
200224
#endif

0 commit comments

Comments
 (0)