Author: Carl Friedrich Bolz-Tereick <cfb...@gmx.de>
Branch: py3.6
Changeset: r96076:b7b3ef736a84
Date: 2019-02-18 21:45 +0100
http://bitbucket.org/pypy/pypy/changeset/b7b3ef736a84/

Log:    make sure __import__ is not stored in a celldict cell, otherwise
        local imports are really slow

diff --git a/pypy/interpreter/mixedmodule.py b/pypy/interpreter/mixedmodule.py
--- a/pypy/interpreter/mixedmodule.py
+++ b/pypy/interpreter/mixedmodule.py
@@ -197,6 +197,17 @@
     def get__doc__(cls, space):
         return space.newtext_or_none(cls.__doc__)
 
+    def setdictvalue_dont_introduce_cell(self, name, w_value):
+        """ inofficial interface on MixedModules to override an existing value
+        in the module but without introducing a cell (in the sense of
+        celldict.py) for it. Should be used sparingly, since it will trigger a
+        JIT recompile of all code that uses this module."""
+        from pypy.objspace.std.celldict import setdictvalue_dont_introduce_cell
+        # first do a regular setdictvalue to force the lazy loading
+        self.setdictvalue(self.space, name, w_value)
+        # then ask cell dict to remove the cell, and store the value directly
+        setdictvalue_dont_introduce_cell(self, self.space, name, w_value)
+
 
 @not_rpython
 def getinterpevalloader(pkgroot, spec):
diff --git a/pypy/module/_frozen_importlib/__init__.py 
b/pypy/module/_frozen_importlib/__init__.py
--- a/pypy/module/_frozen_importlib/__init__.py
+++ b/pypy/module/_frozen_importlib/__init__.py
@@ -80,7 +80,9 @@
         """Copy our __import__ to builtins."""
         if not we_are_translated():
             self.startup_at_translation_time_only(space)
-        self.space.builtin.setdictvalue(space, '__import__', self.w_import)
+        # use special module api to prevent a cell from being introduced
+        self.space.builtin.setdictvalue_dont_introduce_cell(
+            '__import__', self.w_import)
 
     def startup_at_translation_time_only(self, space):
         # Issue #2834
diff --git a/pypy/objspace/std/celldict.py b/pypy/objspace/std/celldict.py
--- a/pypy/objspace/std/celldict.py
+++ b/pypy/objspace/std/celldict.py
@@ -186,5 +186,17 @@
     def wrapvalue(space, value):
         return unwrap_cell(space, value)
 
+def setdictvalue_dont_introduce_cell(w_obj, space, name, w_value):
+    from pypy.objspace.std.dictmultiobject import W_DictMultiObject
+    w_dict = w_obj.getdict(space)
+    if isinstance(w_dict, W_DictMultiObject):
+        strategy = w_dict.get_strategy()
+        if isinstance(strategy, ModuleDictStrategy):
+            dict_w = strategy.unerase(w_dict.dstorage)
+            strategy.mutated()
+            dict_w[name] = w_value
+            return
+    w_obj.setdictvalue(space, name, w_value)
+
 
 create_iterator_classes(ModuleDictStrategy)
diff --git a/pypy/objspace/std/test/test_celldict.py 
b/pypy/objspace/std/test/test_celldict.py
--- a/pypy/objspace/std/test/test_celldict.py
+++ b/pypy/objspace/std/test/test_celldict.py
@@ -58,6 +58,31 @@
         v3 = strategy.version
         assert v2 is v3
 
+    def test_module_no_cell_interface(self):
+        from pypy.interpreter.module import Module
+        w_mod = Module(space, None)
+        assert isinstance(w_mod.w_dict, W_ModuleDictObject)
+
+        key = "a"
+        value1 = object()
+        w_mod.setdictvalue(space, key, value1)
+
+        strategy = w_mod.w_dict.get_strategy()
+        storage = strategy.unerase(w_mod.w_dict.dstorage)
+        assert storage["a"] is value1
+
+        value2 = object()
+        w_mod.setdictvalue_dont_introduce_cell(key, value2)
+        assert storage["a"] is value2
+
+    def test___import__not_a_cell(self):
+        # _frozen_importlib overrides __import__, which used to introduce a
+        # cell
+        w_dict = self.space.builtin.w_dict
+        storage = w_dict.get_strategy().unerase(w_dict.dstorage)
+        assert "Cell" not in repr(storage['__import__'])
+
+
 class AppTestModuleDict(object):
 
     def setup_class(cls):
@@ -173,3 +198,4 @@
         d[o] = 'baz'
         assert set(d) == set(['foo', '&#955;', o])
         assert "ObjectDictStrategy" in __pypy__.internal_repr(d)
+
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to