Skip to content

Commit e615d9f

Browse files
MakeHeapSafe rework, _Py_stackref_set_borrowed_from added (NOP)
1 parent d74a963 commit e615d9f

File tree

2 files changed

+24
-4
lines changed

2 files changed

+24
-4
lines changed

Include/internal/pycore_stackref.h

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ PyAPI_FUNC(PyObject *) _Py_stackref_get_object(_PyStackRef ref);
6363
PyAPI_FUNC(PyObject *) _Py_stackref_close(_PyStackRef ref, const char *filename, int linenumber);
6464
PyAPI_FUNC(_PyStackRef) _Py_stackref_create(PyObject *obj, uint16_t flags, const char *filename, int linenumber);
6565
PyAPI_FUNC(void) _Py_stackref_record_borrow(_PyStackRef ref, const char *filename, int linenumber);
66+
PyAPI_FUNC(void) _Py_stackref_set_borrowed_from(_PyStackRef ref, _PyStackRef borrowed_from, const char *filename, int linenumber);
6667
extern void _Py_stackref_associate(PyInterpreterState *interp, PyObject *obj, _PyStackRef ref);
6768

6869
static const _PyStackRef PyStackRef_NULL = { .index = 0 };
@@ -259,6 +260,7 @@ _PyStackRef_CLOSE_SPECIALIZED(_PyStackRef ref, destructor destruct, const char *
259260
assert(!PyStackRef_IsNull(ref));
260261
assert(!PyStackRef_IsTaggedInt(ref));
261262
PyObject *obj = _Py_stackref_close(ref, filename, linenumber);
263+
assert(Py_REFCNT(obj) > 0);
262264
if (PyStackRef_RefcountOnObject(ref)) {
263265
_Py_DECREF_SPECIALIZED(obj, destruct);
264266
}
@@ -274,7 +276,11 @@ _PyStackRef_Borrow(_PyStackRef ref, const char *filename, int linenumber)
274276
return ref;
275277
}
276278
PyObject *obj = _Py_stackref_get_object(ref);
277-
return _Py_stackref_create(obj, Py_TAG_REFCNT, filename, linenumber);
279+
_PyStackRef new_ref = _Py_stackref_create(obj, Py_TAG_REFCNT, filename, linenumber);
280+
if (!_Py_IsImmortal(obj)) {
281+
_Py_stackref_set_borrowed_from(new_ref, ref, filename, linenumber);
282+
}
283+
return new_ref;
278284
}
279285
#define PyStackRef_Borrow(REF) _PyStackRef_Borrow((REF), __FILE__, __LINE__)
280286

@@ -310,13 +316,22 @@ PyStackRef_IsHeapSafe(_PyStackRef ref)
310316
static inline _PyStackRef
311317
_PyStackRef_MakeHeapSafe(_PyStackRef ref, const char *filename, int linenumber)
312318
{
313-
if (PyStackRef_IsHeapSafe(ref)) {
319+
// Special references that can't be closed.
320+
if (ref.index < INITIAL_STACKREF_INDEX) {
314321
return ref;
315322
}
316323

324+
bool heap_safe = PyStackRef_IsHeapSafe(ref);
317325
PyObject *obj = _Py_stackref_close(ref, filename, linenumber);
318-
Py_INCREF(obj);
319-
return _Py_stackref_create(obj, 0, filename, linenumber);
326+
uint16_t flags = 0;
327+
if (heap_safe) {
328+
// Close old ref and create a new one with the same flags.
329+
// This is necessary for correct borrow checking.
330+
flags = ref.index & Py_TAG_BITS;
331+
} else {
332+
Py_INCREF(obj);
333+
}
334+
return _Py_stackref_create(obj, flags, filename, linenumber);
320335
}
321336
#define PyStackRef_MakeHeapSafe(REF) _PyStackRef_MakeHeapSafe(REF, __FILE__, __LINE__)
322337

Python/stackrefs.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,11 @@ _Py_stackref_record_borrow(_PyStackRef ref, const char *filename, int linenumber
152152
entry->linenumber_borrow = linenumber;
153153
}
154154

155+
void
156+
_Py_stackref_set_borrowed_from(_PyStackRef ref, _PyStackRef borrowed_from, const char *filename, int linenumber)
157+
{
158+
assert(!PyStackRef_IsError(ref));
159+
}
155160

156161
void
157162
_Py_stackref_associate(PyInterpreterState *interp, PyObject *obj, _PyStackRef ref)

0 commit comments

Comments
 (0)