8000 Remove static immortal bit in favor of unicode intern state · python/cpython@a719b41 · GitHub
[go: up one dir, main page]

Skip to content

Commit a719b41

Browse files
Remove static immortal bit in favor of unicode intern state
1 parent 1321ff6 commit a719b41

File tree

8 files changed

+35
-32
lines changed

8 files changed

+35
-32
lines changed

Include/cpython/unicodeobject.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ typedef struct {
151151
SSTATE_NOT_INTERNED (0)
152152
SSTATE_INTERNED_MORTAL (1)
153153
SSTATE_INTERNED_IMMORTAL (2)
154+
SSTATE_INTERNED_IMMORTAL_STATIC (3)
154155
155156
If interned != SSTATE_NOT_INTERNED, the two references from the
156157
dictionary to this object are *not* counted in ob_refcnt.
@@ -278,6 +279,7 @@ PyAPI_FUNC(int) _PyUnicode_CheckConsistency(
278279
#define SSTATE_NOT_INTERNED 0
279280
#define SSTATE_INTERNED_MORTAL 1
280281
#define SSTATE_INTERNED_IMMORTAL 2
282+
#define SSTATE_INTERNED_IMMORTAL_STATIC 3
281283

282284
/* Use only if you know it's a string */
283285
#define PyUnicode_CHECK_INTERNED(op) \

Include/internal/pycore_object.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ extern "C" {
1717

1818
#define _PyObject_IMMORTAL_INIT(type) \
1919
{ \
20-
.ob_refcnt = _Py_IMMORTAL_STATIC_REFCNT, \
20+
.ob_refcnt = _Py_IMMORTAL_REFCNT, \
2121
.ob_type = type, \
2222
}
2323
#define _PyVarObject_IMMORTAL_INIT(type, size) \

Include/internal/pycore_runtime_init.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ extern "C" {
9999
.length = sizeof(LITERAL) - 1, \
100100
.hash = -1, \
101101
.state = { \
102+
.interned = 3, \
102103
.kind = 1, \
103104
.compact = 1, \
104105
.ascii = ASCII, \

Include/object.h

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -94,16 +94,13 @@ cleanup during runtime finalization.
9494
#define _Py_IMMORTAL_BIT_OFFSET (8 * sizeof(Py_ssize_t) - 3)
9595
#define _Py_IMMORTAL_BIT (1LL << _Py_IMMORTAL_BIT_OFFSET)
9696
#define _Py_IMMORTAL_REFCNT (_Py_IMMORTAL_BIT + (_Py_IMMORTAL_BIT / 2))
97-
#define _Py_IMMORTAL_STATIC_BIT_OFFSET (8 * sizeof(Py_ssize_t) - 2)
98-
#define _Py_IMMORTAL_STATIC_BIT (1LL << _Py_IMMORTAL_STATIC_BIT_OFFSET)
99-
#define _Py_IMMORTAL_STATIC_REFCNT (_Py_IMMORTAL_STATIC_BIT + _Py_IMMORTAL_REFCNT)
10097

10198
#define PyObject_HEAD_INIT(type) \
10299
{ _PyObject_EXTRA_INIT \
103100
1, type },
104101

105102
#define PyObject_HEAD_IMMORTAL_INIT(type) \
106-
{ _PyObject_EXTRA_INIT _Py_IMMORTAL_STATIC_REFCNT, type },
103+
{ _PyObject_EXTRA_INIT _Py_IMMORTAL_REFCNT, type },
107104

108105
#define PyVarObject_HEAD_INIT(type, size) \
109106
{ PyObject_HEAD_IMMORTAL_INIT(type) size },
@@ -165,11 +162,6 @@ static inline Py_ssize_t Py_SIZE(const PyVarObject *ob) {
165162
}
166163
#define Py_SIZE(ob) Py_SIZE(_PyVarObject_CAST_CONST(ob))
167164

168-
static inline int _Py_IsStaticImmortal(PyObject *op)
169-
{
170-
return (op->ob_refcnt & _Py_IMMORTAL_STATIC_BIT) != 0;
171-
}
172-
173165
static inline int _Py_IsImmortal(PyObject *op)
174166
{
175167
return (op->ob_refcnt & _Py_IMMORTAL_BIT) != 0;

Objects/object.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1707,7 +1707,7 @@ PyTypeObject _PyNone_Type = {
17071707

17081708
PyObject _Py_NoneStruct = {
17091709
_PyObject_EXTRA_INIT
1710-
_Py_IMMORTAL_STATIC_REFCNT,
1710+
_Py_IMMORTAL_REFCNT,
17111711
&_PyNone_Type
17121712
};
17131713

@@ -1809,7 +1809,7 @@ PyTypeObject _PyNotImplemented_Type = {
18091809

18101810
PyObject _Py_NotImplementedStruct = {
18111811
_PyObject_EXTRA_INIT
1812-
_Py_IMMORTAL_STATIC_REFCNT,
1812+
_Py_IMMORTAL_REFCNT,
18131813
&_PyNotImplemented_Type
18141814
};
18151815

Objects/sliceobject.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ PyTypeObject PyEllipsis_Type = {
8989

9090
PyObject _Py_EllipsisObject = {
9191
_PyObject_EXTRA_INIT
92-
_Py_IMMORTAL_STATIC_REFCNT,
92+
_Py_IMMORTAL_REFCNT,
9393
&PyEllipsis_Type
9494
};
9595

Objects/unicodeobject.c

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -250,16 +250,9 @@ unicode_decode_utf8(const char *s, Py_ssize_t size,
250250
Py_ssize_t *consumed);
251251
#ifdef Py_DEBUG
252252
static inline int unicode_is_finalizing(void);
253-
#endif
254-
255253
static int unicode_is_singleton(PyObject *unicode);
254+
#endif
256255

257-
static struct _Py_unicode_state*
258-
get_unicode_state(void)
259-
{
260-
PyInterpreterState *interp = _PyInterpreterState_GET();
261-
return &interp->unicode;
262-
}
263256

264257
#define _Py_RETURN_UNICODE_EMPTY() \
265258
do { \
@@ -1921,6 +1914,9 @@ unicode_dealloc(PyObject *unicode)
19211914
case SSTATE_INTERNED_IMMORTAL:
19221915
break;
19231916

1917+
case SSTATE_INTERNED_IMMORTAL_STATIC:
1918+
break;
1919+
19241920
default:
19251921
Py_UNREACHABLE();
19261922
}
@@ -15535,10 +15531,12 @@ PyUnicode_InternInPlace(PyObject **p)
1553515531
return;
1553615532
}
1553715533

15538-
if (!_Py_IsStaticImmortal(s)) {
15539-
_Py_SetImmortal(s);
15534+
if (_Py_IsImmortal(s)) {
15535+
_PyUnicode_STATE(*p).interned = SSTATE_INTERNED_IMMORTAL_STATIC;
15536+
return;
1554015537
}
15541-
_PyUnicode_STATE(*p).interned = SSTATE_INTERNED_IMMORTAL;
15538+
_Py_SetImmortal(s);
15539+
_PyUnicode_STATE(*p).interned = SSTATE_INTERNED_IMMORTAL;
1554215540
#else
1554315541
// PyDict expects that interned strings have their hash
1554415542
// (PyASCIIObject.hash) already computed.
@@ -15585,6 +15583,14 @@ _PyUnicode_ClearInterned(PyInterpreterState *interp)
1558515583
}
1558615584
assert(PyDict_CheckExact(interned));
1558715585

15586+
// TODO: Currently, the runtime is not able to guarantee that it can exit
15587+
// without allocations that carry over to a future initialization of
15588+
// Python within the same process.
15589+
// i.e: ./python -X showrefcount -c 'import itertools'
15590+
// [298 refs, 298 blocks]
15591+
// Therefore, this should remain disabled until there is a strict
15592+
// guarantee that no memory will be leftover after `Py_Finalize`
15593+
#ifdef Py_DEBUG
1558815594
/* For all non-singleton interned strings, restore the two valid references
1558915595
to that instance from within the intern string dictionary and let the
1559015596
normal reference counting process clean up these instances. */
@@ -15594,15 +15600,16 @@ _PyUnicode_ClearInterned(PyInterpreterState *interp)
1559415600
assert(PyUnicode_IS_READY(s));
1559515601
switch (PyUnicode_CHECK_INTERNED(s)) {
1559615602
case SSTATE_INTERNED_IMMORTAL:
15597-
if (!_Py_IsStaticImmortal(s) && !unicode_is_singleton(s)) {
15598-
// Skip the Immortal Instance check and directly set the refcnt.
15599-
s->ob_refcnt = 2;
15603+
// printf("String: %s, ptr: %p\n", PyUnicode_AsUTF8(PyObject_Repr(s)), (void *) s);
15604+
// Skip the Immortal Instance check and directly set the refcnt.
15605+
s->ob_refcnt = 2;
1560015606
#ifdef Py_REF_DEBUG
15601-
// Update the total ref counts to account for the original
15602-
// reference to this string that no longer exists.
15603-
_Py_RefTotal--;
15607+
// Update the total ref counts to account for the original
15608+
// reference to this string that no longer exists.
15609+
_Py_RefTotal--;
1560415610
#endif
15605-
}
15611+
break;
15612+
case SSTATE_INTERNED_IMMORTAL_STATIC:
1560615613
break;
1560715614
case SSTATE_INTERNED_MORTAL:
1560815615
/* fall through */
@@ -15620,6 +15627,7 @@ _PyUnicode_ClearInterned(PyInterpreterState *interp)
1562015627
for (Py_ssize_t i=0; i < ids->size; i++) {
1562115628
Py_XINCREF(ids->array[i]);
1562215629
}
15630+
#endif
1562315631

1562415632
PyDict_Clear(interned);
1562515633
Py_CLEAR(interned);

Tools/scripts/deepfreeze.py

Lines changed: 1 addition & 1 deletion
4934
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ def block(self, prefix: str, suffix: str = "") -> None:
139139

140140
def object_head(self, typename: str) -> None:
141141
with self.block(".ob_base =", ","):
142-
self.write(f".ob_refcnt = _Py_IMMORTAL_STATIC_REFCNT,")
142+
self.write(f".ob_refcnt = _Py_IMMORTAL_REFCNT,")
143143
self.write(f".ob_type = &{typename},")
144144

145145
def object_var_head(self, typename: str, size: int) -> None:

0 commit comments

Comments
 (0)
0