[Python-checkins] cpython (2.7): Issue #27942: String constants now interned recursively in tuples and

serhiy.storchaka python-checkins at python.org
Fri Sep 30 03:40:00 EDT 2016


https://hg.python.org/cpython/rev/7cea3bf44acb
changeset:   104178:7cea3bf44acb
branch:      2.7
parent:      104171:5f788ad057ca
user:        Serhiy Storchaka <storchaka at gmail.com>
date:        Fri Sep 30 10:38:08 2016 +0300
summary:
  Issue #27942: String constants now interned recursively in tuples and frozensets.

files:
  Lib/test/test_code.py |  33 ++++++++++++++++++-
  Misc/NEWS             |   2 +
  Objects/codeobject.c  |  54 +++++++++++++++++++++++++-----
  3 files changed, 79 insertions(+), 10 deletions(-)


diff --git a/Lib/test/test_code.py b/Lib/test/test_code.py
--- a/Lib/test/test_code.py
+++ b/Lib/test/test_code.py
@@ -112,6 +112,37 @@
         self.assertEqual(co.co_name, "funcname")
         self.assertEqual(co.co_firstlineno, 15)
 
+class CodeConstsTest(unittest.TestCase):
+
+    def find_const(self, consts, value):
+        for v in consts:
+            if v == value:
+                return v
+        self.assertIn(value, consts)  # rises an exception
+        self.fail('Should be never reached')
+
+    def assertIsInterned(self, s):
+        if s is not intern(s):
+            self.fail('String %r is not interned' % (s,))
+
+    @cpython_only
+    def test_interned_string(self):
+        co = compile('res = "str_value"', '?', 'exec')
+        v = self.find_const(co.co_consts, 'str_value')
+        self.assertIsInterned(v)
+
+    @cpython_only
+    def test_interned_string_in_tuple(self):
+        co = compile('res = ("str_value",)', '?', 'exec')
+        v = self.find_const(co.co_consts, ('str_value',))
+        self.assertIsInterned(v[0])
+
+    @cpython_only
+    def test_interned_string_default(self):
+        def f(a='str_value'):
+            return a
+        self.assertIsInterned(f())
+
 
 class CodeWeakRefTest(unittest.TestCase):
 
@@ -141,7 +172,7 @@
 def test_main(verbose=None):
     from test import test_code
     run_doctest(test_code, verbose)
-    run_unittest(CodeTest, CodeWeakRefTest)
+    run_unittest(CodeTest, CodeConstsTest, CodeWeakRefTest)
 
 
 if __name__ == "__main__":
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,8 @@
 Core and Builtins
 -----------------
 
+- Issue #27942: String constants now interned recursively in tuples and frozensets.
+
 - Issue #15578: Correctly incref the parent module while importing.
 
 - Issue #26307: The profile-opt build now applys PGO to the built-in modules.
diff --git a/Objects/codeobject.c b/Objects/codeobject.c
--- a/Objects/codeobject.c
+++ b/Objects/codeobject.c
@@ -39,6 +39,50 @@
     }
 }
 
+/* Intern selected string constants */
+static int
+intern_string_constants(PyObject *tuple)
+{
+    int modified = 0;
+    Py_ssize_t i;
+
+    for (i = PyTuple_GET_SIZE(tuple); --i >= 0; ) {
+        PyObject *v = PyTuple_GET_ITEM(tuple, i);
+        if (PyString_CheckExact(v)) {
+            if (all_name_chars((unsigned char *)PyString_AS_STRING(v))) {
+                PyObject *w = v;
+                PyString_InternInPlace(&v);
+                if (w != v) {
+                    PyTuple_SET_ITEM(tuple, i, v);
+                    modified = 1;
+                }
+            }
+        }
+        else if (PyTuple_CheckExact(v)) {
+            intern_string_constants(v);
+        }
+        else if (PyFrozenSet_CheckExact(v)) {
+            PyObject *tmp = PySequence_Tuple(v);
+            if (tmp == NULL) {
+                PyErr_Clear();
+                continue;
+            }
+            if (intern_string_constants(tmp)) {
+                v = PyFrozenSet_New(tmp);
+                if (v == NULL) {
+                    PyErr_Clear();
+                }
+                else {
+                    PyTuple_SET_ITEM(tuple, i, v);
+                    modified = 1;
+                }
+            }
+            Py_DECREF(tmp);
+        }
+    }
+    return modified;
+}
+
 
 PyCodeObject *
 PyCode_New(int argcount, int nlocals, int stacksize, int flags,
@@ -68,15 +112,7 @@
     intern_strings(varnames);
     intern_strings(freevars);
     intern_strings(cellvars);
-    /* Intern selected string constants */
-    for (i = PyTuple_Size(consts); --i >= 0; ) {
-        PyObject *v = PyTuple_GetItem(consts, i);
-        if (!PyString_Check(v))
-            continue;
-        if (!all_name_chars((unsigned char *)PyString_AS_STRING(v)))
-            continue;
-        PyString_InternInPlace(&PyTuple_GET_ITEM(consts, i));
-    }
+    intern_string_constants(consts);
     co = PyObject_NEW(PyCodeObject, &PyCode_Type);
     if (co != NULL) {
         co->co_argcount = argcount;

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list