[pypy-commit] pypy py3.6: construct huge dicts in constant stack space as well

cfbolz pypy.commits at gmail.com
Thu Mar 28 06:22:59 EDT 2019


Author: Carl Friedrich Bolz-Tereick <cfbolz at gmx.de>
Branch: py3.6
Changeset: r96374:5ea8098b2f2c
Date: 2019-03-28 11:22 +0100
http://bitbucket.org/pypy/pypy/changeset/5ea8098b2f2c/

Log:	construct huge dicts in constant stack space as well

diff --git a/pypy/interpreter/astcompiler/codegen.py b/pypy/interpreter/astcompiler/codegen.py
--- a/pypy/interpreter/astcompiler/codegen.py
+++ b/pypy/interpreter/astcompiler/codegen.py
@@ -1322,6 +1322,21 @@
         is_unpacking = False
         all_constant_keys_w = None
         if d.values:
+            unpacking_anywhere = False
+            for key in d.keys:
+                if key is None:
+                    unpacking_anywhere = True
+                    break
+            if not unpacking_anywhere and len(d.keys) > MAX_STACKDEPTH_CONTAINERS:
+                # do it in a small amount of stack
+                self.emit_op_arg(ops.BUILD_MAP, 0)
+                for i in range(len(d.values)):
+                    d.values[i].walkabout(self)
+                    key = d.keys[i]
+                    assert key is not None
+                    key.walkabout(self)
+                    self.emit_op_arg(ops.MAP_ADD, 1)
+                return
             if len(d.keys) < 0xffff:
                 all_constant_keys_w = []
                 for key in d.keys:
diff --git a/pypy/interpreter/astcompiler/test/test_compiler.py b/pypy/interpreter/astcompiler/test/test_compiler.py
--- a/pypy/interpreter/astcompiler/test/test_compiler.py
+++ b/pypy/interpreter/astcompiler/test/test_compiler.py
@@ -1593,13 +1593,18 @@
         assert self.space.unwrap(w_res) == tuple(range(200))
 
     def test_list(self):
-        source = "a = [" + ",".join([str(i) for i in range(200)]) + "]\n"
+        source = "[" + ",".join([str(i) for i in range(200)]) + "]\n"
         w_res = self.run_and_check_stacksize(source)
         assert self.space.unwrap(w_res) == range(200)
 
     def test_set(self):
-        source = "a = {" + ",".join([str(i) for i in range(200)]) + "}\n"
+        source = "{" + ",".join([str(i) for i in range(200)]) + "}\n"
         w_res = self.run_and_check_stacksize(source)
         space = self.space
         assert [space.int_w(w_x)
                     for w_x in space.unpackiterable(w_res)] == range(200)
+
+    def test_dict(self):
+        source = "{" + ",".join(['%s: None' % (i, ) for i in range(200)]) + "}\n"
+        w_res = self.run_and_check_stacksize(source)
+        assert self.space.unwrap(w_res) == dict.fromkeys(range(200))


More information about the pypy-commit mailing list