[issue34042] Reference loss for local classes
Pablo Galindo Salgado
report at bugs.python.org
Thu Jul 5 14:03:58 EDT 2018
Pablo Galindo Salgado <pablogsal at gmail.com> added the comment:
I think I found it. After doing the bisect manually (as redirecting stdout/stderr) seems to affect somehow the test) I found commit b0a7a037b8fde56b62f886d5188bced7776777b4 as the culprit. Reverting this commit on the current master seem to solve the problem. This is the diff of the revert:
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index 40d7d8af6e..f7d792232e 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -613,52 +613,6 @@ new_dict_with_shared_keys(PyDictKeysObject *keys)
return new_dict(keys, values);
}
-
-static PyObject *
-clone_combined_dict(PyDictObject *orig)
-{
- assert(PyDict_CheckExact(orig));
- assert(orig->ma_values == NULL);
- assert(orig->ma_keys->dk_refcnt == 1);
-
- Py_ssize_t keys_size = _PyDict_KeysSize(orig->ma_keys);
- PyDictKeysObject *keys = PyObject_Malloc(keys_size);
- if (keys == NULL) {
- PyErr_NoMemory();
- return NULL;
- }
-
- memcpy(keys, orig->ma_keys, keys_size);
-
- /* After copying key/value pairs, we need to incref all
- keys and values and they are about to be co-owned by a
- new dict object. */
- PyDictKeyEntry *ep0 = DK_ENTRIES(keys);
- Py_ssize_t n = keys->dk_nentries;
- for (Py_ssize_t i = 0; i < n; i++) {
- PyDictKeyEntry *entry = &ep0[i];
- PyObject *value = entry->me_value;
- if (value != NULL) {
- Py_INCREF(value);
- Py_INCREF(entry->me_key);
- }
- }
-
- PyDictObject *new = (PyDictObject *)new_dict(keys, NULL);
- if (new == NULL) {
- /* In case of an error, `new_dict()` takes care of
- cleaning up `keys`. */
- return NULL;
- }
- new->ma_used = orig->ma_used;
- assert(_PyDict_CheckConsistency(new));
- if (_PyObject_GC_IS_TRACKED(orig)) {
- /* Maintain tracking. */
- _PyObject_GC_TRACK(new);
- }
- return (PyObject *)new;
-}
-
PyObject *
PyDict_New(void)
{
@@ -2527,13 +2481,7 @@ PyDict_Copy(PyObject *o)
PyErr_BadInternalCall();
return NULL;
}
-
mp = (PyDictObject *)o;
- if (mp->ma_used == 0) {
- /* The dict is empty; just return a new dict. */
- return PyDict_New();
- }
-
if (_PyDict_HasSplitTable(mp)) {
PyDictObject *split_copy;
Py_ssize_t size = USABLE_FRACTION(DK_SIZE(mp->ma_keys));
@@ -2560,27 +2508,6 @@ PyDict_Copy(PyObject *o)
_PyObject_GC_TRACK(split_copy);
return (PyObject *)split_copy;
}
-
- if (PyDict_CheckExact(mp) && mp->ma_values == NULL &&
- (mp->ma_used >= (mp->ma_keys->dk_nentries * 2) / 3))
- {
- /* Use fast-copy if:
-
- (1) 'mp' is an instance of a subclassed dict; and
-
- (2) 'mp' is not a split-dict; and
-
- (3) if 'mp' is non-compact ('del' operation does not resize dicts),
- do fast-copy only if it has at most 1/3 non-used keys.
-
- The last condition (3) is important to guard against a pathological
- case when a large dict is almost emptied with multiple del/pop
- operations and copied after that. In cases like this, we defer to
- PyDict_Merge, which produces a compacted copy.
- */
- return clone_combined_dict(mp);
- }
-
copy = PyDict_New();
if (copy == NULL)
return NULL;
----------
_______________________________________
Python tracker <report at bugs.python.org>
<https://bugs.python.org/issue34042>
_______________________________________
More information about the Python-bugs-list
mailing list