Author: Carl Friedrich Bolz-Tereick <[email protected]>
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', 'λ', o])
assert "ObjectDictStrategy" in __pypy__.internal_repr(d)
+
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit