[pypy-svn] r62773 - in pypy/branch/speedup-globals/pypy: config interpreter objspace objspace/fake objspace/std objspace/std/test

cfbolz at codespeak.net cfbolz at codespeak.net
Mon Mar 9 19:02:51 CET 2009


Author: cfbolz
Date: Mon Mar  9 19:02:50 2009
New Revision: 62773

Modified:
   pypy/branch/speedup-globals/pypy/config/pypyoption.py
   pypy/branch/speedup-globals/pypy/interpreter/module.py
   pypy/branch/speedup-globals/pypy/objspace/fake/objspace.py
   pypy/branch/speedup-globals/pypy/objspace/reflective.py
   pypy/branch/speedup-globals/pypy/objspace/std/dictmultiobject.py
   pypy/branch/speedup-globals/pypy/objspace/std/objspace.py
   pypy/branch/speedup-globals/pypy/objspace/std/test/test_dictmultiobject.py
   pypy/branch/speedup-globals/pypy/objspace/std/test/test_dictobject.py
Log:
First step to make global lookups faster: Introduce a special dict
implementation for modules, where every value in the RPython-level dict is a
cell that contains the real value. As long as the "valid" flag on such a cell is
set, it is safe to store the cell somewhere else.


Modified: pypy/branch/speedup-globals/pypy/config/pypyoption.py
==============================================================================
--- pypy/branch/speedup-globals/pypy/config/pypyoption.py	(original)
+++ pypy/branch/speedup-globals/pypy/config/pypyoption.py	Mon Mar  9 19:02:50 2009
@@ -222,6 +222,13 @@
                    "use dictionaries optimized for flexibility",
                    default=False),
 
+        BoolOption("withcelldict",
+                   "use dictionaries that are opimized for being used as module dicts",
+                   default=False,
+                   requires=[("objspace.std.withmultidict", True),
+                             ("objspace.opcodes.CALL_LIKELY_BUILTIN", False),
+                             ("objspace.honor__builtins__", False)]),
+
         BoolOption("withsharingdict",
                    "use dictionaries that share the keys part",
                    default=False,

Modified: pypy/branch/speedup-globals/pypy/interpreter/module.py
==============================================================================
--- pypy/branch/speedup-globals/pypy/interpreter/module.py	(original)
+++ pypy/branch/speedup-globals/pypy/interpreter/module.py	Mon Mar  9 19:02:50 2009
@@ -11,7 +11,7 @@
     def __init__(self, space, w_name, w_dict=None):
         self.space = space
         if w_dict is None: 
-            w_dict = space.newdict(track_builtin_shadowing=True)
+            w_dict = space.newdict(module=True)
         self.w_dict = w_dict 
         self.w_name = w_name 
         if w_name is not None:

Modified: pypy/branch/speedup-globals/pypy/objspace/fake/objspace.py
==============================================================================
--- pypy/branch/speedup-globals/pypy/objspace/fake/objspace.py	(original)
+++ pypy/branch/speedup-globals/pypy/objspace/fake/objspace.py	Mon Mar  9 19:02:50 2009
@@ -93,7 +93,7 @@
     newint            = make_dummy()
     newlong           = make_dummy()
     newfloat          = make_dummy()
-    def newdict(self, track_builtin_shadowing=False):
+    def newdict(self, module=False):
         return self.newfloat()
     newlist           = make_dummy()
     emptylist         = make_dummy()

Modified: pypy/branch/speedup-globals/pypy/objspace/reflective.py
==============================================================================
--- pypy/branch/speedup-globals/pypy/objspace/reflective.py	(original)
+++ pypy/branch/speedup-globals/pypy/objspace/reflective.py	Mon Mar  9 19:02:50 2009
@@ -137,8 +137,8 @@
         return None
 
     if opname == "newdict": # grr grr kwargs
-        def fn(track_builtin_shadowing=False):
-            w_obj = parentfn(track_builtin_shadowing)
+        def fn(module=False):
+            w_obj = parentfn(module)
             w_newobj = user_hook(w_obj)
             if w_newobj is not None:
                 return w_newobj

Modified: pypy/branch/speedup-globals/pypy/objspace/std/dictmultiobject.py
==============================================================================
--- pypy/branch/speedup-globals/pypy/objspace/std/dictmultiobject.py	(original)
+++ pypy/branch/speedup-globals/pypy/objspace/std/dictmultiobject.py	Mon Mar  9 19:02:50 2009
@@ -865,6 +865,134 @@
         else:
             return None
 
+class ModuleCell(object):
+    def __init__(self):
+        self.w_value = None
+        self.valid = True
+
+    def invalidate(self):
+        self.w_value = None
+        self.valid = False
+
+class ModuleDictImplementation(DictImplementation):
+    def __init__(self, space):
+        self.space = space
+        self.content = {}
+
+    def getcell(self, key, make_new=True):
+        try:
+            return self.content[key]
+        except KeyError:
+            if not make_new:
+                raise
+            result = self.content[key] = ModuleCell()
+            return result
+
+    def setitem(self, w_key, w_value):
+        space = self.space
+        if space.is_w(space.type(w_key), space.w_str):
+            return self.setitem_str(w_key, w_value)
+        else:
+            return self._as_rdict().setitem(w_key, w_value)
+
+    def setitem_str(self, w_key, w_value, shadows_type=True):
+        self.getcell(self.space.str_w(w_key)).w_value = w_value
+        return self
+
+    def delitem(self, w_key):
+        space = self.space
+        w_key_type = space.type(w_key)
+        if space.is_w(w_key_type, space.w_str):
+            key = space.str_w(w_key)
+            cell = self.getcell(key, False)
+            cell.invalidate()
+            del self.content[key]
+            return self
+        elif _is_sane_hash(space, w_key_type):
+            raise KeyError
+        else:
+            return self._as_rdict().delitem(w_key)
+        
+    def length(self):
+        return len(self.content)
+
+    def get(self, w_lookup):
+        space = self.space
+        w_lookup_type = space.type(w_lookup)
+        if space.is_w(w_lookup_type, space.w_str):
+            try:
+                return self.getcell(space.str_w(w_lookup), False).w_value
+            except KeyError:
+                return None
+        elif _is_sane_hash(space, w_lookup_type):
+            return None
+        else:
+            return self._as_rdict().get(w_lookup)
+
+    def iteritems(self):
+        return ModuleDictItemIteratorImplementation(self.space, self)
+
+    def iterkeys(self):
+        return ModuleDictKeyIteratorImplementation(self.space, self)
+
+    def itervalues(self):
+        return ModuleDictValueIteratorImplementation(self.space, self)
+
+    def keys(self):
+        space = self.space
+        return [space.wrap(key) for key in self.content.iterkeys()]
+
+    def values(self):
+        return [cell.w_value for cell in self.content.itervalues()]
+
+    def items(self):
+        space = self.space
+        return [space.newtuple([space.wrap(key), cell.w_value])
+                    for (key, cell) in self.content.iteritems()]
+
+    def _as_rdict(self):
+        newimpl = self.space.DefaultDictImpl(self.space)
+        for k, cell in self.content.iteritems():
+            newimpl.setitem(self.space.wrap(k), cell.w_value)
+            cell.invalidate()
+        return newimpl
+
+# grrrrr. just a copy-paste from StrKeyIteratorImplementation above
+class ModuleDictKeyIteratorImplementation(IteratorImplementation):
+    def __init__(self, space, dictimplementation):
+        IteratorImplementation.__init__(self, space, dictimplementation)
+        self.iterator = dictimplementation.content.iterkeys()
+
+    def next_entry(self):
+        # note that this 'for' loop only runs once, at most
+        for key in self.iterator:
+            return self.space.wrap(key)
+        else:
+            return None
+
+class ModuleDictValueIteratorImplementation(IteratorImplementation):
+    def __init__(self, space, dictimplementation):
+        IteratorImplementation.__init__(self, space, dictimplementation)
+        self.iterator = dictimplementation.content.itervalues()
+
+    def next_entry(self):
+        # note that this 'for' loop only runs once, at most
+        for cell in self.iterator:
+            return cell.w_value
+        else:
+            return None
+
+class ModuleDictItemIteratorImplementation(IteratorImplementation):
+    def __init__(self, space, dictimplementation):
+        IteratorImplementation.__init__(self, space, dictimplementation)
+        self.iterator = dictimplementation.content.iteritems()
+
+    def next_entry(self):
+        # note that this 'for' loop only runs once, at most
+        for key, cell in self.iterator:
+            return self.space.newtuple([self.space.wrap(key), cell.w_value])
+        else:
+            return None
 
 import time, py
 
@@ -1038,8 +1166,10 @@
 class W_DictMultiObject(W_Object):
     from pypy.objspace.std.dicttype import dict_typedef as typedef
 
-    def __init__(w_self, space, wary=False, sharing=False):
-        if space.config.objspace.opcodes.CALL_LIKELY_BUILTIN and wary:
+    def __init__(w_self, space, wary=False, sharing=False, module=False):
+        if space.config.objspace.std.withcelldict and wary:
+            w_self.implementation = ModuleDictImplementation(space)
+        elif space.config.objspace.opcodes.CALL_LIKELY_BUILTIN and wary:
             w_self.implementation = WaryDictImplementation(space)
         elif space.config.objspace.std.withdictmeasurement:
             w_self.implementation = MeasuringDictImplementation(space)

Modified: pypy/branch/speedup-globals/pypy/objspace/std/objspace.py
==============================================================================
--- pypy/branch/speedup-globals/pypy/objspace/std/objspace.py	(original)
+++ pypy/branch/speedup-globals/pypy/objspace/std/objspace.py	Mon Mar  9 19:02:50 2009
@@ -580,8 +580,8 @@
             from pypy.objspace.std.listobject import W_ListObject
             return W_ListObject(list_w)
 
-    def newdict(self, track_builtin_shadowing=False):
-        if self.config.objspace.opcodes.CALL_LIKELY_BUILTIN and track_builtin_shadowing:
+    def newdict(self, module=False):
+        if self.config.objspace.std.withmultidict and module:
             from pypy.objspace.std.dictmultiobject import W_DictMultiObject
             return W_DictMultiObject(self, wary=True)
         return self.DictObjectCls(self)

Modified: pypy/branch/speedup-globals/pypy/objspace/std/test/test_dictmultiobject.py
==============================================================================
--- pypy/branch/speedup-globals/pypy/objspace/std/test/test_dictmultiobject.py	(original)
+++ pypy/branch/speedup-globals/pypy/objspace/std/test/test_dictmultiobject.py	Mon Mar  9 19:02:50 2009
@@ -2,7 +2,8 @@
 from pypy.objspace.std.dictmultiobject import \
      W_DictMultiObject, setitem__DictMulti_ANY_ANY, getitem__DictMulti_ANY, \
      EmptyDictImplementation, RDictImplementation, StrDictImplementation, \
-     SmallDictImplementation, SmallStrDictImplementation, MeasuringDictImplementation
+     SmallDictImplementation, SmallStrDictImplementation, MeasuringDictImplementation, \
+     ModuleDictImplementation
 from pypy.conftest import gettestobjspace
 from pypy.objspace.std.test import test_dictobject
 
@@ -58,6 +59,26 @@
         a.__dict__.items() == [("abc", 12)]
 
 
+class AppTestModuleDict(object):
+    def setup_class(cls):
+        cls.space = gettestobjspace(**{"objspace.std.withcelldict": True})
+        cls.w_impl_used = cls.space.appexec([], """():
+            import __pypy__
+            def impl_used(obj):
+                assert "ModuleDictImplementation" in __pypy__.internal_repr(obj)
+            return impl_used
+        """)
+
+
+    def test_check_module_uses_module_dict(self):
+        m = type(__builtins__)("abc")
+        self.impl_used(m.__dict__)
+
+    def test_key_not_there(self):
+        d = type(__builtins__)("abc").__dict__
+        raises(KeyError, "d['def']")
+
+
 
 class TestW_DictSmall(test_dictobject.TestW_DictObject):
     def setup_class(cls):
@@ -233,3 +254,15 @@
 
     def get_impl(self):
         return self.ImplementionClass(self.space, self.string, self.string2)
+
+class TestModuleDictImplementation(TestRDictImplementation):
+    ImplementionClass = ModuleDictImplementation
+    EmptyClass = ModuleDictImplementation
+
+class TestModuleDictImplementationWithBuiltinNames(TestRDictImplementation):
+    ImplementionClass = ModuleDictImplementation
+    EmptyClass = ModuleDictImplementation
+
+    string = "int"
+    string2 = "isinstance"
+

Modified: pypy/branch/speedup-globals/pypy/objspace/std/test/test_dictobject.py
==============================================================================
--- pypy/branch/speedup-globals/pypy/objspace/std/test/test_dictobject.py	(original)
+++ pypy/branch/speedup-globals/pypy/objspace/std/test/test_dictobject.py	Mon Mar  9 19:02:50 2009
@@ -489,6 +489,7 @@
 FakeSpace.config.objspace.std.withdictmeasurement = False
 FakeSpace.config.objspace.std.withsharingdict = False
 FakeSpace.config.objspace.std.withsmalldicts = False
+FakeSpace.config.objspace.std.withcelldict = False
 FakeSpace.config.objspace.opcodes = Config()
 FakeSpace.config.objspace.opcodes.CALL_LIKELY_BUILTIN = False
 



More information about the Pypy-commit mailing list