[pypy-svn] r78359 - in pypy/trunk/pypy: config config/test doc doc/config interpreter jit/codewriter jit/tl module/__builtin__ module/__builtin__/test module/pypyjit/test objspace objspace/std objspace/std/test

arigo at codespeak.net arigo at codespeak.net
Wed Oct 27 16:20:29 CEST 2010


Author: arigo
Date: Wed Oct 27 16:20:26 2010
New Revision: 78359

Added:
   pypy/trunk/pypy/objspace/std/test/test_methodcache.py
      - copied, changed from r78358, pypy/branch/cleanup-dict-impl/pypy/objspace/std/test/test_methodcache.py
Removed:
   pypy/trunk/pypy/doc/config/objspace.std.withinlineddict.txt
   pypy/trunk/pypy/doc/config/objspace.std.withshadowtracking.txt
   pypy/trunk/pypy/doc/config/objspace.std.withsharingdict.txt
   pypy/trunk/pypy/objspace/std/inlinedict.py
   pypy/trunk/pypy/objspace/std/sharingdict.py
   pypy/trunk/pypy/objspace/std/test/test_inlinedict.py
   pypy/trunk/pypy/objspace/std/test/test_shadowtracking.py
   pypy/trunk/pypy/objspace/std/test/test_sharingdict.py
Modified:
   pypy/trunk/pypy/config/pypyoption.py
   pypy/trunk/pypy/config/test/test_pypyoption.py
   pypy/trunk/pypy/doc/config/objspace.opcodes.CALL_METHOD.txt
   pypy/trunk/pypy/doc/interpreter-optimizations.txt
   pypy/trunk/pypy/interpreter/baseobjspace.py
   pypy/trunk/pypy/interpreter/typedef.py
   pypy/trunk/pypy/jit/codewriter/jtransform.py
   pypy/trunk/pypy/jit/tl/pypyjit.py
   pypy/trunk/pypy/module/__builtin__/interp_classobj.py
   pypy/trunk/pypy/module/__builtin__/test/test_classobj.py
   pypy/trunk/pypy/module/pypyjit/test/test_pypy_c.py
   pypy/trunk/pypy/objspace/descroperation.py
   pypy/trunk/pypy/objspace/std/callmethod.py
   pypy/trunk/pypy/objspace/std/celldict.py
   pypy/trunk/pypy/objspace/std/dictmultiobject.py
   pypy/trunk/pypy/objspace/std/mapdict.py
   pypy/trunk/pypy/objspace/std/objspace.py
   pypy/trunk/pypy/objspace/std/proxyobject.py
   pypy/trunk/pypy/objspace/std/test/test_dictmultiobject.py
Log:
(cfbolz, arigo)
Merge branch/cleanup-dict-impl: get rid of the inlinedict and sharingdict
and use mapdict instead -- now by default with the JIT, including a fix
that stops mapdict from creating tons of versions of the code.


Modified: pypy/trunk/pypy/config/pypyoption.py
==============================================================================
--- pypy/trunk/pypy/config/pypyoption.py	(original)
+++ pypy/trunk/pypy/config/pypyoption.py	Wed Oct 27 16:20:26 2010
@@ -229,27 +229,15 @@
                    requires=[("objspace.opcodes.CALL_LIKELY_BUILTIN", False),
                              ("objspace.honor__builtins__", False)]),
 
-        BoolOption("withsharingdict",
-                   "use dictionaries that share the keys part",
-                   default=False),
-
         BoolOption("withdictmeasurement",
                    "create huge files with masses of information "
                    "about dictionaries",
                    default=False),
 
-        BoolOption("withinlineddict",
-                   "make instances more compact by revoming a level of indirection",
-                   default=False,
-                   requires=[("objspace.std.withshadowtracking", False)]),
-
         BoolOption("withmapdict",
                    "make instances really small but slow without the JIT",
                    default=False,
-                   requires=[("objspace.std.withshadowtracking", False),
-                             ("objspace.std.withinlineddict", False),
-                             ("objspace.std.withsharingdict", False),
-                             ("objspace.std.getattributeshortcut", True),
+                   requires=[("objspace.std.getattributeshortcut", True),
                              ("objspace.std.withtypeversion", True),
                        ]),
 
@@ -266,12 +254,6 @@
                    # weakrefs needed, because of get_subclasses()
                    requires=[("translation.rweakref", True)]),
 
-        BoolOption("withshadowtracking",
-                   "track whether an instance attribute shadows a type"
-                   " attribute",
-                   default=False,
-                   requires=[("objspace.std.withtypeversion", True),
-                             ("translation.rweakref", True)]),
         BoolOption("withmethodcache",
                    "try to cache method lookups",
                    default=False,
@@ -343,9 +325,6 @@
         config.objspace.std.suggest(optimized_list_getitem=True)
         config.objspace.std.suggest(getattributeshortcut=True)
         config.objspace.std.suggest(newshortcut=True)        
-        if type_system != 'ootype':
-            config.objspace.std.suggest(withsharingdict=True)
-        config.objspace.std.suggest(withinlineddict=True)
 
     # extra costly optimizations only go in level 3
     if level == '3':
@@ -374,7 +353,7 @@
     # extra optimizations with the JIT
     if level == 'jit':
         config.objspace.std.suggest(withcelldict=True)
-        #config.objspace.std.suggest(withmapdict=True)
+        config.objspace.std.suggest(withmapdict=True)
 
 
 def enable_allworkingmodules(config):

Modified: pypy/trunk/pypy/config/test/test_pypyoption.py
==============================================================================
--- pypy/trunk/pypy/config/test/test_pypyoption.py	(original)
+++ pypy/trunk/pypy/config/test/test_pypyoption.py	Wed Oct 27 16:20:26 2010
@@ -47,7 +47,7 @@
 def test_set_pypy_opt_level():
     conf = get_pypy_config()
     set_pypy_opt_level(conf, '2')
-    assert conf.objspace.std.withsharingdict
+    assert conf.objspace.std.newshortcut
     conf = get_pypy_config()
     set_pypy_opt_level(conf, '0')
     assert not conf.objspace.std.newshortcut
@@ -59,7 +59,6 @@
 
     assert not conf.objspace.std.withtypeversion
     assert not conf.objspace.std.withmethodcache
-    assert not conf.objspace.std.withshadowtracking
 
 def test_check_documentation():
     def check_file_exists(fn):

Modified: pypy/trunk/pypy/doc/config/objspace.opcodes.CALL_METHOD.txt
==============================================================================
--- pypy/trunk/pypy/doc/config/objspace.opcodes.CALL_METHOD.txt	(original)
+++ pypy/trunk/pypy/doc/config/objspace.opcodes.CALL_METHOD.txt	Wed Oct 27 16:20:26 2010
@@ -5,8 +5,6 @@
 case.  So far, this only works for calls with no keyword, no ``*arg``
 and no ``**arg`` but it would be easy to extend.
 
-Gives the best results combined with :config:`objspace.std.withshadowtracking`.
-
 For more information, see the section in `Standard Interpreter Optimizations`_.
 
 .. _`Standard Interpreter Optimizations`: ../interpreter-optimizations.html#lookup-method-call-method

Modified: pypy/trunk/pypy/doc/interpreter-optimizations.txt
==============================================================================
--- pypy/trunk/pypy/doc/interpreter-optimizations.txt	(original)
+++ pypy/trunk/pypy/doc/interpreter-optimizations.txt	Wed Oct 27 16:20:26 2010
@@ -153,8 +153,8 @@
 dicts:
 the representation of the instance dict contains only a list of values.
 
-You can enable this feature with the :config:`objspace.std.withsharingdict`
-option.
+A more advanced version of sharing dicts, called *map dicts,* is available
+with the :config:`objspace.std.withmapdict` option.
 
 Builtin-Shadowing
 +++++++++++++++++
@@ -219,8 +219,7 @@
 shadowing the class attribute. If we know that there is no shadowing (since
 instance dict tells us that) we can save this lookup on the instance dictionary.
 
-You can enable this feature with the :config:`objspace.std.withshadowtracking`
-option.
+*This was deprecated and is no longer available.*
 
 
 Method Caching

Modified: pypy/trunk/pypy/interpreter/baseobjspace.py
==============================================================================
--- pypy/trunk/pypy/interpreter/baseobjspace.py	(original)
+++ pypy/trunk/pypy/interpreter/baseobjspace.py	Wed Oct 27 16:20:26 2010
@@ -36,13 +36,10 @@
             return space.finditem_str(w_dict, attr)
         return None
 
-    def getdictvalue_attr_is_in_class(self, space, attr):
-        return self.getdictvalue(space, attr)
-
-    def setdictvalue(self, space, attr, w_value, shadows_type=True):
+    def setdictvalue(self, space, attr, w_value):
         w_dict = self.getdict()
         if w_dict is not None:
-            space.setitem_str(w_dict, attr, w_value, shadows_type)
+            space.setitem_str(w_dict, attr, w_value)
             return True
         return False
 
@@ -657,7 +654,7 @@
         """shortcut for space.int_w(space.hash(w_obj))"""
         return self.int_w(self.hash(w_obj))
 
-    def setitem_str(self, w_obj, key, w_value, shadows_type=True):
+    def setitem_str(self, w_obj, key, w_value):
         return self.setitem(w_obj, self.wrap(key), w_value)
 
     def finditem_str(self, w_obj, key):

Modified: pypy/trunk/pypy/interpreter/typedef.py
==============================================================================
--- pypy/trunk/pypy/interpreter/typedef.py	(original)
+++ pypy/trunk/pypy/interpreter/typedef.py	Wed Oct 27 16:20:26 2010
@@ -262,16 +262,7 @@
                 return self.slots_w[index]
         add(Proto)
 
-    wantdict = "dict" in features
-    if wantdict and config.objspace.std.withinlineddict:
-        from pypy.objspace.std.objectobject import W_ObjectObject
-        from pypy.objspace.std.inlinedict import make_mixin
-        if supercls is W_ObjectObject:
-            Mixin = make_mixin(config)
-            add(Mixin)
-            wantdict = False
-
-    if wantdict:
+    if "dict" in features:
         base_user_setup = supercls.user_setup.im_func
         if "user_setup" in body:
             base_user_setup = body["user_setup"]
@@ -290,15 +281,6 @@
             def setclass(self, space, w_subtype):
                 # only used by descr_set___class__
                 self.w__class__ = w_subtype
-                if space.config.objspace.std.withshadowtracking:
-                    self.w__dict__.set_shadows_anything()
-
-            def getdictvalue_attr_is_in_class(self, space, name):
-                w_dict = self.w__dict__
-                if space.config.objspace.std.withshadowtracking:
-                    if not w_dict.shadows_anything():
-                        return None
-                return space.finditem_str(w_dict, name)
 
         add(Proto)
 

Modified: pypy/trunk/pypy/jit/codewriter/jtransform.py
==============================================================================
--- pypy/trunk/pypy/jit/codewriter/jtransform.py	(original)
+++ pypy/trunk/pypy/jit/codewriter/jtransform.py	Wed Oct 27 16:20:26 2010
@@ -172,6 +172,7 @@
 
     def rewrite_op_same_as(self, op): pass
     def rewrite_op_cast_pointer(self, op): pass
+    def rewrite_op_cast_opaque_ptr(self, op): pass   # rlib.rerased
     def rewrite_op_cast_primitive(self, op): pass
     def rewrite_op_cast_bool_to_int(self, op): pass
     def rewrite_op_cast_bool_to_uint(self, op): pass

Modified: pypy/trunk/pypy/jit/tl/pypyjit.py
==============================================================================
--- pypy/trunk/pypy/jit/tl/pypyjit.py	(original)
+++ pypy/trunk/pypy/jit/tl/pypyjit.py	Wed Oct 27 16:20:26 2010
@@ -44,7 +44,6 @@
 config.objspace.usemodules._ffi = True
 #
 set_pypy_opt_level(config, level='jit')
-config.objspace.std.withinlineddict = True
 
 if BACKEND == 'c':
     config.objspace.std.multimethods = 'mrd'

Modified: pypy/trunk/pypy/module/__builtin__/interp_classobj.py
==============================================================================
--- pypy/trunk/pypy/module/__builtin__/interp_classobj.py	(original)
+++ pypy/trunk/pypy/module/__builtin__/interp_classobj.py	Wed Oct 27 16:20:26 2010
@@ -410,8 +410,7 @@
         if w_meth is not None:
             space.call_function(w_meth, w_name, w_value)
         else:
-            # bit obscure: appease normalization
-            self.setdictvalue(space, name, w_value, True)
+            self.setdictvalue(space, name, w_value)
 
     def descr_delattr(self, space, w_name):
         name = unwrap_attr(space, w_name)

Modified: pypy/trunk/pypy/module/__builtin__/test/test_classobj.py
==============================================================================
--- pypy/trunk/pypy/module/__builtin__/test/test_classobj.py	(original)
+++ pypy/trunk/pypy/module/__builtin__/test/test_classobj.py	Wed Oct 27 16:20:26 2010
@@ -954,28 +954,7 @@
         raises(TypeError, descr.__delete__, a)
 
 
-class AppTestOldStyleSharing(AppTestOldstyle):
-    def setup_class(cls):
-        cls.space = gettestobjspace(**{"objspace.std.withsharingdict": True})
-        if option.runappdirect:
-            py.test.skip("can only be run on py.py")
-        def is_sharing(space, w_inst):
-            from pypy.objspace.std.sharingdict import SharedDictImplementation
-            w_d = w_inst.getdict()
-            return space.wrap(isinstance(w_d, SharedDictImplementation) and w_d.r_dict_content is None)
-        cls.w_is_sharing = cls.space.wrap(gateway.interp2app(is_sharing))
-
-
-    def test_real_sharing(self):
-        class A:
-            def __init__(self):
-                self.x = 42
-        A1, A2, A3 = A(), A(), A()
-        assert self.is_sharing(A3)
-        assert self.is_sharing(A2)
-        assert self.is_sharing(A1)
-
-class AppTestOldStyleModDict(object):
+class AppTestOldStyleClassStrDict(object):
     def setup_class(cls):
         if option.runappdirect:
             py.test.skip("can only be run on py.py")

Modified: pypy/trunk/pypy/module/pypyjit/test/test_pypy_c.py
==============================================================================
--- pypy/trunk/pypy/module/pypyjit/test/test_pypy_c.py	(original)
+++ pypy/trunk/pypy/module/pypyjit/test/test_pypy_c.py	Wed Oct 27 16:20:26 2010
@@ -136,9 +136,10 @@
         assert opslogfile.check()
         log = logparser.parse_log_file(str(opslogfile))
         parts = logparser.extract_category(log, 'jit-log-opt-')
+        self.rawloops = [part for part in parts
+                         if not from_entry_bridge(part, parts)]
         # skip entry bridges, they can contain random things
-        self.loops = [parse(part, no_namespace=True) for part in parts
-                          if not from_entry_bridge(part, parts)]
+        self.loops = [parse(part, no_namespace=True) for part in self.rawloops]
         self.sliced_loops = [] # contains all bytecodes of all loops
         self.total_ops = 0
         for loop in self.loops:
@@ -162,12 +163,11 @@
         return [ops for ops in self.sliced_loops if ops.bytecode == name]
 
     def print_loops(self):
-        for loop in self.loops:
+        for rawloop in self.rawloops:
             print
             print '@' * 79
             print
-            for op in loop.operations:
-                print op
+            print rawloop.rstrip()
         print
         print '@' * 79
 
@@ -278,7 +278,7 @@
         assert len(ops) == 2
         assert not ops[0].get_opnames("call")
         assert not ops[0].get_opnames("new")
-        assert len(ops[0].get_opnames("guard")) <= 3     # we get 2 withmapdict
+        assert len(ops[0].get_opnames("guard")) <= 2
         assert not ops[1] # second LOOKUP_METHOD folded away
 
         ops = self.get_by_bytecode("CALL_METHOD")
@@ -323,8 +323,8 @@
         assert len(ops) == 2
         assert not ops[0].get_opnames("call")
         assert not ops[0].get_opnames("new")
-        assert len(ops[0].get_opnames("guard")) <= 3    # we get 2 withmapdict
-        assert len(ops[0].get_opnames("getfield")) <= 5 # we get <5 withmapdict
+        assert len(ops[0].get_opnames("guard")) <= 2
+        assert len(ops[0].get_opnames("getfield")) <= 4
         assert not ops[1] # second LOOKUP_METHOD folded away
 
     def test_default_and_kw(self):

Modified: pypy/trunk/pypy/objspace/descroperation.py
==============================================================================
--- pypy/trunk/pypy/objspace/descroperation.py	(original)
+++ pypy/trunk/pypy/objspace/descroperation.py	Wed Oct 27 16:20:26 2010
@@ -64,9 +64,7 @@
                     w_type = space.type(w_obj)
                     return space.get_and_call_function(w_get, w_descr, w_obj,
                                                        w_type)
-            w_value = w_obj.getdictvalue_attr_is_in_class(space, name)
-        else:
-            w_value = w_obj.getdictvalue(space, name)
+        w_value = w_obj.getdictvalue(space, name)
         if w_value is not None:
             return w_value
         if w_descr is not None:
@@ -76,13 +74,11 @@
     def descr__setattr__(space, w_obj, w_name, w_value):
         name = space.str_w(w_name)
         w_descr = space.lookup(w_obj, name)
-        shadows_type = False
         if w_descr is not None:
             if space.is_data_descr(w_descr):
                 space.set(w_descr, w_obj, w_value)
                 return
-            shadows_type = True
-        if w_obj.setdictvalue(space, name, w_value, shadows_type):
+        if w_obj.setdictvalue(space, name, w_value):
             return
         raiseattrerror(space, w_obj, name, w_descr)
 

Modified: pypy/trunk/pypy/objspace/std/callmethod.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/callmethod.py	(original)
+++ pypy/trunk/pypy/objspace/std/callmethod.py	Wed Oct 27 16:20:26 2010
@@ -44,7 +44,7 @@
         else:
             typ = type(w_descr)
             if typ is function.Function or typ is function.FunctionWithFixedCode:
-                w_value = w_obj.getdictvalue_attr_is_in_class(space, name)
+                w_value = w_obj.getdictvalue(space, name)
                 if w_value is None:
                     # fast method path: a function object in the class,
                     # nothing in the instance
@@ -103,7 +103,7 @@
         w_descr = space.lookup(w_obj, methname)
         typ = type(w_descr)
         if typ is function.Function or typ is function.FunctionWithFixedCode:
-            w_value = w_obj.getdictvalue_attr_is_in_class(space, methname)
+            w_value = w_obj.getdictvalue(space, methname)
             if w_value is None:
                 # fast method path: a function object in the class,
                 # nothing in the instance

Modified: pypy/trunk/pypy/objspace/std/celldict.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/celldict.py	(original)
+++ pypy/trunk/pypy/objspace/std/celldict.py	Wed Oct 27 16:20:26 2010
@@ -47,7 +47,7 @@
         else:
             self._as_rdict().impl_fallback_setitem(w_key, w_value)
 
-    def impl_setitem_str(self, name, w_value, shadows_type=True):
+    def impl_setitem_str(self, name, w_value):
         self.getcell(name, True).w_value = w_value
 
     def impl_delitem(self, w_key):

Modified: pypy/trunk/pypy/objspace/std/dictmultiobject.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/dictmultiobject.py	(original)
+++ pypy/trunk/pypy/objspace/std/dictmultiobject.py	Wed Oct 27 16:20:26 2010
@@ -49,14 +49,6 @@
         elif space.config.objspace.std.withdictmeasurement:
             assert w_type is None
             return MeasuringDictImplementation(space)
-        elif space.config.objspace.std.withsharingdict and instance:
-            from pypy.objspace.std.sharingdict import SharedDictImplementation
-            assert w_type is None
-            return SharedDictImplementation(space)
-        elif (space.config.objspace.std.withshadowtracking and instance and
-                classofinstance is not None):
-            assert w_type is None
-            return ShadowDetectingDictImplementation(space, classofinstance)
         elif instance or strdict or module:
             assert w_type is None
             return StrDictImplementation(space)
@@ -112,7 +104,7 @@
         #return w_value or None
         raise NotImplementedError("abstract base class")
 
-    def impl_setitem_str(self, key, w_value, shadows_type=True):
+    def impl_setitem_str(self, key, w_value):
         raise NotImplementedError("abstract base class")
 
     def impl_setitem(self,  w_key, w_value):
@@ -165,20 +157,13 @@
         key = OPTIMIZED_BUILTINS[i]
         return self.impl_getitem_str(key)
 
-    # this method will only be seen whan a certain config option is used
-    def impl_shadows_anything(self):
-        return True
-
-    def impl_set_shadows_anything(self):
-        pass
-
     # _________________________________________________________________
     # fallback implementation methods
 
     def impl_fallback_setitem(self, w_key, w_value):
         self.r_dict_content[w_key] = w_value
 
-    def impl_fallback_setitem_str(self, key, w_value, shadows_type=True):
+    def impl_fallback_setitem_str(self, key, w_value):
         return self.impl_fallback_setitem(self.space.wrap(key), w_value)
 
     def impl_fallback_delitem(self, w_key):
@@ -211,18 +196,12 @@
         key = OPTIMIZED_BUILTINS[i]
         return self.impl_fallback_getitem_str(key)
 
-    def impl_fallback_shadows_anything(self):
-        return True
-
-    def impl_fallback_set_shadows_anything(self):
-        pass
-
 
 implementation_methods = [
     ("getitem", 1),
     ("getitem_str", 1),
     ("length", 0),
-    ("setitem_str", 3),
+    ("setitem_str", 2),
     ("setitem", 2),
     ("delitem", 1),
     ("iter", 0),
@@ -231,8 +210,6 @@
     ("keys", 0),
     ("clear", 0),
     ("get_builtin_indexed", 1),
-    ("shadows_anything", 0),
-    ("set_shadows_anything", 0),
 ]
 
 
@@ -312,7 +289,7 @@
         else:
             self._as_rdict().impl_fallback_setitem(w_key, w_value)
 
-    def impl_setitem_str(self, key, w_value, shadows_type=True):
+    def impl_setitem_str(self, key, w_value):
         self.content[key] = w_value
 
     def impl_delitem(self, w_key):
@@ -388,47 +365,12 @@
             return None, None
 
 
-class ShadowDetectingDictImplementation(StrDictImplementation):
-    def __init__(self, space, w_type):
-        StrDictImplementation.__init__(self, space)
-        self.w_type = w_type
-        self.original_version_tag = w_type.version_tag()
-        if self.original_version_tag is None:
-            self._shadows_anything = True
-        else:
-            self._shadows_anything = False
-
-    def impl_setitem_str(self, key, w_value, shadows_type=True):
-        if shadows_type:
-            self._shadows_anything = True
-        StrDictImplementation.impl_setitem_str(
-            self, key, w_value, shadows_type)
-
-    def impl_setitem(self, w_key, w_value):
-        space = self.space
-        if space.is_w(space.type(w_key), space.w_str):
-            if not self._shadows_anything:
-                w_obj = self.w_type.lookup(space.str_w(w_key))
-                if w_obj is not None:
-                    self._shadows_anything = True
-            StrDictImplementation.impl_setitem_str(
-                self, self.space.str_w(w_key), w_value, False)
-        else:
-            self._as_rdict().impl_fallback_setitem(w_key, w_value)
-
-    def impl_shadows_anything(self):
-        return (self._shadows_anything or 
-                self.w_type.version_tag() is not self.original_version_tag)
-
-    def impl_set_shadows_anything(self):
-        self._shadows_anything = True
-
 class WaryDictImplementation(StrDictImplementation):
     def __init__(self, space):
         StrDictImplementation.__init__(self, space)
         self.shadowed = [None] * len(BUILTIN_TO_INDEX)
 
-    def impl_setitem_str(self, key, w_value, shadows_type=True):
+    def impl_setitem_str(self, key, w_value):
         i = BUILTIN_TO_INDEX.get(key, -1)
         if i != -1:
             self.shadowed[i] = w_value
@@ -558,7 +500,7 @@
         self.info.writes += 1
         self.content[w_key] = w_value
         self.info.maxcontents = max(self.info.maxcontents, len(self.content))
-    def impl_setitem_str(self, key, w_value, shadows_type=True):
+    def impl_setitem_str(self, key, w_value):
         self.info.setitem_strs += 1
         self.impl_setitem(self.space.wrap(key), w_value)
     def impl_delitem(self, w_key):

Modified: pypy/trunk/pypy/objspace/std/mapdict.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/mapdict.py	(original)
+++ pypy/trunk/pypy/objspace/std/mapdict.py	Wed Oct 27 16:20:26 2010
@@ -1,4 +1,4 @@
-from pypy.rlib import jit, objectmodel
+from pypy.rlib import jit, objectmodel, debug
 
 from pypy.interpreter.baseobjspace import W_Root
 from pypy.objspace.std.dictmultiobject import W_DictMultiObject
@@ -10,6 +10,9 @@
 # attribute shapes
 
 NUM_DIGITS = 4
+NUM_DIGITS_POW2 = 1 << NUM_DIGITS
+# note: we use "x * NUM_DIGITS_POW2" instead of "x << NUM_DIGITS" because
+# we want to propagate knowledge that the result cannot be negative
 
 class AbstractAttribute(object):
     _immutable_fields_ = ['w_cls']
@@ -69,8 +72,10 @@
         attr = self._get_new_attr(selector[0], selector[1])
         oldattr = obj._get_mapdict_map()
         if not jit.we_are_jitted():
-            oldattr._size_estimate += attr.size_estimate() - oldattr.size_estimate()
-            assert oldattr.size_estimate() >= oldattr.length()
+            size_est = (oldattr._size_estimate + attr.size_estimate()
+                                               - oldattr.size_estimate())
+            assert size_est >= (oldattr.length() * NUM_DIGITS_POW2)
+            oldattr._size_estimate = size_est
         if attr.length() > obj._mapdict_storage_length():
             # note that attr.size_estimate() is always at least attr.length()
             new_storage = [None] * attr.size_estimate()
@@ -188,7 +193,7 @@
         self.selector = selector
         self.position = back.length()
         self.back = back
-        self._size_estimate = self.length() << NUM_DIGITS
+        self._size_estimate = self.length() * NUM_DIGITS_POW2
 
     def _copy_attr(self, obj, new_obj):
         w_value = self.read(obj, self.selector)
@@ -291,7 +296,7 @@
     def getdictvalue(self, space, attrname):
         return self._get_mapdict_map().read(self, (attrname, DICT))
 
-    def setdictvalue(self, space, attrname, w_value, shadows_type=True):
+    def setdictvalue(self, space, attrname, w_value):
         return self._get_mapdict_map().write(self, (attrname, DICT), w_value)
 
     def deldictvalue(self, space, w_name):
@@ -383,16 +388,18 @@
     assert space.config.objspace.std.withmapdict
     map = w_type.terminator
     classes = memo_get_subclass_of_correct_size(space, cls)
+    if SUBCLASSES_MIN_FIELDS == SUBCLASSES_MAX_FIELDS:
+        return classes[0]
     size = map.size_estimate()
-    if not size:
-        size = 1
-    try:
-        return classes[size - 1]
-    except IndexError:
-        return classes[-1]
+    debug.check_nonneg(size)
+    if size < len(classes):
+        return classes[size]
+    else:
+        return classes[len(classes)-1]
 get_subclass_of_correct_size._annspecialcase_ = "specialize:arg(1)"
 
-NUM_SUBCLASSES = 10 # XXX tweak this number
+SUBCLASSES_MIN_FIELDS = 5 # XXX tweak these numbers
+SUBCLASSES_MAX_FIELDS = 5
 
 def memo_get_subclass_of_correct_size(space, supercls):
     key = space, supercls
@@ -401,8 +408,12 @@
     except KeyError:
         assert not hasattr(supercls, "__del__")
         result = []
-        for i in range(1, NUM_SUBCLASSES+1):
+        for i in range(SUBCLASSES_MIN_FIELDS, SUBCLASSES_MAX_FIELDS+1):
             result.append(_make_subclass_size_n(supercls, i))
+        for i in range(SUBCLASSES_MIN_FIELDS):
+            result.insert(0, result[0])
+        if SUBCLASSES_MIN_FIELDS == SUBCLASSES_MAX_FIELDS:
+            assert len(set(result)) == 1
         _subclass_cache[key] = result
         return result
 memo_get_subclass_of_correct_size._annspecialcase_ = "specialize:memo"
@@ -413,7 +424,7 @@
     rangen = unroll.unrolling_iterable(range(n))
     nmin1 = n - 1
     rangenmin1 = unroll.unrolling_iterable(range(nmin1))
-    class subcls(ObjectMixin, BaseMapdictObject, supercls):
+    class subcls(BaseMapdictObject, supercls):
         def _init_empty(self, map):
             from pypy.rlib.debug import make_sure_not_resized
             for i in rangen:
@@ -506,8 +517,8 @@
     def impl_getitem_str(self, key):
         return self.w_obj.getdictvalue(self.space, key)
 
-    def impl_setitem_str(self,  key, w_value, shadows_type=True):
-        flag = self.w_obj.setdictvalue(self.space, key, w_value, shadows_type)
+    def impl_setitem_str(self,  key, w_value):
+        flag = self.w_obj.setdictvalue(self.space, key, w_value)
         assert flag
 
     def impl_setitem(self,  w_key, w_value):
@@ -588,8 +599,6 @@
 # ____________________________________________________________
 # Magic caching
 
-# XXX we also would like getdictvalue_attr_is_in_class() above
-
 class CacheEntry(object):
     map = None
     version_tag = None

Modified: pypy/trunk/pypy/objspace/std/objspace.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/objspace.py	(original)
+++ pypy/trunk/pypy/objspace/std/objspace.py	Wed Oct 27 16:20:26 2010
@@ -437,7 +437,7 @@
             if is_data:
                 w_get = self.lookup(w_descr, "__get__")
             if w_get is None:
-                w_value = w_obj.getdictvalue_attr_is_in_class(self, name)
+                w_value = w_obj.getdictvalue(self, name)
                 if w_value is not None:
                     return w_value
                 if not is_data:
@@ -489,14 +489,12 @@
             return w_obj.getitem(w_key)
         return ObjSpace.finditem(self, w_obj, w_key)
 
-    def setitem_str(self, w_obj, key, w_value, shadows_type=True):
+    def setitem_str(self, w_obj, key, w_value):
         """ Same as setitem, but takes string instead of any wrapped object
-
-        XXX what shadows_type means???
         """
         if (isinstance(w_obj, W_DictMultiObject) and
                 not w_obj.user_overridden_class):
-            w_obj.setitem_str(key, w_value, shadows_type)
+            w_obj.setitem_str(key, w_value)
         else:
             self.setitem(w_obj, self.wrap(key), w_value)
 

Modified: pypy/trunk/pypy/objspace/std/proxyobject.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/proxyobject.py	(original)
+++ pypy/trunk/pypy/objspace/std/proxyobject.py	Wed Oct 27 16:20:26 2010
@@ -43,7 +43,7 @@
                     raise
                 return None
         
-        def setdictvalue(self, space, attr, w_value, shadows_type=True):
+        def setdictvalue(self, space, attr, w_value):
             try:
                 space.call_function(self.w_controller, space.wrap('__setattr__'),
                    space.wrap(attr), w_value)

Modified: pypy/trunk/pypy/objspace/std/test/test_dictmultiobject.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/test/test_dictmultiobject.py	(original)
+++ pypy/trunk/pypy/objspace/std/test/test_dictmultiobject.py	Wed Oct 27 16:20:26 2010
@@ -4,7 +4,6 @@
      StrDictImplementation
 
 from pypy.objspace.std.celldict import ModuleDictImplementation
-from pypy.objspace.std.sharingdict import SharedDictImplementation
 from pypy.conftest import gettestobjspace
 
 
@@ -513,32 +512,6 @@
         assert getattr(a, s) == 42
 
 
-class TestW_DictSharing(TestW_DictObject):
-    def setup_class(cls):
-        cls.space = gettestobjspace(**{"objspace.std.withsharingdict": True})
-
-class AppTest_DictSharing(AppTest_DictObject):
-    def setup_class(cls):
-        cls.space = gettestobjspace(**{"objspace.std.withsharingdict": True})
-
-    def test_values_does_not_share(self):
-        class A(object):
-            pass
-        a = A()
-        a.abc = 12
-        l = a.__dict__.values()
-        assert l == [12]
-        l[0] = 24
-        assert a.abc == 12
-
-    def test_items(self):
-        class A(object):
-            pass
-        a = A()
-        a.abc = 12
-        a.__dict__.items() == [("abc", 12)]
-
-
 class AppTestModuleDict(object):
     def setup_class(cls):
         cls.space = gettestobjspace(**{"objspace.std.withcelldict": True})
@@ -632,10 +605,8 @@
     class objspace:
         class std:
             withdictmeasurement = False
-            withsharingdict = False
             withsmalldicts = False
             withcelldict = False
-            withshadowtracking = False
         class opcodes:
             CALL_LIKELY_BUILTIN = False
 
@@ -770,9 +741,6 @@
     string = "int"
     string2 = "isinstance"
 
-class TestSharedDictImplementation(BaseTestRDictImplementation):
-    ImplementionClass = SharedDictImplementation
-
 
 class BaseTestDevolvedDictImplementation(BaseTestRDictImplementation):
     def fill_impl(self):
@@ -794,8 +762,6 @@
     string = "int"
     string2 = "isinstance"
 
-class TestDevolvedSharedDictImplementation(BaseTestDevolvedDictImplementation):
-    ImplementionClass = SharedDictImplementation
 
 def test_module_uses_strdict():
     fakespace = FakeSpace()

Copied: pypy/trunk/pypy/objspace/std/test/test_methodcache.py (from r78358, pypy/branch/cleanup-dict-impl/pypy/objspace/std/test/test_methodcache.py)
==============================================================================
--- pypy/branch/cleanup-dict-impl/pypy/objspace/std/test/test_methodcache.py	(original)
+++ pypy/trunk/pypy/objspace/std/test/test_methodcache.py	Wed Oct 27 16:20:26 2010
@@ -29,10 +29,11 @@
 
     def test_class_that_cannot_be_cached(self):
         import __pypy__
-        class metatype(type):
+        class X:
             pass
-        class A(object):
-            __metaclass__ = metatype
+        class Y(object):
+            pass
+        class A(Y, X):
             def f(self):
                 return 42
 
@@ -130,3 +131,20 @@
             foo = 3
         D.__bases__ = (C, F)
         assert e.foo == 3
+
+    def test_custom_metaclass(self):
+        import __pypy__
+        class MetaA(type):
+            def __getattribute__(self, x):
+                return 1
+        def f(self):
+            return 42
+        A = type.__new__(MetaA, "A", (), {"f": f})
+        l = [type.__getattribute__(A, "__new__")(A)] * 10
+        __pypy__.reset_method_cache_counter()
+        for i, a in enumerate(l):
+            assert a.f() == 42
+        cache_counter = __pypy__.method_cache_counter("f")
+        assert cache_counter[0] >= 5
+        assert cache_counter[1] >= 1 # should be (27, 3)
+        assert sum(cache_counter) == 10



More information about the Pypy-commit mailing list