[pypy-commit] pypy py3.6-wordcode: also emit BUILD_CONST_KEY_MAP for regular dicts (the implementation could be faster, but later)
cfbolz
pypy.commits at gmail.com
Mon May 21 08:34:57 EDT 2018
Author: Carl Friedrich Bolz-Tereick <cfbolz at gmx.de>
Branch: py3.6-wordcode
Changeset: r94624:761a52b54b30
Date: 2018-05-21 14:09 +0200
http://bitbucket.org/pypy/pypy/changeset/761a52b54b30/
Log: also emit BUILD_CONST_KEY_MAP for regular dicts (the implementation
could be faster, but later)
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
@@ -1296,28 +1296,46 @@
containers = 0
elements = 0
is_unpacking = False
+ all_constant_keys_w = None
if d.values:
+ if len(d.keys) < 0xffff:
+ all_constant_keys_w = []
+ for key in d.keys:
+ if key is None or key.as_constant() is None:
+ all_constant_keys_w = None
+ break
+ else:
+ all_constant_keys_w.append(key.as_constant())
for i in range(len(d.values)):
key = d.keys[i]
is_unpacking = key is None
if elements == 0xFFFF or (elements and is_unpacking):
+ assert all_constant_keys_w is None
self.emit_op_arg(ops.BUILD_MAP, elements)
containers += 1
elements = 0
if is_unpacking:
+ assert all_constant_keys_w is None
d.values[i].walkabout(self)
containers += 1
else:
- key.walkabout(self)
+ if not all_constant_keys_w:
+ key.walkabout(self)
d.values[i].walkabout(self)
elements += 1
if elements or containers == 0:
- self.emit_op_arg(ops.BUILD_MAP, elements)
- containers += 1
+ if all_constant_keys_w:
+ w_tup = self.space.newtuple(all_constant_keys_w)
+ self.load_const(w_tup)
+ self.emit_op_arg(ops.BUILD_CONST_KEY_MAP, elements)
+ else:
+ self.emit_op_arg(ops.BUILD_MAP, elements)
+ containers += 1
# If there is more than one dict, they need to be merged into
# a new dict. If there is one dict and it's an unpacking, then
#it needs to be copied into a new dict.
while containers > 1 or is_unpacking:
+ assert all_constant_keys_w is None
oparg = min(containers, 255)
self.emit_op_arg(ops.BUILD_MAP_UNPACK, oparg)
containers -= (oparg - 1)
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
@@ -1491,3 +1491,18 @@
del []
"""
generate_function_code(source, self.space)
+
+ def test_make_constant_map(self):
+ source = """def f():
+ return {"A": 1, "b": 2}
+ """
+ counts = self.count_instructions(source)
+ assert ops.BUILD_MAP not in counts
+ source = """def f():
+ return {"a": 1, "b": {}, 1: {"a": x}}
+ """
+ counts = self.count_instructions(source)
+ assert counts[ops.BUILD_MAP] == 1 # the empty dict
+ assert counts[ops.BUILD_CONST_KEY_MAP] == 2
+
+
diff --git a/pypy/interpreter/test/test_pycode.py b/pypy/interpreter/test/test_pycode.py
--- a/pypy/interpreter/test/test_pycode.py
+++ b/pypy/interpreter/test/test_pycode.py
@@ -14,6 +14,6 @@
finally:
sys.stdout = stdout
print '>>>\n' + output + '\n<<<'
- assert ' 1 (7)' in output
+ assert ' 0 (7)' in output
assert ' 4 (None)' in output
assert ' 16 RETURN_VALUE' in output
More information about the pypy-commit
mailing list