Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(5)

Unified Diff: Objects/codeobject.c

Issue 25843: lambdas on the same line may incorrectly share code objects
Patch Set: Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
--- a/Objects/codeobject.c Wed Jan 20 12:16:21 2016 +0100
+++ b/Objects/codeobject.c Wed Jan 20 14:59:07 2016 +0100
@@ -409,11 +409,130 @@ code_repr(PyCodeObject *co)
}
}
+PyObject*
+_PyCode_ConstantKey(PyObject *op)
+{
+ PyObject *key;
+
+ /* necessary to make sure types aren't coerced (e.g., float and complex)
+ * _and_ to distinguish 0.0 from -0.0 e.g. on IEEE platforms */
+ if (PyFloat_Check(op)) {
storchaka 2016/01/20 19:19:01 See my comments to previous patches.
+ double d = PyFloat_AS_DOUBLE(op);
+ /* all we need is to make the tuple different in either the 0.0
+ * or -0.0 case from all others, just to avoid the "coercion".
+ */
+ if (d == 0.0 && copysign(1.0, d) < 0.0)
+ key = PyTuple_Pack(3, op, Py_TYPE(op), Py_None);
+ else
+ key = PyTuple_Pack(2, op, Py_TYPE(op));
+ }
+ else if (PyComplex_Check(op)) {
+ Py_complex z;
+ int real_negzero, imag_negzero;
+ /* For the complex case we must make complex(x, 0.)
+ different from complex(x, -0.) and complex(0., y)
+ different from complex(-0., y), for any x and y.
+ All four complex zeros must be distinguished.*/
+ z = PyComplex_AsCComplex(op);
+ real_negzero = z.real == 0.0 && copysign(1.0, z.real) < 0.0;
+ imag_negzero = z.imag == 0.0 && copysign(1.0, z.imag) < 0.0;
+ if (real_negzero && imag_negzero) {
+ key = PyTuple_Pack(5, op, Py_TYPE(op),
storchaka 2016/01/20 19:19:01 See my comments to previous patches.
+ Py_None, Py_None, Py_None);
+ }
+ else if (imag_negzero) {
+ key = PyTuple_Pack(4, op, Py_TYPE(op), Py_None, Py_None);
+ }
+ else if (real_negzero) {
+ key = PyTuple_Pack(3, op, Py_TYPE(op), Py_None);
+ }
+ else {
+ key = PyTuple_Pack(2, op, Py_TYPE(op));
+ }
+ }
+ else if (PyTuple_Check(op)) {
+ Py_ssize_t i, len;
+ PyObject *keys;
+
+ len = PyTuple_GET_SIZE(op);
+ keys = PyTuple_New(len);
+ if (keys == NULL)
+ return NULL;
+
+ for (i=0; i < len; i++) {
+ PyObject *item, *item_key;
+
+ item = PyTuple_GET_ITEM(op, i);
+ item_key = _PyCode_ConstantKey(item);
+ if (item_key == NULL) {
+ Py_DECREF(keys);
+ return NULL;
+ }
+
+ PyTuple_SET_ITEM(keys, i, item_key);
+ }
+
+ key = PyTuple_Pack(2, op, keys);
+ }
+ else if (PyAnySet_CheckExact(op)) {
storchaka 2016/01/20 19:19:01 Accepts set.
+ Py_ssize_t pos = 0;
+ PyObject *item;
+ Py_hash_t hash;
+ Py_ssize_t i, len;
+ PyObject *keys;
+
+ len = PySet_GET_SIZE(op);
+ keys = PyTuple_New(len);
+ if (keys == NULL)
+ return NULL;
+
+ i = 0;
+ while (_PySet_NextEntry(op, &pos, &item, &hash)) {
+ PyObject *item_key;
+
+ item_key = _PyCode_ConstantKey(item);
+ if (item_key == NULL) {
+ Py_DECREF(keys);
+ return NULL;
+ }
+
+ PyTuple_SET_ITEM(keys, i, item_key);
+ i++;
+ if (i >= len) {
+ /* set size changed during iteration, ignore */
storchaka 2016/01/20 19:19:01 See my comments to previous patches. I think it is
+ break;
+ }
+ }
+ return keys;
storchaka 2016/01/20 19:19:01 See my comments to previous patches.
+ }
+ /* Py_None and Py_Ellipsis are singleton */
+ else if (op == Py_None || op == Py_Ellipsis
+ || PyLong_CheckExact(op)
+ || PyBool_Check(op)
+ || PyBytes_CheckExact(op)
+ || PyUnicode_CheckExact(op)
+ /* code_richcompare() uses _PyCode_ConstantKey() internally */
+ || PyCode_Check(op)) {
+ key = PyTuple_Pack(2, op, Py_TYPE(op));
+ }
+ else {
+ /* for other types, use the identifier to *not* merge them
+ * even if they are equal */
+ PyObject *obj_id = PyLong_FromVoidPtr(op);
+ if (obj_id == NULL)
+ return NULL;
+ key = PyTuple_Pack(3, op, Py_TYPE(op), obj_id);
+ Py_DECREF(obj_id);
+ }
+ return key;
+}
+
static PyObject *
code_richcompare(PyObject *self, PyObject *other, int op)
{
PyCodeObject *co, *cp;
int eq;
+ PyObject *consts1, *consts2;
PyObject *res;
if ((op != Py_EQ && op != Py_NE) ||
@@ -439,8 +558,21 @@ code_richcompare(PyObject *self, PyObjec
if (!eq) goto unequal;
eq = PyObject_RichCompareBool(co->co_code, cp->co_code, Py_EQ);
if (eq <= 0) goto unequal;
- eq = PyObject_RichCompareBool(co->co_consts, cp->co_consts, Py_EQ);
+
+ /* compare constants */
+ consts1 = _PyCode_ConstantKey(co->co_consts);
+ if (!consts1)
+ return NULL;
+ consts2 = _PyCode_ConstantKey(cp->co_consts);
+ if (!consts2) {
+ Py_DECREF(consts1);
+ return NULL;
+ }
+ eq = PyObject_RichCompareBool(consts1, consts2, Py_EQ);
+ Py_DECREF(consts1);
+ Py_DECREF(consts2);
if (eq <= 0) goto unequal;
+
eq = PyObject_RichCompareBool(co->co_names, cp->co_names, Py_EQ);
if (eq <= 0) goto unequal;
eq = PyObject_RichCompareBool(co->co_varnames, cp->co_varnames, Py_EQ);
« Lib/test/test_compile.py ('K') | « Lib/test/test_compile.py ('k') | Python/compile.c » ('j') | no next file with comments »

RSS Feeds Recent Issues | This issue
This is Rietveld 894c83f36cb7+