Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 34k
bpo-39465: Fix _PyUnicode_FromId() for subinterpreters#20058
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| Make :c:func:`_PyUnicode_FromId` function compatible with subinterpreters. | ||
| Each interpreter now has an array of identifier objects (interned strings | ||
| decoded from UTF-8). Patch by Victor Stinner. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -41,6 +41,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| #define PY_SSIZE_T_CLEAN | ||
| #include "Python.h" | ||
| #include "pycore_abstract.h" // _PyIndex_Check() | ||
| #include "pycore_atomic_funcs.h" // _Py_atomic_size_get() | ||
| #include "pycore_bytes_methods.h" // _Py_bytes_lower() | ||
| #include "pycore_format.h" // F_LJUST | ||
| #include "pycore_initconfig.h" // _PyStatus_OK() | ||
| @@ -302,9 +303,6 @@ unicode_decode_utf8(const char *s, Py_ssize_t size, | ||
| _Py_error_handler error_handler, const char *errors, | ||
| Py_ssize_t *consumed); | ||
| /* List of static strings. */ | ||
| static _Py_Identifier *static_strings = NULL; | ||
| /* Fast detection of the most frequent whitespace characters */ | ||
| const unsigned char _Py_ascii_whitespace[] ={ | ||
| 0, 0, 0, 0, 0, 0, 0, 0, | ||
| @@ -2312,42 +2310,85 @@ PyUnicode_FromString(const char *u) | ||
| return PyUnicode_DecodeUTF8Stateful(u, (Py_ssize_t)size, NULL, NULL); | ||
| } | ||
| PyObject * | ||
| _PyUnicode_FromId(_Py_Identifier *id) | ||
| { | ||
| if (id->object){ | ||
| return id->object; | ||
| PyInterpreterState *interp = _PyInterpreterState_GET(); | ||
| struct _Py_unicode_ids *ids = &interp->unicode.ids; | ||
serhiy-storchaka marked this conversation as resolved. Outdated Show resolvedHide resolvedUh oh!There was an error while loading. Please reload this page. | ||
| int index = _Py_atomic_size_get(&id->index); | ||
| if (index < 0){ | ||
vstinner marked this conversation as resolved. Outdated Show resolvedHide resolvedUh oh!There was an error while loading. Please reload this page. | ||
| struct _Py_unicode_runtime_ids *rt_ids = &interp->runtime->unicode_ids; | ||
| PyThread_acquire_lock(rt_ids->lock, WAIT_LOCK); | ||
vstinner marked this conversation as resolved. Outdated Show resolvedHide resolvedUh oh!There was an error while loading. Please reload this page. | ||
| // Check again to detect concurrent access. Another thread can have | ||
| // initialized the index while this thread waited for the lock. | ||
| index = _Py_atomic_size_get(&id->index); | ||
| if (index < 0){ | ||
| assert(rt_ids->next_index < PY_SSIZE_T_MAX); | ||
| index = rt_ids->next_index; | ||
| rt_ids->next_index++; | ||
| _Py_atomic_size_set(&id->index, index); | ||
| } | ||
| PyThread_release_lock(rt_ids->lock); | ||
| } | ||
| assert(index >= 0); | ||
| PyObject *obj; | ||
| obj = PyUnicode_DecodeUTF8Stateful(id->string, | ||
| strlen(id->string), | ||
| if (index < ids->size){ | ||
vstinner marked this conversation as resolved. Outdated Show resolvedHide resolvedUh oh!There was an error while loading. Please reload this page. | ||
| obj = ids->array[index]; | ||
| if (obj){ | ||
| // Return a borrowed reference | ||
| return obj; | ||
| } | ||
| } | ||
| obj = PyUnicode_DecodeUTF8Stateful(id->string, strlen(id->string), | ||
| NULL, NULL); | ||
| if (!obj){ | ||
| return NULL; | ||
| } | ||
| PyUnicode_InternInPlace(&obj); | ||
| assert(!id->next); | ||
| id->object = obj; | ||
| id->next = static_strings; | ||
| static_strings = id; | ||
| return id->object; | ||
| if (index >= ids->size){ | ||
serhiy-storchaka marked this conversation as resolved. Outdated Show resolvedHide resolvedUh oh!There was an error while loading. Please reload this page. | ||
| // Overallocate to reduce the number of realloc | ||
| Py_ssize_t new_size = Py_MAX(index * 2, 16); | ||
vstinner marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading. Please reload this page. | ||
| Py_ssize_t item_size = sizeof(ids->array[0]); | ||
| PyObject **new_array = PyMem_Realloc(ids->array, new_size * item_size); | ||
| if (new_array == NULL){ | ||
| PyErr_NoMemory(); | ||
| return NULL; | ||
| } | ||
| memset(&new_array[ids->size], 0, (new_size - ids->size) * item_size); | ||
| ids->array = new_array; | ||
| ids->size = new_size; | ||
| } | ||
| // The array stores a strong reference | ||
| ids->array[index] = obj; | ||
| // Return a borrowed reference | ||
| return obj; | ||
| } | ||
| static void | ||
| unicode_clear_static_strings(void) | ||
| unicode_clear_identifiers(PyThreadState *tstate) | ||
| { | ||
| _Py_Identifier *tmp, *s = static_strings; | ||
| while (s){ | ||
| Py_CLEAR(s->object); | ||
| tmp = s->next; | ||
| s->next = NULL; | ||
| s = tmp; | ||
| PyInterpreterState *interp = _PyInterpreterState_GET(); | ||
| struct _Py_unicode_ids *ids = &interp->unicode.ids; | ||
| for (Py_ssize_t i=0; i < ids->size; i++){ | ||
| Py_XDECREF(ids->array[i]); | ||
| } | ||
| static_strings = NULL; | ||
| ids->size = 0; | ||
| PyMem_Free(ids->array); | ||
| ids->array = NULL; | ||
| // Don't reset _PyRuntime next_index: _Py_Identifier.id remains valid | ||
vstinner marked this conversation as resolved. Outdated Show resolvedHide resolvedUh oh!There was an error while loading. Please reload this page. | ||
| // after Py_Finalize(). | ||
| } | ||
| /* Internal function, doesn't check maximum character */ | ||
| PyObject* | ||
| @@ -16238,9 +16279,7 @@ _PyUnicode_Fini(PyThreadState *tstate) | ||
| Py_CLEAR(state->latin1[i]); | ||
| } | ||
| if (_Py_IsMainInterpreter(tstate)){ | ||
| unicode_clear_static_strings(); | ||
| } | ||
| unicode_clear_identifiers(tstate); | ||
| _PyUnicode_FiniEncodings(&tstate->interp->unicode.fs_codec); | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.