Skip to content

Commit 2cc17c7

Browse files
Do not check immortality at PyStackRef_FromPyObjectSteal
1 parent 5989095 commit 2cc17c7

File tree

2 files changed

+17
-39
lines changed

2 files changed

+17
-39
lines changed

Include/internal/pycore_stackref.h

Lines changed: 15 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ extern "C" {
88
# error "this header requires Py_BUILD_CORE define"
99
#endif
1010

11-
#include "pycore_object.h" // Py_DECREF_MORTAL
11+
#include "pycore_object.h" // _Py_DECREF_SPECIALIZED
1212
#include "pycore_object_deferred.h" // _PyObject_HasDeferredRefcount()
1313

1414
#include <stdbool.h> // bool
@@ -195,11 +195,7 @@ static inline _PyStackRef
195195
_PyStackRef_FromPyObjectSteal(PyObject *obj, const char *filename, int linenumber)
196196
{
197197
assert(obj != NULL);
198-
uint16_t flags = 0;
199-
if (_Py_IsImmortal(obj)) {
200-
flags = Py_TAG_REFCNT;
201-
}
202-
return _Py_stackref_create(obj, flags, filename, linenumber);
198+
return _Py_stackref_create(obj, 0, filename, linenumber);
203199
}
204200
#define PyStackRef_FromPyObjectSteal(obj) _PyStackRef_FromPyObjectSteal(_PyObject_CAST(obj), __FILE__, __LINE__)
205201

@@ -347,8 +343,8 @@ static inline _PyStackRef
347343
_PyStackRef_FromPyObjectNewMortal(PyObject *obj, const char *filename, int linenumber)
348344
{
349345
assert(obj != NULL);
350-
assert(!_Py_IsStaticImmortal(obj));
351-
Py_INCREF(obj);
346+
assert(!_Py_IsImmortal(obj));
347+
_Py_INCREF_MORTAL(obj);
352348
return _Py_stackref_create(obj, 0, filename, linenumber);
353349
}
354350
#define PyStackRef_FromPyObjectNewMortal(obj) _PyStackRef_FromPyObjectNewMortal(_PyObject_CAST(obj), __FILE__, __LINE__)
@@ -483,24 +479,14 @@ static const _PyStackRef PyStackRef_NULL = { .bits = PyStackRef_NULL_BITS };
483479

484480
#define PyStackRef_IsNullOrInt(stackref) (PyStackRef_IsNull(stackref) || PyStackRef_IsTaggedInt(stackref))
485481

486-
#if defined(Py_DEBUG) && !defined(Py_GIL_DISABLED)
482+
#if defined(Py_DEBUG)
487483

488484
static inline void
489485
PyStackRef_CheckValid(_PyStackRef ref)
490486
{
491487
assert(ref.bits != 0);
492488
int tag = ref.bits & Py_TAG_BITS;
493-
PyObject *obj = BITS_TO_PTR_MASKED(ref);
494-
switch (tag) {
495-
case 0:
496-
/* Can be immortal if object was made immortal after reference came into existence */
497-
assert(!_Py_IsStaticImmortal(obj));
498-
break;
499-
case Py_TAG_REFCNT:
500-
break;
501-
default:
502-
assert(0);
503-
}
489+
assert((tag == 0) || (tag == Py_TAG_REFCNT));
504490
}
505491

506492
#else
@@ -514,7 +500,7 @@ PyStackRef_CheckValid(_PyStackRef ref)
514500
#define PyStackRef_AsPyObjectBorrow BITS_TO_PTR_MASKED
515501
#define PyStackRef_Borrow(REF) (_PyStackRef){ .bits = ((REF).bits) | Py_TAG_REFCNT};
516502
#else
517-
/* Does this ref not have an embedded refcount and thus not refer to a declared immmortal object? */
503+
/* Does this ref not have an embedded refcount? */
518504
static inline int
519505
PyStackRef_RefcountOnObject(_PyStackRef ref)
520506
{
@@ -552,18 +538,9 @@ static inline _PyStackRef
552538
PyStackRef_FromPyObjectSteal(PyObject *obj)
553539
{
554540
assert(obj != NULL);
555-
#ifdef Py_GIL_DISABLED
556-
return (_PyStackRef){ .bits = (uintptr_t)obj };
557-
#else
558-
# if SIZEOF_VOID_P > 4
559-
unsigned int tag = obj->ob_flags & Py_TAG_REFCNT;
560-
# else
561-
unsigned int tag = _Py_IsImmortal(obj) ? Py_TAG_REFCNT : 0;
562-
# endif
563-
_PyStackRef ref = ((_PyStackRef){.bits = ((uintptr_t)(obj)) | tag});
541+
_PyStackRef ref = (_PyStackRef){ .bits = (uintptr_t)obj };
564542
PyStackRef_CheckValid(ref);
565543
return ref;
566-
#endif
567544
}
568545

569546
static inline _PyStackRef
@@ -600,6 +577,7 @@ static inline _PyStackRef
600577
_PyStackRef_FromPyObjectNewMortal(PyObject *obj)
601578
{
602579
assert(obj != NULL);
580+
assert(!_Py_IsImmortal(obj));
603581
_Py_INCREF_MORTAL(obj);
604582
_PyStackRef ref = (_PyStackRef){ .bits = (uintptr_t)obj };
605583
PyStackRef_CheckValid(ref);
@@ -618,14 +596,14 @@ PyStackRef_FromPyObjectBorrow(PyObject *obj)
618596
/* WARNING: This macro evaluates its argument more than once */
619597
#ifdef _WIN32
620598
#define PyStackRef_DUP(REF) \
621-
(PyStackRef_RefcountOnObject(REF) ? (_Py_INCREF_MORTAL(BITS_TO_PTR(REF)), (REF)) : (REF))
599+
(PyStackRef_RefcountOnObject(REF) ? (Py_INCREF(BITS_TO_PTR(REF)), (REF)) : (REF))
622600
#else
623601
static inline _PyStackRef
624602
PyStackRef_DUP(_PyStackRef ref)
625603
{
626604
assert(!PyStackRef_IsNull(ref));
627605
if (PyStackRef_RefcountOnObject(ref)) {
628-
_Py_INCREF_MORTAL(BITS_TO_PTR(ref));
606+
Py_INCREF(BITS_TO_PTR(ref));
629607
}
630608
return ref;
631609
}
@@ -669,15 +647,15 @@ PyStackRef_AsStrongReference(_PyStackRef stackref)
669647
#define PyStackRef_CLOSE(REF) \
670648
do { \
671649
_PyStackRef _temp = (REF); \
672-
if (PyStackRef_RefcountOnObject(_temp)) Py_DECREF_MORTAL(BITS_TO_PTR(_temp)); \
650+
if (PyStackRef_RefcountOnObject(_temp)) Py_DECREF(BITS_TO_PTR(_temp)); \
673651
} while (0)
674652
#else
675653
static inline void
676654
PyStackRef_CLOSE(_PyStackRef ref)
677655
{
678656
assert(!PyStackRef_IsNull(ref));
679657
if (PyStackRef_RefcountOnObject(ref)) {
680-
Py_DECREF_MORTAL(BITS_TO_PTR(ref));
658+
Py_DECREF(BITS_TO_PTR(ref));
681659
}
682660
}
683661
#endif
@@ -687,7 +665,7 @@ PyStackRef_CLOSE_SPECIALIZED(_PyStackRef ref, destructor destruct)
687665
{
688666
assert(!PyStackRef_IsNull(ref));
689667
if (PyStackRef_RefcountOnObject(ref)) {
690-
Py_DECREF_MORTAL_SPECIALIZED(BITS_TO_PTR(ref), destruct);
668+
_Py_DECREF_SPECIALIZED(BITS_TO_PTR(ref), destruct);
691669
}
692670
}
693671

@@ -700,7 +678,7 @@ PyStackRef_XCLOSE(_PyStackRef ref)
700678
assert(ref.bits != 0);
701679
if (PyStackRef_RefcountOnObject(ref)) {
702680
assert(!PyStackRef_IsNull(ref));
703-
Py_DECREF_MORTAL(BITS_TO_PTR(ref));
681+
Py_DECREF(BITS_TO_PTR(ref));
704682
}
705683
}
706684
#endif

InternalDocs/stackrefs.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ to avoid refcount contention on commonly shared objects.
2121
Three conversions control ownership:
2222

2323
- `PyStackRef_FromPyObjectNew(obj)` - create a new reference (INCREF if mortal).
24-
- `PyStackRef_FromPyObjectSteal(obj)` - take over ownership without changing the count unless the
25-
object is immortal.
24+
- `PyStackRef_FromPyObjectSteal(obj)` - take over ownership without changing the count;
25+
this function is very lightweight since it does not check or modify any refcount.
2626
- `PyStackRef_FromPyObjectBorrow(obj)` - create a borrowed stackref (never decref on close).
2727

2828
The `obj` argument must not be `NULL`.

0 commit comments

Comments
 (0)