Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Modify singleton object interning to not use intern dict
Using it in the intern dict seems to causes decrementation
of its reference count elsewhere that cannot be solved
with Py_INCREF. However, updating the tuple inside
intern_string_constants does not cause the extra
decrementation.
  • Loading branch information
Christopher-Chianelli committed Apr 16, 2023
commit 7d06a7ebf1008215e14a90ee52452a7f6ca65601
37 changes: 35 additions & 2 deletions Objects/codeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@
#include "pycore_tuple.h" // _PyTuple_ITEMS()
#include "clinic/codeobject.c.h"

#define LATIN1(ch) \
(ch < 128 \
? (PyObject*)&_Py_SINGLETON(strings).ascii[ch] \
: (PyObject*)&_Py_SINGLETON(strings).latin1[ch - 128])

static PyObject* code_repr(PyCodeObject *co);

static const char *
Expand Down Expand Up @@ -111,6 +116,15 @@ PyCode_ClearWatcher(int watcher_id)
* generic helpers
******************/

/* is_runtime_global_string(s): true iff s is a runtime global (singleton ascii strings) */
static int
is_runtime_global_string(PyObject *o) {
if (!PyUnicode_IS_ASCII(o))
return 0;

return PyUnicode_GET_LENGTH(o) == 1;
}

/* all_name_chars(s): true iff s matches [a-zA-Z0-9_]* */
static int
all_name_chars(PyObject *o)
Expand Down Expand Up @@ -156,8 +170,27 @@ intern_string_constants(PyObject *tuple, int *modified)
if (PyUnicode_READY(v) == -1) {
return -1;
}

if (all_name_chars(v)) {
if (is_runtime_global_string(v)) {
// unfortunately, storing the immortal singletons
// in the interned string dict seem to cause some
// refcount issues
const void *data;
int kind;
Py_UCS4 ch;

kind = PyUnicode_KIND(v);
data = PyUnicode_DATA(v);
ch = PyUnicode_READ(kind, data, 0);
PyObject *w = LATIN1(ch);
if (w != v) {
PyTuple_SET_ITEM(tuple, i, w);
Py_INCREF(w);
if (modified) {
*modified = 1;
}
}
}
else if (all_name_chars(v)) {
PyObject *w = v;
PyUnicode_InternInPlace(&v);
if (w != v) {
Expand Down
7 changes: 0 additions & 7 deletions Objects/unicodeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -244,13 +244,6 @@ init_interned_dict(PyInterpreterState *interp)
if (interned == NULL) {
return -1;
}
for (int ch = 0; ch < 256; ch++) {
PyObject *singleton_str = LATIN1(ch);
if (PyDict_SetItem(interned, singleton_str, singleton_str) == -1) {
Py_DECREF(interned);
return -1;
}
}
_Py_INTERP_CACHED_OBJECT(interp, interned_strings) = interned;
return 0;
}
Expand Down