diff -r 9f7d16266928 Python/compile.c --- a/Python/compile.c Tue Jan 17 03:46:13 2017 +0100 +++ b/Python/compile.c Sat Jan 21 12:27:26 2017 +0900 @@ -158,12 +158,13 @@ int c_interactive; /* true if in interactive mode */ int c_nestlevel; struct compiler_unit *u; /* compiler state for current block */ PyObject *c_stack; /* Python list holding compiler_unit ptrs */ PyArena *c_arena; /* pointer to memory allocation arena */ + PyObject *c_tuplecache; /* dict used for merge same tuples */ }; static int compiler_enter_scope(struct compiler *, identifier, int, void *, int); static void compiler_free(struct compiler *); static basicblock *compiler_new_block(struct compiler *); static int compiler_next_instr(struct compiler *, basicblock *); @@ -317,12 +318,15 @@ Py_INCREF(filename); c.c_filename = filename; c.c_arena = arena; c.c_future = PyFuture_FromASTObject(mod, filename); if (c.c_future == NULL) goto finally; + c.c_tuplecache = PyDict_New(); + if (c.c_tuplecache == NULL) + goto finally; if (!flags) { local_flags.cf_flags = 0; flags = &local_flags; } merged = c.c_future->ff_features | flags->cf_flags; c.c_future->ff_features = merged; @@ -380,12 +384,13 @@ compiler_free(struct compiler *c) { if (c->c_st) PySymtable_Free(c->c_st); if (c->c_future) PyObject_Free(c->c_future); + Py_XDECREF(c->c_tuplecache); Py_XDECREF(c->c_filename); Py_DECREF(c->c_stack); } static PyObject * list2dict(PyObject *list) @@ -5227,12 +5232,43 @@ flags |= CO_NOFREE; } return flags; } +static PyObject * +merge_tuples(PyObject *cache, PyObject *tuple) +{ + if (tuple == NULL) + return NULL; + + Py_ssize_t n = PyTuple_GET_SIZE(tuple); + + // Check tuple is simple and safe. + // Note that integer and float are not safe, because 1 == 1.0 == True. + for (Py_ssize_t i=0; i < n; i++) { + PyObject *o = PyTuple_GET_ITEM(tuple, i); + if (o != Py_None && o != Py_True && o != Py_False && + !PyUnicode_CheckExact(o) && + !PyBytes_CheckExact(o)) { + return tuple; + } + } + + PyObject *t = PyDict_SetDefault(cache, tuple, tuple); + if (t == NULL) { // Unhashable type is in consts? + PyErr_Clear(); + return tuple; + } + if (t != tuple) { + Py_INCREF(t); + Py_DECREF(tuple); + } + return t; +} + static PyCodeObject * makecode(struct compiler *c, struct assembler *a) { PyObject *tmp; PyCodeObject *co = NULL; PyObject *consts = NULL; @@ -5280,12 +5316,18 @@ tmp = PyList_AsTuple(consts); /* PyCode_New requires a tuple */ if (!tmp) goto error; Py_DECREF(consts); consts = tmp; + consts = merge_tuples(c->c_tuplecache, consts); + names = merge_tuples(c->c_tuplecache, names); + varnames = merge_tuples(c->c_tuplecache, varnames); + freevars = merge_tuples(c->c_tuplecache, freevars); + cellvars = merge_tuples(c->c_tuplecache, cellvars); + argcount = Py_SAFE_DOWNCAST(c->u->u_argcount, Py_ssize_t, int); kwonlyargcount = Py_SAFE_DOWNCAST(c->u->u_kwonlyargcount, Py_ssize_t, int); co = PyCode_New(argcount, kwonlyargcount, nlocals_int, stackdepth(c), flags, bytecode, consts, names, varnames, freevars, cellvars,