Skip to content

Commit b7a8b5d

Browse files
committed
Restore immortality bit
1 parent 3334c14 commit b7a8b5d

File tree

2 files changed

+46
-41
lines changed

2 files changed

+46
-41
lines changed

Include/internal/pycore_frame.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -142,11 +142,11 @@ _PyFrame_NumSlotsForCodeObject(PyCodeObject *code)
142142

143143
static inline void _PyFrame_Copy(_PyInterpreterFrame *src, _PyInterpreterFrame *dest)
144144
{
145-
dest->f_executable = PyStackRef_HeapSafe(src->f_executable);
145+
dest->f_executable = PyStackRef_MakeHeapSafe(src->f_executable);
146146
// Don't leave a dangling pointer to the old frame when creating generators
147147
// and coroutines:
148148
dest->previous = NULL;
149-
dest->f_funcobj = PyStackRef_HeapSafe(src->f_funcobj);
149+
dest->f_funcobj = PyStackRef_MakeHeapSafe(src->f_funcobj);
150150
dest->f_globals = src->f_globals;
151151
dest->f_builtins = src->f_builtins;
152152
dest->f_locals = src->f_locals;
@@ -157,7 +157,7 @@ static inline void _PyFrame_Copy(_PyInterpreterFrame *src, _PyInterpreterFrame *
157157
assert(stacktop >= 0);
158158
dest->stackpointer = dest->localsplus + stacktop;
159159
for (int i = 0; i < stacktop; i++) {
160-
dest->localsplus[i] = PyStackRef_HeapSafe(src->localsplus[i]);
160+
dest->localsplus[i] = PyStackRef_MakeHeapSafe(src->localsplus[i]);
161161
PyStackRef_CheckValid(dest->localsplus[i]);
162162
}
163163

Include/internal/pycore_stackref.h

Lines changed: 43 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ PyStackRef_IsHeapSafe(_PyStackRef ref)
165165
}
166166

167167
static inline _PyStackRef
168-
PyStackRef_HeapSafe(_PyStackRef ref)
168+
PyStackRef_MakeHeapSafe(_PyStackRef ref)
169169
{
170170
return ref;
171171
}
@@ -200,58 +200,73 @@ PyStackRef_AsStrongReference(_PyStackRef stackref)
200200
// With GIL
201201

202202
#define Py_TAG_BITS 3
203-
#define Py_NULL_BIT 2
203+
#define Py_TAG_IMMORTAL 3
204204
#define Py_TAG_REFCNT 1
205205
#define BITS_TO_PTR(REF) ((PyObject *)((REF).bits))
206206
#define BITS_TO_PTR_MASKED(REF) ((PyObject *)(((REF).bits) & (~Py_TAG_BITS)))
207207

208-
#define PyStackRef_NULL_BITS (Py_TAG_REFCNT | Py_NULL_BIT)
208+
#define PyStackRef_NULL_BITS Py_TAG_IMMORTAL
209209
static const _PyStackRef PyStackRef_NULL = { .bits = PyStackRef_NULL_BITS };
210210

211211
#define PyStackRef_IsNull(ref) ((ref).bits == PyStackRef_NULL_BITS)
212-
#define PyStackRef_True ((_PyStackRef){.bits = ((uintptr_t)&_Py_TrueStruct) | Py_TAG_REFCNT })
213-
#define PyStackRef_False ((_PyStackRef){.bits = ((uintptr_t)&_Py_FalseStruct) | Py_TAG_REFCNT })
214-
#define PyStackRef_None ((_PyStackRef){.bits = ((uintptr_t)&_Py_NoneStruct) | Py_TAG_REFCNT })
212+
#define PyStackRef_True ((_PyStackRef){.bits = ((uintptr_t)&_Py_TrueStruct) | Py_TAG_IMMORTAL })
213+
#define PyStackRef_False ((_PyStackRef){.bits = ((uintptr_t)&_Py_FalseStruct) | Py_TAG_IMMORTAL })
214+
#define PyStackRef_None ((_PyStackRef){.bits = ((uintptr_t)&_Py_NoneStruct) | Py_TAG_IMMORTAL })
215215

216-
// #define PyStackRef_IsTrue(ref) ((ref).bits == (((uintptr_t)&_Py_TrueStruct) | Py_TAG_REFCNT))
217-
// #define PyStackRef_IsFalse(ref) ((ref).bits == (((uintptr_t)&_Py_FalseStruct) | Py_TAG_REFCNT))
218-
// #define PyStackRef_IsNone(ref) ((ref).bits == (((uintptr_t)&_Py_NoneStruct) | Py_TAG_REFCNT))
216+
// #define PyStackRef_IsTrue(ref) ((ref).bits == (((uintptr_t)&_Py_TrueStruct) | Py_TAG_IMMORTAL))
217+
// #define PyStackRef_IsFalse(ref) ((ref).bits == (((uintptr_t)&_Py_FalseStruct) | Py_TAG_IMMORTAL))
218+
// #define
219219

220220
/* We should be able to guarantee that the tag bits are set for immortal objects */
221221

222222
#define PyStackRef_IsTrue(ref) (((ref).bits & (~Py_TAG_BITS)) == ((uintptr_t)&_Py_TrueStruct))
223223
#define PyStackRef_IsFalse(ref) (((ref).bits & (~Py_TAG_BITS)) == ((uintptr_t)&_Py_FalseStruct))
224-
// #define PyStackRef_IsNone(ref) (((ref).bits & (~Py_TAG_BITS)) == ((uintptr_t)&_Py_NoneStruct))
225224

226225

227226
static inline void PyStackRef_CheckValid(_PyStackRef ref) {
228227
int tag = ref.bits & Py_TAG_BITS;
229-
if (tag == PyStackRef_NULL_BITS) {
230-
assert(ref.bits == PyStackRef_NULL_BITS);
231-
}
232-
else if (tag == 0) {
233-
assert(!_Py_IsImmortal(BITS_TO_PTR_MASKED(ref)));
228+
PyObject *obj = BITS_TO_PTR_MASKED(ref);
229+
switch (tag) {
230+
case 0:
231+
assert(!_Py_IsImmortal(obj));
232+
break;
233+
case Py_TAG_REFCNT:
234+
/* Can be immortal if object was made immortal after reference came into existence */
235+
assert(obj != NULL && obj != Py_True && obj != Py_False && obj != Py_None);
236+
break;
237+
case Py_TAG_IMMORTAL:
238+
assert(obj == NULL || _Py_IsImmortal(obj));
239+
break;
240+
default:
241+
assert(0);
234242
}
235243
}
236244

245+
#ifdef Py_DEBUG
237246
static inline int
238247
PyStackRef_IsNone(_PyStackRef ref)
239248
{
240249
if ((ref.bits & (~Py_TAG_BITS)) == ((uintptr_t)&_Py_NoneStruct)) {
241-
assert ((ref.bits & Py_TAG_BITS) == Py_TAG_REFCNT);
250+
assert ((ref.bits & Py_TAG_BITS) == Py_TAG_IMMORTAL);
242251
return 1;
243252
}
244253
return 0;
245254
}
246255

256+
#else
257+
258+
#define PyStackRef_IsNone(REF) ((REF).bits == (((uintptr_t)&_Py_NoneStruct) | Py_TAG_IMMORTAL))
259+
260+
#endif
261+
247262
static inline int
248263
PyStackRef_HasCount(_PyStackRef ref)
249264
{
250265
return ref.bits & Py_TAG_REFCNT;
251266
}
252267

253-
static inline int
254-
PyStackRef_HasCountAndNotNull(_PyStackRef ref)
268+
static inline bool
269+
PyStackRef_HasCountAndMortal(_PyStackRef ref)
255270
{
256271
return (ref.bits & Py_TAG_BITS) == Py_TAG_REFCNT;
257272
}
@@ -280,7 +295,7 @@ static inline _PyStackRef
280295
PyStackRef_FromPyObjectSteal(PyObject *obj)
281296
{
282297
assert(obj != NULL);
283-
unsigned int tag = _Py_IsImmortal(obj) ? Py_TAG_REFCNT : 0;
298+
unsigned int tag = _Py_IsImmortal(obj) ? Py_TAG_IMMORTAL : 0;
284299
_PyStackRef ref = ((_PyStackRef){.bits = ((uintptr_t)(obj)) | tag});
285300
PyStackRef_CheckValid(ref);
286301
return ref;
@@ -295,8 +310,8 @@ PyStackRef_FromPyObjectSteal(PyObject *obj)
295310
static inline _PyStackRef
296311
_PyStackRef_FromPyObjectNew(PyObject *obj)
297312
{
298-
if (_Py_IsDeferrable(obj)) {
299-
return (_PyStackRef){ .bits = ((uintptr_t)obj) | Py_TAG_REFCNT};
313+
if (_Py_IsImmortal(obj)) {
314+
return (_PyStackRef){ .bits = ((uintptr_t)obj) | Py_TAG_IMMORTAL};
300315
}
301316
Py_INCREF_MORTAL(obj);
302317
_PyStackRef ref = (_PyStackRef){ .bits = (uintptr_t)obj };
@@ -307,14 +322,11 @@ _PyStackRef_FromPyObjectNew(PyObject *obj)
307322

308323
/* Create a new reference from an object with an embedded reference count */
309324
static inline _PyStackRef
310-
_PyStackRef_FromPyObjectWithCount(PyObject *obj)
325+
PyStackRef_FromPyObjectImmortal(PyObject *obj)
311326
{
312-
return (_PyStackRef){ .bits = (uintptr_t)obj | Py_TAG_REFCNT};
327+
assert(_Py_IsImmortal(obj));
328+
return (_PyStackRef){ .bits = (uintptr_t)obj | Py_TAG_IMMORTAL};
313329
}
314-
#define PyStackRef_FromPyObjectWithCount(obj) _PyStackRef_FromPyObjectWithCount(_PyObject_CAST(obj))
315-
316-
#define PyStackRef_FromPyObjectImmortal PyStackRef_FromPyObjectWithCount
317-
318330

319331
static inline _PyStackRef
320332
PyStackRef_DUP(_PyStackRef ref)
@@ -326,26 +338,19 @@ PyStackRef_DUP(_PyStackRef ref)
326338
return ref;
327339
}
328340

329-
static inline int
341+
static inline bool
330342
PyStackRef_IsHeapSafe(_PyStackRef ref)
331343
{
332-
return (
333-
PyStackRef_IsNull(ref) ||
334-
!PyStackRef_HasCount(ref) ||
335-
_Py_IsImmortal(PyStackRef_AsPyObjectBorrow(ref))
336-
);
344+
return !PyStackRef_HasCountAndMortal(ref);
337345
}
338346

339347
static inline _PyStackRef
340-
PyStackRef_HeapSafe(_PyStackRef ref)
348+
PyStackRef_MakeHeapSafe(_PyStackRef ref)
341349
{
342-
if (!PyStackRef_HasCountAndNotNull(ref)) {
350+
if (!PyStackRef_HasCountAndMortal(ref)) {
343351
return ref;
344352
}
345353
PyObject *obj = BITS_TO_PTR_MASKED(ref);
346-
if (_Py_IsImmortal(obj)) {
347-
return ref;
348-
}
349354
Py_INCREF_MORTAL(obj);
350355
ref.bits = (uintptr_t)obj;
351356
PyStackRef_CheckValid(ref);

0 commit comments

Comments
 (0)