From f1f85eb2b34defff83cb7f9bbb6ef15e4f322ef3 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 23 Jun 2020 12:36:42 +0200 Subject: [PATCH] bpo-40521: Make the empty frozenset per interpreter Each interpreter now has its own empty frozenset singleton. --- Include/internal/pycore_interp.h | 2 ++ Include/internal/pycore_pylifecycle.h | 2 +- .../2020-05-20-01-17-34.bpo-40521.wvAehI.rst | 10 ++++---- Objects/setobject.c | 25 +++++++++++-------- Python/pylifecycle.c | 4 +-- 5 files changed, 24 insertions(+), 19 deletions(-) diff --git a/Include/internal/pycore_interp.h b/Include/internal/pycore_interp.h index 3f64edcee983ba..697d97a39e01fb 100644 --- a/Include/internal/pycore_interp.h +++ b/Include/internal/pycore_interp.h @@ -238,6 +238,8 @@ struct _is { /* Using a cache is very effective since typically only a single slice is created and then deleted again. */ PySliceObject *slice_cache; + // The empty frozenset is a singleton. + PyObject *empty_frozenset; struct _Py_tuple_state tuple; struct _Py_list_state list; diff --git a/Include/internal/pycore_pylifecycle.h b/Include/internal/pycore_pylifecycle.h index dc997378297722..83ce1d2e7468c0 100644 --- a/Include/internal/pycore_pylifecycle.h +++ b/Include/internal/pycore_pylifecycle.h @@ -62,7 +62,7 @@ extern void _PyFrame_Fini(PyThreadState *tstate); extern void _PyDict_Fini(PyThreadState *tstate); extern void _PyTuple_Fini(PyThreadState *tstate); extern void _PyList_Fini(PyThreadState *tstate); -extern void _PySet_Fini(void); +extern void _PySet_Fini(PyThreadState *tstate); extern void _PyBytes_Fini(void); extern void _PyFloat_Fini(PyThreadState *tstate); extern void _PySlice_Fini(PyThreadState *tstate); diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-05-20-01-17-34.bpo-40521.wvAehI.rst b/Misc/NEWS.d/next/Core and Builtins/2020-05-20-01-17-34.bpo-40521.wvAehI.rst index 3406ca8c973d8b..24fd437062a51f 100644 --- a/Misc/NEWS.d/next/Core and Builtins/2020-05-20-01-17-34.bpo-40521.wvAehI.rst +++ b/Misc/NEWS.d/next/Core and Builtins/2020-05-20-01-17-34.bpo-40521.wvAehI.rst @@ -1,5 +1,5 @@ -The tuple free lists, the empty tuple singleton, the list free list, the float -free list, the slice cache, the dict free lists, the frame free list, the -asynchronous generator free lists, and the context free list are no longer -shared by all interpreters: each interpreter now its has own free lists and -caches. +The tuple free lists, the empty tuple singleton, the list free list, the empty +frozenset singleton, the float free list, the slice cache, the dict free lists, +the frame free list, the asynchronous generator free lists, and the context +free list are no longer shared by all interpreters: each interpreter now its +has own free lists and caches. diff --git a/Objects/setobject.c b/Objects/setobject.c index 76b1944db45588..69bfc7d0a58fb2 100644 --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -975,12 +975,11 @@ make_new_set_basetype(PyTypeObject *type, PyObject *iterable) return make_new_set(type, iterable); } -/* The empty frozenset is a singleton */ -static PyObject *emptyfrozenset = NULL; - static PyObject * make_new_frozenset(PyTypeObject *type, PyObject *iterable) { + PyObject *res; + if (type != &PyFrozenSet_Type) { return make_new_set(type, iterable); } @@ -991,7 +990,7 @@ make_new_frozenset(PyTypeObject *type, PyObject *iterable) Py_INCREF(iterable); return iterable; } - PyObject *res = make_new_set((PyTypeObject *)type, iterable); + res = make_new_set((PyTypeObject *)type, iterable); if (res == NULL || PySet_GET_SIZE(res) != 0) { return res; } @@ -1000,11 +999,17 @@ make_new_frozenset(PyTypeObject *type, PyObject *iterable) } // The empty frozenset is a singleton - if (emptyfrozenset == NULL) { - emptyfrozenset = make_new_set((PyTypeObject *)type, NULL); + PyInterpreterState *interp = _PyInterpreterState_GET(); + res = interp->empty_frozenset; + if (res == NULL) { + interp->empty_frozenset = make_new_set((PyTypeObject *)type, NULL); + res = interp->empty_frozenset; + if (res == NULL) { + return NULL; + } } - Py_XINCREF(emptyfrozenset); - return emptyfrozenset; + Py_INCREF(res); + return res; } static PyObject * @@ -2300,9 +2305,9 @@ PySet_Add(PyObject *anyset, PyObject *key) } void -_PySet_Fini(void) +_PySet_Fini(PyThreadState *tstate) { - Py_CLEAR(emptyfrozenset); + Py_CLEAR(tstate->interp->empty_frozenset); } int diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 1b4a3db517c1d1..aaea0454d00844 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -1255,9 +1255,7 @@ finalize_interp_types(PyThreadState *tstate, int is_main_interp) _PyAsyncGen_Fini(tstate); _PyContext_Fini(tstate); - if (is_main_interp) { - _PySet_Fini(); - } + _PySet_Fini(tstate); _PyDict_Fini(tstate); _PyList_Fini(tstate); _PyTuple_Fini(tstate); pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy