mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 23:21:29 +00:00 
			
		
		
		
	bpo-34100: compile: Re-enable frozenset merging (GH-10760)
This reverts commit 1005c84535.
			
			
This commit is contained in:
		
							parent
							
								
									1cdfcfc984
								
							
						
					
					
						commit
						f7e4d3642f
					
				
					 2 changed files with 65 additions and 2 deletions
				
			
		| 
						 | 
					@ -615,6 +615,14 @@ def check_same_constant(const):
 | 
				
			||||||
        self.check_constant(f1, Ellipsis)
 | 
					        self.check_constant(f1, Ellipsis)
 | 
				
			||||||
        self.assertEqual(repr(f1()), repr(Ellipsis))
 | 
					        self.assertEqual(repr(f1()), repr(Ellipsis))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Merge constants in tuple or frozenset
 | 
				
			||||||
 | 
					        f1, f2 = lambda: "not a name", lambda: ("not a name",)
 | 
				
			||||||
 | 
					        f3 = lambda x: x in {("not a name",)}
 | 
				
			||||||
 | 
					        self.assertIs(f1.__code__.co_consts[1],
 | 
				
			||||||
 | 
					                      f2.__code__.co_consts[1][0])
 | 
				
			||||||
 | 
					        self.assertIs(next(iter(f3.__code__.co_consts[1])),
 | 
				
			||||||
 | 
					                      f2.__code__.co_consts[1])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # {0} is converted to a constant frozenset({0}) by the peephole
 | 
					        # {0} is converted to a constant frozenset({0}) by the peephole
 | 
				
			||||||
        # optimizer
 | 
					        # optimizer
 | 
				
			||||||
        f1, f2 = lambda x: x in {0}, lambda x: x in {0}
 | 
					        f1, f2 = lambda x: x in {0}, lambda x: x in {0}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1208,14 +1208,18 @@ merge_consts_recursive(struct compiler *c, PyObject *o)
 | 
				
			||||||
    // t is borrowed reference
 | 
					    // t is borrowed reference
 | 
				
			||||||
    PyObject *t = PyDict_SetDefault(c->c_const_cache, key, key);
 | 
					    PyObject *t = PyDict_SetDefault(c->c_const_cache, key, key);
 | 
				
			||||||
    if (t != key) {
 | 
					    if (t != key) {
 | 
				
			||||||
 | 
					        // o is registered in c_const_cache.  Just use it.
 | 
				
			||||||
        Py_INCREF(t);
 | 
					        Py_INCREF(t);
 | 
				
			||||||
        Py_DECREF(key);
 | 
					        Py_DECREF(key);
 | 
				
			||||||
        return t;
 | 
					        return t;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // We registered o in c_const_cache.
 | 
				
			||||||
 | 
					    // When o is a tuple or frozenset, we want to merge it's
 | 
				
			||||||
 | 
					    // items too.
 | 
				
			||||||
    if (PyTuple_CheckExact(o)) {
 | 
					    if (PyTuple_CheckExact(o)) {
 | 
				
			||||||
        Py_ssize_t i, len = PyTuple_GET_SIZE(o);
 | 
					        Py_ssize_t len = PyTuple_GET_SIZE(o);
 | 
				
			||||||
        for (i = 0; i < len; i++) {
 | 
					        for (Py_ssize_t i = 0; i < len; i++) {
 | 
				
			||||||
            PyObject *item = PyTuple_GET_ITEM(o, i);
 | 
					            PyObject *item = PyTuple_GET_ITEM(o, i);
 | 
				
			||||||
            PyObject *u = merge_consts_recursive(c, item);
 | 
					            PyObject *u = merge_consts_recursive(c, item);
 | 
				
			||||||
            if (u == NULL) {
 | 
					            if (u == NULL) {
 | 
				
			||||||
| 
						 | 
					@ -1240,6 +1244,57 @@ merge_consts_recursive(struct compiler *c, PyObject *o)
 | 
				
			||||||
            Py_DECREF(u);
 | 
					            Py_DECREF(u);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    else if (PyFrozenSet_CheckExact(o)) {
 | 
				
			||||||
 | 
					        // *key* is tuple. And it's first item is frozenset of
 | 
				
			||||||
 | 
					        // constant keys.
 | 
				
			||||||
 | 
					        // See _PyCode_ConstantKey() for detail.
 | 
				
			||||||
 | 
					        assert(PyTuple_CheckExact(key));
 | 
				
			||||||
 | 
					        assert(PyTuple_GET_SIZE(key) == 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Py_ssize_t len = PySet_GET_SIZE(o);
 | 
				
			||||||
 | 
					        if (len == 0) {  // empty frozenset should not be re-created.
 | 
				
			||||||
 | 
					            return key;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        PyObject *tuple = PyTuple_New(len);
 | 
				
			||||||
 | 
					        if (tuple == NULL) {
 | 
				
			||||||
 | 
					            Py_DECREF(key);
 | 
				
			||||||
 | 
					            return NULL;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        Py_ssize_t i = 0, pos = 0;
 | 
				
			||||||
 | 
					        PyObject *item;
 | 
				
			||||||
 | 
					        Py_hash_t hash;
 | 
				
			||||||
 | 
					        while (_PySet_NextEntry(o, &pos, &item, &hash)) {
 | 
				
			||||||
 | 
					            PyObject *k = merge_consts_recursive(c, item);
 | 
				
			||||||
 | 
					            if (k == NULL) {
 | 
				
			||||||
 | 
					                Py_DECREF(tuple);
 | 
				
			||||||
 | 
					                Py_DECREF(key);
 | 
				
			||||||
 | 
					                return NULL;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            PyObject *u;
 | 
				
			||||||
 | 
					            if (PyTuple_CheckExact(k)) {
 | 
				
			||||||
 | 
					                u = PyTuple_GET_ITEM(k, 1);
 | 
				
			||||||
 | 
					                Py_INCREF(u);
 | 
				
			||||||
 | 
					                Py_DECREF(k);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else {
 | 
				
			||||||
 | 
					                u = k;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            PyTuple_SET_ITEM(tuple, i, u);  // Steals reference of u.
 | 
				
			||||||
 | 
					            i++;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Instead of rewriting o, we create new frozenset and embed in the
 | 
				
			||||||
 | 
					        // key tuple.  Caller should get merged frozenset from the key tuple.
 | 
				
			||||||
 | 
					        PyObject *new = PyFrozenSet_New(tuple);
 | 
				
			||||||
 | 
					        Py_DECREF(tuple);
 | 
				
			||||||
 | 
					        if (new == NULL) {
 | 
				
			||||||
 | 
					            Py_DECREF(key);
 | 
				
			||||||
 | 
					            return NULL;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        assert(PyTuple_GET_ITEM(key, 1) == o);
 | 
				
			||||||
 | 
					        Py_DECREF(o);
 | 
				
			||||||
 | 
					        PyTuple_SET_ITEM(key, 1, new);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return key;
 | 
					    return key;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue