Skip to content

Commit 2451a86

Browse files
committed
Add function for 'interned' writes; fix type for free-threaded builds (unit8)
1 parent 2611679 commit 2451a86

File tree

2 files changed

+22
-12
lines changed

2 files changed

+22
-12
lines changed

Include/cpython/unicodeobject.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ _Py_DEPRECATED_EXTERNALLY(3.14) typedef _PyUnicodeObject PyUnicodeObject;
212212
/* Use only if you know it's a string */
213213
static inline unsigned int PyUnicode_CHECK_INTERNED(PyObject *op) {
214214
#ifdef Py_GIL_DISABLED
215-
return _Py_atomic_load_uint16_relaxed(&_PyASCIIObject_CAST(op)->state.interned);
215+
return _Py_atomic_load_uint8_relaxed(&_PyASCIIObject_CAST(op)->state.interned);
216216
#else
217217
return _PyASCIIObject_CAST(op)->state.interned;
218218
#endif

Objects/unicodeobject.c

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,17 @@ clear_interned_dict(PyInterpreterState *interp)
373373
}
374374
}
375375

376+
static inline void
377+
set_interned_field(PyObject *s, int new_state)
378+
{
379+
#ifdef Py_GIL_DISABLED
380+
FT_ATOMIC_STORE_UINT8_RELAXED((_PyUnicode_STATE(s).interned),
381+
((unsigned char)new_state));
382+
#else
383+
_PyUnicode_STATE(s).interned = new_state;
384+
#endif
385+
}
386+
376387
static PyStatus
377388
init_global_interned_strings(PyInterpreterState *interp)
378389
{
@@ -1348,7 +1359,6 @@ _PyUnicode_Dump(PyObject *op)
13481359
}
13491360
#endif
13501361

1351-
13521362
PyObject *
13531363
PyUnicode_New(Py_ssize_t size, Py_UCS4 maxchar)
13541364
{
@@ -1417,7 +1427,7 @@ PyUnicode_New(Py_ssize_t size, Py_UCS4 maxchar)
14171427
data = unicode + 1;
14181428
_PyUnicode_LENGTH(unicode) = size;
14191429
_PyUnicode_HASH(unicode) = -1;
1420-
_PyUnicode_STATE(unicode).interned = 0;
1430+
set_interned_field(obj, 0);
14211431
_PyUnicode_STATE(unicode).kind = kind;
14221432
_PyUnicode_STATE(unicode).compact = 1;
14231433
_PyUnicode_STATE(unicode).ascii = is_ascii;
@@ -1722,7 +1732,7 @@ unicode_dealloc(PyObject *unicode)
17221732
_Py_SetImmortal(unicode);
17231733
return;
17241734
}
1725-
switch (_PyUnicode_STATE(unicode).interned) {
1735+
switch (PyUnicode_CHECK_INTERNED(unicode)) {
17261736
case SSTATE_NOT_INTERNED:
17271737
break;
17281738
case SSTATE_INTERNED_MORTAL:
@@ -1752,7 +1762,7 @@ unicode_dealloc(PyObject *unicode)
17521762
// so it can't cause trouble (except wasted memory)
17531763
// - if it wasn't popped, it'll remain interned
17541764
_Py_SetImmortal(unicode);
1755-
_PyUnicode_STATE(unicode).interned = SSTATE_INTERNED_IMMORTAL;
1765+
set_interned_field(unicode, SSTATE_INTERNED_IMMORTAL);
17561766
return;
17571767
}
17581768
if (r == 0) {
@@ -15485,7 +15495,7 @@ unicode_subtype_new(PyTypeObject *type, PyObject *unicode)
1548515495
#else
1548615496
_PyUnicode_HASH(self) = _PyUnicode_HASH(unicode);
1548715497
#endif
15488-
_PyUnicode_STATE(self).interned = 0;
15498+
set_interned_field(self, 0);
1548915499
_PyUnicode_STATE(self).kind = kind;
1549015500
_PyUnicode_STATE(self).compact = 0;
1549115501
_PyUnicode_STATE(self).ascii = _PyUnicode_STATE(unicode).ascii;
@@ -15704,8 +15714,8 @@ intern_static(PyInterpreterState *interp, PyObject *s /* stolen */)
1570415714
assert(r == NULL);
1570515715
/* but just in case (for the non-debug build), handle this */
1570615716
if (r != NULL && r != s) {
15707-
assert(_PyUnicode_STATE(r).interned == SSTATE_INTERNED_IMMORTAL_STATIC);
1570815717
assert(_PyUnicode_CHECK(r));
15718+
assert(PyUnicode_CHECK_INTERNED(r) == SSTATE_INTERNED_IMMORTAL_STATIC);
1570915719
Py_DECREF(s);
1571015720
return Py_NewRef(r);
1571115721
}
@@ -15714,7 +15724,7 @@ intern_static(PyInterpreterState *interp, PyObject *s /* stolen */)
1571415724
Py_FatalError("failed to intern static string");
1571515725
}
1571615726

15717-
_PyUnicode_STATE(s).interned = SSTATE_INTERNED_IMMORTAL_STATIC;
15727+
set_interned_field(s, SSTATE_INTERNED_IMMORTAL_STATIC);
1571815728
return s;
1571915729
}
1572015730

@@ -15741,7 +15751,7 @@ immortalize_interned(PyObject *s)
1574115751
_Py_DecRefTotal(_PyThreadState_GET());
1574215752
}
1574315753
#endif
15744-
FT_ATOMIC_STORE_UINT16_RELAXED(_PyUnicode_STATE(s).interned, SSTATE_INTERNED_IMMORTAL);
15754+
set_interned_field(s, SSTATE_INTERNED_IMMORTAL);
1574515755
_Py_SetImmortal(s);
1574615756
}
1574715757

@@ -15851,15 +15861,15 @@ intern_common(PyInterpreterState *interp, PyObject *s /* stolen */,
1585115861

1585215862
/* NOT_INTERNED -> INTERNED_MORTAL */
1585315863

15854-
assert(_PyUnicode_STATE(s).interned == SSTATE_NOT_INTERNED);
15864+
assert(PyUnicode_CHECK_INTERNED(s) == SSTATE_NOT_INTERNED);
1585515865

1585615866
if (!_Py_IsImmortal(s)) {
1585715867
/* The two references in interned dict (key and value) are not counted.
1585815868
unicode_dealloc() and _PyUnicode_ClearInterned() take care of this. */
1585915869
Py_DECREF(s);
1586015870
Py_DECREF(s);
1586115871
}
15862-
FT_ATOMIC_STORE_UINT16_RELAXED(_PyUnicode_STATE(s).interned, SSTATE_INTERNED_MORTAL);
15872+
set_interned_field(s, SSTATE_INTERNED_MORTAL);
1586315873

1586415874
/* INTERNED_MORTAL -> INTERNED_IMMORTAL (if needed) */
1586515875

@@ -15996,7 +16006,7 @@ _PyUnicode_ClearInterned(PyInterpreterState *interp)
1599616006
Py_UNREACHABLE();
1599716007
}
1599816008
if (!shared) {
15999-
FT_ATOMIC_STORE_UINT16_RELAXED(_PyUnicode_STATE(s).interned, SSTATE_NOT_INTERNED);
16009+
set_interned_field(s, SSTATE_NOT_INTERNED);
1600016010
}
1600116011
}
1600216012
#ifdef INTERNED_STATS

0 commit comments

Comments
 (0)