diff -r f9bd6ddb6ba4 Include/setobject.h --- a/Include/setobject.h Mon Feb 08 20:27:52 2016 +0200 +++ b/Include/setobject.h Mon Feb 08 15:48:56 2016 -0800 @@ -90,6 +90,7 @@ PyAPI_FUNC(int) PySet_Add(PyObject *set, PyObject *key); PyAPI_FUNC(int) _PySet_Next(PyObject *set, Py_ssize_t *pos, PyObject **key); PyAPI_FUNC(int) _PySet_NextEntry(PyObject *set, Py_ssize_t *pos, PyObject **key, long *hash); +PyAPI_FUNC(PyObject *) _PySet_GetStringItem(PyObject *anyset, PyObject *key, long hash); PyAPI_FUNC(PyObject *) PySet_Pop(PyObject *set); PyAPI_FUNC(int) _PySet_Update(PyObject *set, PyObject *iterable); diff -r f9bd6ddb6ba4 Include/stringobject.h --- a/Include/stringobject.h Mon Feb 08 20:27:52 2016 +0200 +++ b/Include/stringobject.h Mon Feb 08 15:48:56 2016 -0800 @@ -82,7 +82,6 @@ PyAPI_FUNC(void) PyString_InternInPlace(PyObject **); PyAPI_FUNC(void) PyString_InternImmortal(PyObject **); PyAPI_FUNC(PyObject *) PyString_InternFromString(const char *); -PyAPI_FUNC(void) _Py_ReleaseInternedStrings(void); /* Use only if you know it's a string */ #define PyString_CHECK_INTERNED(op) (((PyStringObject *)(op))->ob_sstate) diff -r f9bd6ddb6ba4 Modules/main.c --- a/Modules/main.c Mon Feb 08 20:27:52 2016 +0200 +++ b/Modules/main.c Mon Feb 08 15:48:56 2016 -0800 @@ -668,19 +668,6 @@ fprintf(stderr, "\x0cq\x0c"); /* make frontend quit */ #endif -#ifdef __INSURE__ - /* Insure++ is a memory analysis tool that aids in discovering - * memory leaks and other memory problems. On Python exit, the - * interned string dictionary is flagged as being in use at exit - * (which it is). Under normal circumstances, this is fine because - * the memory will be automatically reclaimed by the system. Under - * memory debugging, it's a huge source of useless noise, so we - * trade off slower shutdown for less distraction in the memory - * reports. -baw - */ - _Py_ReleaseInternedStrings(); -#endif /* __INSURE__ */ - return sts; } diff -r f9bd6ddb6ba4 Objects/setobject.c --- a/Objects/setobject.c Mon Feb 08 20:27:52 2016 +0200 +++ b/Objects/setobject.c Mon Feb 08 15:48:56 2016 -0800 @@ -681,6 +681,21 @@ return 0; } +PyObject * +_PySet_GetStringItem(PyObject *o, PyObject *key, long hash) +{ + PySetObject *so = (PySetObject*)o; + assert (PyAnySet_Check(so)); + setentry *entry = (so->lookup)(so, key, hash); + if (entry == NULL) { + PyErr_Clear(); + return NULL; + } + if (entry->key == dummy) + return NULL; + return entry->key; +} + static int set_contains_key(PySetObject *so, PyObject *key) { diff -r f9bd6ddb6ba4 Objects/stringobject.c --- a/Objects/stringobject.c Mon Feb 08 20:27:52 2016 +0200 +++ b/Objects/stringobject.c Mon Feb 08 15:48:56 2016 -0800 @@ -581,9 +581,9 @@ break; case SSTATE_INTERNED_MORTAL: - /* revive dead object temporarily for DelItem */ - Py_REFCNT(op) = 3; - if (PyDict_DelItem(interned, op) != 0) + /* revive dead object temporarily for Discard */ + Py_REFCNT(op) = 2; + if (PySet_Discard(interned, op) != 1) Py_FatalError( "deletion of interned string failed"); break; @@ -4741,26 +4741,29 @@ if (PyString_CHECK_INTERNED(s)) return; if (interned == NULL) { - interned = PyDict_New(); + interned = PySet_New(NULL); if (interned == NULL) { PyErr_Clear(); /* Don't leave an exception */ return; } } - t = PyDict_GetItem(interned, (PyObject *)s); + if (s->ob_shash == -1) { + string_hash(s); + } + t = _PySet_GetStringItem(interned, (PyObject *)s, s->ob_shash); if (t) { Py_INCREF(t); Py_SETREF(*p, t); return; } - if (PyDict_SetItem(interned, (PyObject *)s, (PyObject *)s) < 0) { + if (PySet_Add(interned, (PyObject *)s) < 0) { PyErr_Clear(); return; } - /* The two references in interned are not counted by refcnt. + /* The reference in interned is not counted by refcnt. The string deallocator will take care of this */ - Py_REFCNT(s) -= 2; + Py_REFCNT(s) -= 1; PyString_CHECK_INTERNED(s) = SSTATE_INTERNED_MORTAL; } @@ -4793,53 +4796,3 @@ Py_CLEAR(characters[i]); Py_CLEAR(nullstring); } - -void _Py_ReleaseInternedStrings(void) -{ - PyObject *keys; - PyStringObject *s; - Py_ssize_t i, n; - Py_ssize_t immortal_size = 0, mortal_size = 0; - - if (interned == NULL || !PyDict_Check(interned)) - return; - keys = PyDict_Keys(interned); - if (keys == NULL || !PyList_Check(keys)) { - PyErr_Clear(); - return; - } - - /* Since _Py_ReleaseInternedStrings() is intended to help a leak - detector, interned strings are not forcibly deallocated; rather, we - give them their stolen references back, and then clear and DECREF - the interned dict. */ - - n = PyList_GET_SIZE(keys); - fprintf(stderr, "releasing %" PY_FORMAT_SIZE_T "d interned strings\n", - n); - for (i = 0; i < n; i++) { - s = (PyStringObject *) PyList_GET_ITEM(keys, i); - switch (s->ob_sstate) { - case SSTATE_NOT_INTERNED: - /* XXX Shouldn't happen */ - break; - case SSTATE_INTERNED_IMMORTAL: - Py_REFCNT(s) += 1; - immortal_size += Py_SIZE(s); - break; - case SSTATE_INTERNED_MORTAL: - Py_REFCNT(s) += 2; - mortal_size += Py_SIZE(s); - break; - default: - Py_FatalError("Inconsistent interned string state."); - } - s->ob_sstate = SSTATE_NOT_INTERNED; - } - fprintf(stderr, "total size of all interned strings: " - "%" PY_FORMAT_SIZE_T "d/%" PY_FORMAT_SIZE_T "d " - "mortal/immortal\n", mortal_size, immortal_size); - Py_DECREF(keys); - PyDict_Clear(interned); - Py_CLEAR(interned); -} diff -r f9bd6ddb6ba4 PC/os2emx/python27.def --- a/PC/os2emx/python27.def Mon Feb 08 20:27:52 2016 +0200 +++ b/PC/os2emx/python27.def Mon Feb 08 15:48:56 2016 -0800 @@ -539,7 +539,6 @@ "PyString_AsStringAndSize" "_PyString_FormatLong" "PyString_Format" - "_Py_ReleaseInternedStrings" "PyString_Size" "PyString_Concat" "PyString_ConcatAndDel" diff -r f9bd6ddb6ba4 Python/pythonrun.c --- a/Python/pythonrun.c Mon Feb 08 20:27:52 2016 +0200 +++ b/Python/pythonrun.c Mon Feb 08 15:48:56 2016 -0800 @@ -522,8 +522,8 @@ PyCFunction_Fini(); PyTuple_Fini(); PyList_Fini(); + PyString_Fini(); PySet_Fini(); - PyString_Fini(); PyByteArray_Fini(); PyInt_Fini(); PyFloat_Fini();