[pypy-svn] r68930 - in pypy/trunk/pypy: config doc/config interpreter interpreter/test jit/tl module/__builtin__ module/__builtin__/test module/operator module/sys module/sys/test objspace objspace/std objspace/std/test

cfbolz at codespeak.net cfbolz at codespeak.net
Tue Nov 3 11:42:44 CET 2009


Author: cfbolz
Date: Tue Nov  3 11:42:42 2009
New Revision: 68930

Added:
   pypy/trunk/pypy/doc/config/objspace.std.withinlineddict.txt   (contents, props changed)
   pypy/trunk/pypy/objspace/std/inlinedict.py   (contents, props changed)
   pypy/trunk/pypy/objspace/std/test/test_inlinedict.py   (contents, props changed)
Removed:
   pypy/trunk/pypy/doc/config/objspace.std.withbucketdict.txt
   pypy/trunk/pypy/objspace/std/dictbucket.py
   pypy/trunk/pypy/objspace/std/test/test_dictbucket.py
Modified:
   pypy/trunk/pypy/config/pypyoption.py
   pypy/trunk/pypy/interpreter/baseobjspace.py
   pypy/trunk/pypy/interpreter/function.py
   pypy/trunk/pypy/interpreter/main.py
   pypy/trunk/pypy/interpreter/mixedmodule.py
   pypy/trunk/pypy/interpreter/pyopcode.py
   pypy/trunk/pypy/interpreter/test/test_function.py
   pypy/trunk/pypy/interpreter/test/test_typedef.py
   pypy/trunk/pypy/interpreter/typedef.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/operator/__init__.py
   pypy/trunk/pypy/module/sys/__init__.py
   pypy/trunk/pypy/module/sys/test/test_sysmodule.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/dicttype.py
   pypy/trunk/pypy/objspace/std/marshal_impl.py
   pypy/trunk/pypy/objspace/std/model.py
   pypy/trunk/pypy/objspace/std/objectobject.py
   pypy/trunk/pypy/objspace/std/objecttype.py
   pypy/trunk/pypy/objspace/std/objspace.py
   pypy/trunk/pypy/objspace/std/proxyobject.py
   pypy/trunk/pypy/objspace/std/sharingdict.py
   pypy/trunk/pypy/objspace/std/test/test_celldict.py
   pypy/trunk/pypy/objspace/std/test/test_dictmultiobject.py
   pypy/trunk/pypy/objspace/std/test/test_obj.py
   pypy/trunk/pypy/objspace/std/test/test_shadowtracking.py
   pypy/trunk/pypy/objspace/std/typeobject.py
   pypy/trunk/pypy/objspace/std/typetype.py
   pypy/trunk/pypy/objspace/taint.py
Log:
Merge the shrink-multidict branch:

    ------------------------------------------------------------------------
    r68599 | cfbolz | 2009-10-17 18:49:36 +0200 (Sat, 17 Oct 2009) | 2 lines
    Changed paths:
       A /pypy/branch/shrink-multidict (from /pypy/trunk:68598)

    resurrect the branch to try again

    ------------------------------------------------------------------------
    r68749 | cfbolz | 2009-10-26 14:46:32 +0100 (Mon, 26 Oct 2009) | 5 lines
    Changed paths:
       M /pypy/branch/shrink-multidict/pypy/interpreter/baseobjspace.py
       M /pypy/branch/shrink-multidict/pypy/interpreter/typedef.py
       M /pypy/branch/shrink-multidict/pypy/module/__builtin__/interp_classobj.py
       M /pypy/branch/shrink-multidict/pypy/module/__builtin__/test/test_classobj.py
       M /pypy/branch/shrink-multidict/pypy/objspace/std/celldict.py
       D /pypy/branch/shrink-multidict/pypy/objspace/std/dictbucket.py
       M /pypy/branch/shrink-multidict/pypy/objspace/std/dictmultiobject.py
       M /pypy/branch/shrink-multidict/pypy/objspace/std/dicttype.py
       M /pypy/branch/shrink-multidict/pypy/objspace/std/marshal_impl.py
       M /pypy/branch/shrink-multidict/pypy/objspace/std/objspace.py
       M /pypy/branch/shrink-multidict/pypy/objspace/std/sharingdict.py
       M /pypy/branch/shrink-multidict/pypy/objspace/std/test/test_celldict.py
       D /pypy/branch/shrink-multidict/pypy/objspace/std/test/test_dictbucket.py
       M /pypy/branch/shrink-multidict/pypy/objspace/std/test/test_dictmultiobject.py
       M /pypy/branch/shrink-multidict/pypy/objspace/std/test/test_shadowtracking.py
       M /pypy/branch/shrink-multidict/pypy/objspace/std/typeobject.py

    Refactor the multidict to use one level of indirection less. Instead of having
    an indirection, all W_DictMultiObjects have an attribute r_dict_content that is
    usually None. When the dict devolves, it is set to an r_dict and used instead of
    the normal attributes.

    ------------------------------------------------------------------------
    r68751 | cfbolz | 2009-10-26 15:28:38 +0100 (Mon, 26 Oct 2009) | 2 lines
    Changed paths:
       M /pypy/branch/shrink-multidict/pypy/objspace/std/objectobject.py

    don't use * import

    ------------------------------------------------------------------------
    r68752 | cfbolz | 2009-10-26 15:34:37 +0100 (Mon, 26 Oct 2009) | 2 lines
    Changed paths:
       M /pypy/branch/shrink-multidict/pypy/objspace/std/test/test_obj.py

    uh?

    ------------------------------------------------------------------------
    r68753 | cfbolz | 2009-10-26 15:34:58 +0100 (Mon, 26 Oct 2009) | 2 lines
    Changed paths:
       M /pypy/branch/shrink-multidict/pypy/objspace/std/objecttype.py

    remove old commented out code

    ------------------------------------------------------------------------
    r68754 | cfbolz | 2009-10-26 15:43:38 +0100 (Mon, 26 Oct 2009) | 2 lines
    Changed paths:
       M /pypy/branch/shrink-multidict/pypy/objspace/std/celldict.py
       M /pypy/branch/shrink-multidict/pypy/objspace/std/dictmultiobject.py
       M /pypy/branch/shrink-multidict/pypy/objspace/std/test/test_dictmultiobject.py
       M /pypy/branch/shrink-multidict/pypy/objspace/std/typeobject.py

    A number of fixes.

    ------------------------------------------------------------------------
    r68759 | cfbolz | 2009-10-26 16:54:49 +0100 (Mon, 26 Oct 2009) | 12 lines
    Changed paths:
       M /pypy/branch/shrink-multidict/pypy/config/pypyoption.py
       M /pypy/branch/shrink-multidict/pypy/interpreter/test/test_typedef.py
       M /pypy/branch/shrink-multidict/pypy/interpreter/typedef.py
       A /pypy/branch/shrink-multidict/pypy/objspace/std/inlinedict.py
       M /pypy/branch/shrink-multidict/pypy/objspace/std/model.py
       M /pypy/branch/shrink-multidict/pypy/objspace/std/objspace.py
       M /pypy/branch/shrink-multidict/pypy/objspace/std/sharingdict.py
       A /pypy/branch/shrink-multidict/pypy/objspace/std/test/test_inlinedict.py
       M /pypy/branch/shrink-multidict/pypy/objspace/std/test/test_shadowtracking.py

    Make it possible for objects to not have an applevel dict at all:
     - the W_UserDictObjectObject gets the attributes of a StrDictImplementation
       inlined. As long as nobody accesses the applevel .__dict__ attribute, only
       those are used

     - if the __dict__ is requested, we create a dict that forwards all requests to
       the instance

     - if the __dict__ devolves (e.g. a non-string-key is added), the content is
       stored into the r_dict_content of the forwarding dict instance. In this case
       the information on the object is invalid.

    ------------------------------------------------------------------------
    r68763 | cfbolz | 2009-10-26 18:42:39 +0100 (Mon, 26 Oct 2009) | 2 lines
    Changed paths:
       M /pypy/branch/shrink-multidict/pypy/interpreter/function.py
       M /pypy/branch/shrink-multidict/pypy/interpreter/test/test_function.py

    the repr of bound methods was wrong (and quite confusing)

    ------------------------------------------------------------------------
    r68776 | cfbolz | 2009-10-27 10:01:24 +0100 (Tue, 27 Oct 2009) | 4 lines
    Changed paths:
       M /pypy/branch/shrink-multidict/pypy/interpreter/baseobjspace.py
       M /pypy/branch/shrink-multidict/pypy/interpreter/mixedmodule.py
       M /pypy/branch/shrink-multidict/pypy/interpreter/typedef.py
       M /pypy/branch/shrink-multidict/pypy/objspace/descroperation.py
       M /pypy/branch/shrink-multidict/pypy/objspace/std/callmethod.py
       M /pypy/branch/shrink-multidict/pypy/objspace/std/celldict.py
       M /pypy/branch/shrink-multidict/pypy/objspace/std/dictmultiobject.py
       M /pypy/branch/shrink-multidict/pypy/objspace/std/inlinedict.py
       M /pypy/branch/shrink-multidict/pypy/objspace/std/objspace.py
       M /pypy/branch/shrink-multidict/pypy/objspace/std/proxyobject.py
       M /pypy/branch/shrink-multidict/pypy/objspace/std/sharingdict.py
       M /pypy/branch/shrink-multidict/pypy/objspace/std/test/test_dictmultiobject.py
       M /pypy/branch/shrink-multidict/pypy/objspace/std/test/test_inlinedict.py

    A new shortcut in the objspace: finditem_str that takes an unwrapped string as
    the item to find. Please don't ask me how I managed to triplicate the content of
    inlinedict.py and test_inlinedict.py

    ------------------------------------------------------------------------
    r68789 | cfbolz | 2009-10-27 14:16:35 +0100 (Tue, 27 Oct 2009) | 2 lines
    Changed paths:
       D /pypy/branch/shrink-multidict/pypy/doc/config/objspace.std.withbucketdict.txt

    this option is gone

    ------------------------------------------------------------------------
    r68792 | cfbolz | 2009-10-27 14:27:30 +0100 (Tue, 27 Oct 2009) | 2 lines
    Changed paths:
       A /pypy/branch/shrink-multidict/pypy/doc/config/objspace.std.withinlineddict.txt

    document the new option

    ------------------------------------------------------------------------
    r68819 | cfbolz | 2009-10-28 15:02:40 +0100 (Wed, 28 Oct 2009) | 2 lines
    Changed paths:
       M /pypy/branch/shrink-multidict/pypy/module/sys/__init__.py
       M /pypy/branch/shrink-multidict/pypy/module/sys/test/test_sysmodule.py

    bah, there were no tests for sys.exc_value, .exc_type and .exc_traceback

    ------------------------------------------------------------------------
    r68820 | cfbolz | 2009-10-28 15:26:31 +0100 (Wed, 28 Oct 2009) | 2 lines
    Changed paths:
       M /pypy/branch/shrink-multidict/pypy/interpreter/baseobjspace.py
       M /pypy/branch/shrink-multidict/pypy/interpreter/main.py
       M /pypy/branch/shrink-multidict/pypy/interpreter/mixedmodule.py
       M /pypy/branch/shrink-multidict/pypy/interpreter/pyopcode.py
       M /pypy/branch/shrink-multidict/pypy/module/operator/__init__.py
       M /pypy/branch/shrink-multidict/pypy/module/sys/__init__.py
       M /pypy/branch/shrink-multidict/pypy/objspace/descroperation.py
       M /pypy/branch/shrink-multidict/pypy/objspace/std/callmethod.py
       M /pypy/branch/shrink-multidict/pypy/objspace/std/inlinedict.py
       M /pypy/branch/shrink-multidict/pypy/objspace/std/objspace.py
       M /pypy/branch/shrink-multidict/pypy/objspace/std/proxyobject.py
       M /pypy/branch/shrink-multidict/pypy/objspace/std/typeobject.py
       M /pypy/branch/shrink-multidict/pypy/objspace/std/typetype.py
       M /pypy/branch/shrink-multidict/pypy/objspace/taint.py

    make getdictvalue take an unwrapped string and kill getdictvalue_w

    ------------------------------------------------------------------------
    r68821 | cfbolz | 2009-10-28 16:21:35 +0100 (Wed, 28 Oct 2009) | 3 lines
    Changed paths:
       M /pypy/branch/shrink-multidict/pypy/interpreter/baseobjspace.py
       M /pypy/branch/shrink-multidict/pypy/interpreter/pyopcode.py
       M /pypy/branch/shrink-multidict/pypy/jit/tl/pypyjit.py
       M /pypy/branch/shrink-multidict/pypy/jit/tl/pypyjit_demo.py
       M /pypy/branch/shrink-multidict/pypy/module/__builtin__/interp_classobj.py
       M /pypy/branch/shrink-multidict/pypy/objspace/descroperation.py
       M /pypy/branch/shrink-multidict/pypy/objspace/std/celldict.py
       M /pypy/branch/shrink-multidict/pypy/objspace/std/dictmultiobject.py
       M /pypy/branch/shrink-multidict/pypy/objspace/std/inlinedict.py
       M /pypy/branch/shrink-multidict/pypy/objspace/std/objspace.py
       M /pypy/branch/shrink-multidict/pypy/objspace/std/proxyobject.py
       M /pypy/branch/shrink-multidict/pypy/objspace/std/sharingdict.py
       M /pypy/branch/shrink-multidict/pypy/objspace/std/test/test_inlinedict.py
       M /pypy/branch/shrink-multidict/pypy/objspace/taint.py
       M /pypy/branch/shrink-multidict/pypy/translator/goal/gcbench.py

    Change setdictvalue to also take a string. Now it's asymmetric to deldictvalue,
    I might not care though.

    ------------------------------------------------------------------------
    r68912 | cfbolz | 2009-11-02 15:28:38 +0100 (Mon, 02 Nov 2009) | 2 lines
    Changed paths:
       M /pypy/branch/shrink-multidict/pypy/objspace/std/inlinedict.py

    running the tests is generally a good idea

    ------------------------------------------------------------------------
    r68923 | cfbolz | 2009-11-02 18:33:08 +0100 (Mon, 02 Nov 2009) | 3 lines
    Changed paths:
       M /pypy/branch/shrink-multidict/pypy/objspace/std/celldict.py
       M /pypy/branch/shrink-multidict/pypy/objspace/std/dictmultiobject.py
       M /pypy/branch/shrink-multidict/pypy/objspace/std/inlinedict.py
       M /pypy/branch/shrink-multidict/pypy/objspace/std/sharingdict.py
       M /pypy/branch/shrink-multidict/pypy/objspace/std/test/test_inlinedict.py

    A bug found by test_descr.py: setting the dict of an object with a devolved dict
    runs into an assertion.

    ------------------------------------------------------------------------



Modified: pypy/trunk/pypy/config/pypyoption.py
==============================================================================
--- pypy/trunk/pypy/config/pypyoption.py	(original)
+++ pypy/trunk/pypy/config/pypyoption.py	Tue Nov  3 11:42:42 2009
@@ -236,10 +236,10 @@
                    "about dictionaries",
                    default=False),
 
-        BoolOption("withbucketdict",
-                   "use dictionaries with chained hash tables "
-                   "(default is open addressing)",
-                   default=False),
+        BoolOption("withinlineddict",
+                   "make instances more compact by revoming a level of indirection",
+                   default=False,
+                   requires=[("objspace.std.withshadowtracking", False)]),
 
         BoolOption("withrangelist",
                    "enable special range list implementation that does not "
@@ -362,6 +362,7 @@
         if type_system != 'ootype':
             config.objspace.std.suggest(withsharingdict=True)
         config.objspace.std.suggest(withcelldict=True)
+        config.objspace.std.suggest(withinlineddict=True)
 
 
 def enable_allworkingmodules(config):

Added: pypy/trunk/pypy/doc/config/objspace.std.withinlineddict.txt
==============================================================================
--- (empty file)
+++ pypy/trunk/pypy/doc/config/objspace.std.withinlineddict.txt	Tue Nov  3 11:42:42 2009
@@ -0,0 +1,2 @@
+Make instances smaller by creating the __dict__ only when somebody actually
+accesses it. Also makes attribute accesses a tiny bit faster.

Modified: pypy/trunk/pypy/interpreter/baseobjspace.py
==============================================================================
--- pypy/trunk/pypy/interpreter/baseobjspace.py	(original)
+++ pypy/trunk/pypy/interpreter/baseobjspace.py	Tue Nov  3 11:42:42 2009
@@ -20,26 +20,24 @@
     in a 'normal' object space like StdObjSpace."""
     __slots__ = ()
     _settled_ = True
+    user_overridden_class = False
 
     def getdict(self):
         return None
 
-    def getdictvalue_w(self, space, attr):
-        return self.getdictvalue(space, space.wrap(attr))
-
-    def getdictvalue(self, space, w_attr):
+    def getdictvalue(self, space, attr):
         w_dict = self.getdict()
         if w_dict is not None:
-            return space.finditem(w_dict, w_attr)
+            return space.finditem_str(w_dict, attr)
         return None
 
-    def getdictvalue_attr_is_in_class(self, space, w_attr):
-        return self.getdictvalue(space, w_attr)
+    def getdictvalue_attr_is_in_class(self, space, attr):
+        return self.getdictvalue(space, attr)
 
-    def setdictvalue(self, space, w_attr, w_value, shadows_type=True):
+    def setdictvalue(self, space, attr, w_value, shadows_type=True):
         w_dict = self.getdict()
         if w_dict is not None:
-            space.set_str_keyed_item(w_dict, w_attr, w_value, shadows_type)
+            space.set_str_keyed_item(w_dict, attr, w_value, shadows_type)
             return True
         return False
 
@@ -281,7 +279,7 @@
                 self.timer.stop("startup " + modname)
 
     def finish(self):
-        w_exitfunc = self.sys.getdictvalue_w(self, 'exitfunc')
+        w_exitfunc = self.sys.getdictvalue(self, 'exitfunc')
         if w_exitfunc is not None:
             self.call_function(w_exitfunc)
         from pypy.interpreter.module import Module
@@ -550,12 +548,6 @@
     # that can be defined in term of more primitive ones.  Subclasses
     # may also override specific functions for performance.
 
-    #def is_(self, w_x, w_y):   -- not really useful.  Must be subclassed
-    #    "'x is y'."
-    #    w_id_x = self.id(w_x)
-    #    w_id_y = self.id(w_y)
-    #    return self.eq(w_id_x, w_id_y)
-
     def not_(self, w_obj):
         return self.wrap(not self.is_true(w_obj))
 
@@ -571,8 +563,11 @@
         """shortcut for space.int_w(space.hash(w_obj))"""
         return self.int_w(self.hash(w_obj))
 
-    def set_str_keyed_item(self, w_obj, w_key, w_value, shadows_type=True):
-        return self.setitem(w_obj, w_key, w_value)
+    def set_str_keyed_item(self, w_obj, key, w_value, shadows_type=True):
+        return self.setitem(w_obj, self.wrap(key), w_value)
+
+    def finditem_str(self, w_obj, key):
+        return self.finditem(w_obj, self.wrap(key))
 
     def finditem(self, w_obj, w_key):
         try:
@@ -777,7 +772,7 @@
         w_type = self.type(w_obj)
         w_mro = self.getattr(w_type, self.wrap("__mro__"))
         for w_supertype in self.unpackiterable(w_mro):
-            w_value = w_supertype.getdictvalue_w(self, name)
+            w_value = w_supertype.getdictvalue(self, name)
             if w_value is not None:
                 return w_value
         return None

Modified: pypy/trunk/pypy/interpreter/function.py
==============================================================================
--- pypy/trunk/pypy/interpreter/function.py	(original)
+++ pypy/trunk/pypy/interpreter/function.py	Tue Nov  3 11:42:42 2009
@@ -494,9 +494,8 @@
             return space.wrap(s)
         else:
             objrepr = space.str_w(space.repr(self.w_instance))
-            info = 'bound method %s.%s of %s' % (typename, name, objrepr)
-            # info = "method %s of %s object" % (name, typename)
-            return self.w_instance.getrepr(self.space, info)
+            s = '<bound method %s.%s of %s>' % (typename, name, objrepr)
+            return space.wrap(s)
 
     def descr_method_getattribute(self, w_attr):
         space = self.space

Modified: pypy/trunk/pypy/interpreter/main.py
==============================================================================
--- pypy/trunk/pypy/interpreter/main.py	(original)
+++ pypy/trunk/pypy/interpreter/main.py	Tue Nov  3 11:42:42 2009
@@ -149,11 +149,11 @@
                           w_traceback)
 
             # call sys.excepthook if present
-            w_hook = space.sys.getdictvalue_w(space, 'excepthook')
+            w_hook = space.sys.getdictvalue(space, 'excepthook')
             if w_hook is not None:
                 # hack: skip it if it wasn't modified by the user,
                 #       to do instead the faster verbose/nonverbose thing below
-                w_original = space.sys.getdictvalue_w(space, '__excepthook__')
+                w_original = space.sys.getdictvalue(space, '__excepthook__')
                 if w_original is None or not space.is_w(w_hook, w_original):
                     space.call_function(w_hook, w_type, w_value, w_traceback)
                     return False   # done

Modified: pypy/trunk/pypy/interpreter/mixedmodule.py
==============================================================================
--- pypy/trunk/pypy/interpreter/mixedmodule.py	(original)
+++ pypy/trunk/pypy/interpreter/mixedmodule.py	Tue Nov  3 11:42:42 2009
@@ -32,7 +32,7 @@
 
     def get(self, name):
         space = self.space
-        w_value = self.getdictvalue_w(space, name) 
+        w_value = self.getdictvalue(space, name) 
         if w_value is None: 
             raise OperationError(space.w_AttributeError, space.wrap(name))
         return w_value 
@@ -41,40 +41,41 @@
         w_builtin = self.get(name) 
         return self.space.call_function(w_builtin, *args_w)
 
-    def getdictvalue(self, space, w_name):
-        w_value = space.finditem(self.w_dict, w_name)
+    def getdictvalue(self, space, name):
+        w_value = space.finditem_str(self.w_dict, name)
         if self.lazy and w_value is None:
-            name = space.str_w(w_name)
-            w_name = space.new_interned_w_str(w_name)
-            try: 
-                loader = self.loaders[name]
-            except KeyError: 
-                return None 
-            else: 
-                #print "trying to load", name
-                w_value = loader(space) 
-                #print "loaded", w_value 
-                # obscure
-                func = space.interpclass_w(w_value)
-                # the idea of the following code is that all functions that are
-                # directly in a mixed-module are "builtin", e.g. they get a
-                # special type without a __get__
-                # note that this is not just all functions that contain a
-                # builtin code object, as e.g. methods of builtin types have to
-                # be normal Functions to get the correct binding behaviour
-                if (isinstance(func, Function) and
-                    type(func) is not BuiltinFunction):
-                    try:
-                        bltin = func._builtinversion_
-                    except AttributeError:
-                        bltin = BuiltinFunction(func)
-                        bltin.w_module = self.w_name
-                        func._builtinversion_ = bltin
-                        bltin.name = name
-                    w_value = space.wrap(bltin)
-                space.setitem(self.w_dict, w_name, w_value) 
+            return self._load_lazily(space, name)
         return w_value
 
+    def _load_lazily(self, space, name):
+        w_name = space.new_interned_str(name)
+        try: 
+            loader = self.loaders[name]
+        except KeyError: 
+            return None 
+        else: 
+            w_value = loader(space) 
+            func = space.interpclass_w(w_value)
+            # the idea of the following code is that all functions that are
+            # directly in a mixed-module are "builtin", e.g. they get a
+            # special type without a __get__
+            # note that this is not just all functions that contain a
+            # builtin code object, as e.g. methods of builtin types have to
+            # be normal Functions to get the correct binding behaviour
+            if (isinstance(func, Function) and
+                type(func) is not BuiltinFunction):
+                try:
+                    bltin = func._builtinversion_
+                except AttributeError:
+                    bltin = BuiltinFunction(func)
+                    bltin.w_module = self.w_name
+                    func._builtinversion_ = bltin
+                    bltin.name = name
+                w_value = space.wrap(bltin)
+            space.setitem(self.w_dict, w_name, w_value) 
+            return w_value
+
+
     def getdict(self): 
         if self.lazy: 
             space = self.space

Modified: pypy/trunk/pypy/interpreter/pyopcode.py
==============================================================================
--- pypy/trunk/pypy/interpreter/pyopcode.py	(original)
+++ pypy/trunk/pypy/interpreter/pyopcode.py	Tue Nov  3 11:42:42 2009
@@ -619,9 +619,9 @@
         f.pushvalue(w_newclass)
 
     def STORE_NAME(f, varindex, *ignored):
-        w_varname = f.getname_w(varindex)
+        varname = f.getname_u(varindex)
         w_newvalue = f.popvalue()
-        f.space.set_str_keyed_item(f.w_locals, w_varname, w_newvalue)
+        f.space.set_str_keyed_item(f.w_locals, varname, w_newvalue)
 
     def DELETE_NAME(f, varindex, *ignored):
         w_varname = f.getname_w(varindex)
@@ -656,9 +656,9 @@
         f.space.delattr(w_obj, w_attributename)
 
     def STORE_GLOBAL(f, nameindex, *ignored):
-        w_varname = f.getname_w(nameindex)
+        varname = f.getname_u(nameindex)
         w_newvalue = f.popvalue()
-        f.space.set_str_keyed_item(f.w_globals, w_varname, w_newvalue)
+        f.space.set_str_keyed_item(f.w_globals, varname, w_newvalue)
 
     def DELETE_GLOBAL(f, nameindex, *ignored):
         w_varname = f.getname_w(nameindex)
@@ -673,25 +673,24 @@
                 return
         f.LOAD_GLOBAL(nameindex)    # fall-back
 
-    def _load_global(f, w_varname):
-        w_value = f.space.finditem(f.w_globals, w_varname)
+    def _load_global(f, varname):
+        w_value = f.space.finditem_str(f.w_globals, varname)
         if w_value is None:
             # not in the globals, now look in the built-ins
-            w_value = f.get_builtin().getdictvalue(f.space, w_varname)
+            w_value = f.get_builtin().getdictvalue(f.space, varname)
             if w_value is None:
-                f._load_global_failed(w_varname)
+                f._load_global_failed(varname)
         return w_value
     _load_global._always_inline_ = True
 
-    def _load_global_failed(f, w_varname):
-        varname = f.space.str_w(w_varname)
+    def _load_global_failed(f, varname):
         message = "global name '%s' is not defined" % varname
         raise OperationError(f.space.w_NameError,
                              f.space.wrap(message))
     _load_global_failed._dont_inline_ = True
 
     def LOAD_GLOBAL(f, nameindex, *ignored):
-        f.pushvalue(f._load_global(f.getname_w(nameindex)))
+        f.pushvalue(f._load_global(f.getname_u(nameindex)))
     LOAD_GLOBAL._always_inline_ = True
 
     def DELETE_FAST(f, varindex, *ignored):
@@ -782,7 +781,7 @@
         else:
             w_flag = None
 
-        w_import = f.get_builtin().getdictvalue_w(f.space, '__import__')
+        w_import = f.get_builtin().getdictvalue(f.space, '__import__')
         if w_import is None:
             raise OperationError(space.w_ImportError,
                                  space.wrap("__import__ not found"))
@@ -989,8 +988,8 @@
     def CALL_LIKELY_BUILTIN(f, oparg, *ignored):
         # overridden by faster version in the standard object space.
         from pypy.module.__builtin__ import OPTIMIZED_BUILTINS
-        w_varname = f.space.wrap(OPTIMIZED_BUILTINS[oparg >> 8])
-        w_function = f._load_global(w_varname)
+        varname = OPTIMIZED_BUILTINS[oparg >> 8]
+        w_function = f._load_global(varname)
         nargs = oparg&0xFF
         try:
             w_result = f.space.call_valuestack(w_function, nargs, f)

Modified: pypy/trunk/pypy/interpreter/test/test_function.py
==============================================================================
--- pypy/trunk/pypy/interpreter/test/test_function.py	(original)
+++ pypy/trunk/pypy/interpreter/test/test_function.py	Tue Nov  3 11:42:42 2009
@@ -382,11 +382,13 @@
                 pass
         assert repr(A.f) == "<unbound method A.f>"
         assert repr(A().f).startswith("<bound method A.f of <") 
+        assert repr(A().f).endswith(">>") 
         class B:
             def f(self):
                 pass
         assert repr(B.f) == "<unbound method B.f>"
         assert repr(B().f).startswith("<bound method B.f of <")
+        assert repr(A().f).endswith(">>") 
 
 
     def test_method_call(self):

Modified: pypy/trunk/pypy/interpreter/test/test_typedef.py
==============================================================================
--- pypy/trunk/pypy/interpreter/test/test_typedef.py	(original)
+++ pypy/trunk/pypy/interpreter/test/test_typedef.py	Tue Nov  3 11:42:42 2009
@@ -125,7 +125,7 @@
                                checks[2], checks[3]))
         subclasses = {}
         for key, subcls in typedef._subclass_cache.items():
-            cls = key[0]
+            cls = key[1]
             subclasses.setdefault(cls, {})
             subclasses[cls][subcls] = True
         for cls, set in subclasses.items():

Modified: pypy/trunk/pypy/interpreter/typedef.py
==============================================================================
--- pypy/trunk/pypy/interpreter/typedef.py	(original)
+++ pypy/trunk/pypy/interpreter/typedef.py	Tue Nov  3 11:42:42 2009
@@ -97,23 +97,24 @@
 #         /           \
 #        5             6
 
-def get_unique_interplevel_subclass(cls, hasdict, wants_slots, needsdel=False,
-                                    weakrefable=False):
+def get_unique_interplevel_subclass(config, cls, hasdict, wants_slots,
+                                    needsdel=False, weakrefable=False):
     "NOT_RPYTHON: initialization-time only"
     if hasattr(cls, '__del__') and getattr(cls, "handle_del_manually", False):
         needsdel = False
     assert cls.typedef.acceptable_as_base_class
-    key = cls, hasdict, wants_slots, needsdel, weakrefable
+    key = config, cls, hasdict, wants_slots, needsdel, weakrefable
     try:
         return _subclass_cache[key]
     except KeyError:
-        subcls = _getusercls(cls, hasdict, wants_slots, needsdel, weakrefable)
+        subcls = _getusercls(config, cls, hasdict, wants_slots, needsdel,
+                             weakrefable)
         _subclass_cache[key] = subcls
         return subcls
 get_unique_interplevel_subclass._annspecialcase_ = "specialize:memo"
 _subclass_cache = {}
 
-def enum_interplevel_subclasses(cls):
+def enum_interplevel_subclasses(config, cls):
     """Return a list of all the extra interp-level subclasses of 'cls' that
     can be built by get_unique_interplevel_subclass()."""
     result = []
@@ -121,14 +122,13 @@
         for flag2 in (False, True):
             for flag3 in (False, True):
                 for flag4 in (False, True):
-                    result.append(get_unique_interplevel_subclass(cls, flag1,
-                                                                  flag2, flag3,
-                                                                  flag4))
+                    result.append(get_unique_interplevel_subclass(
+                        config, cls, flag1, flag2, flag3, flag4))
     result = dict.fromkeys(result)
     assert len(result) <= 6
     return result.keys()
 
-def _getusercls(cls, wants_dict, wants_slots, wants_del, weakrefable):
+def _getusercls(config, cls, wants_dict, wants_slots, wants_del, weakrefable):
     typedef = cls.typedef
     if wants_dict and typedef.hasdict:
         wants_dict = False
@@ -136,47 +136,47 @@
     if wants_del:
         if wants_dict:
             # case 5.  Parent class is 3.
-            parentcls = get_unique_interplevel_subclass(cls, True, True,
+            parentcls = get_unique_interplevel_subclass(config, cls, True, True,
                                                         False, True)
         else:
             # case 6.  Parent class is 4.
-            parentcls = get_unique_interplevel_subclass(cls, False, True,
+            parentcls = get_unique_interplevel_subclass(config, cls, False, True,
                                                         False, True)
-        return _usersubclswithfeature(parentcls, "del")
+        return _usersubclswithfeature(config, parentcls, "del")
     elif wants_dict:
         if wants_slots:
             # case 3.  Parent class is 1.
-            parentcls = get_unique_interplevel_subclass(cls, True, False,
+            parentcls = get_unique_interplevel_subclass(config, cls, True, False,
                                                         False, True)
-            return _usersubclswithfeature(parentcls, "slots")
+            return _usersubclswithfeature(config, parentcls, "slots")
         else:
             # case 1 (we need to add weakrefable unless it's already in 'cls')
             if not typedef.weakrefable:
-                return _usersubclswithfeature(cls, "user", "dict", "weakref")
+                return _usersubclswithfeature(config, cls, "user", "dict", "weakref")
             else:
-                return _usersubclswithfeature(cls, "user", "dict")
+                return _usersubclswithfeature(config, cls, "user", "dict")
     else:
         if weakrefable and not typedef.weakrefable:
             # case 4.  Parent class is 2.
-            parentcls = get_unique_interplevel_subclass(cls, False, True,
+            parentcls = get_unique_interplevel_subclass(config, cls, False, True,
                                                         False, False)
-            return _usersubclswithfeature(parentcls, "weakref")
+            return _usersubclswithfeature(config, parentcls, "weakref")
         else:
             # case 2 (if the base is already weakrefable, case 2 == case 4)
-            return _usersubclswithfeature(cls, "user", "slots")
+            return _usersubclswithfeature(config, cls, "user", "slots")
 
-def _usersubclswithfeature(parentcls, *features):
-    key = parentcls, features
+def _usersubclswithfeature(config, parentcls, *features):
+    key = config, parentcls, features
     try:
         return _usersubclswithfeature_cache[key]
     except KeyError:
-        subcls = _builduserclswithfeature(parentcls, *features)
+        subcls = _builduserclswithfeature(config, parentcls, *features)
         _usersubclswithfeature_cache[key] = subcls
         return subcls
 _usersubclswithfeature_cache = {}
 _allusersubcls_cache = {}
 
-def _builduserclswithfeature(supercls, *features):
+def _builduserclswithfeature(config, supercls, *features):
     "NOT_RPYTHON: initialization-time only"
     name = supercls.__name__
     name += ''.join([name.capitalize() for name in features])
@@ -190,6 +190,8 @@
 
     if "user" in features:     # generic feature needed by all subcls
         class Proto(object):
+            user_overridden_class = True
+
             def getclass(self, space):
                 return hint(self.w__class__, promote=True)
 
@@ -242,7 +244,16 @@
                 return self.slots_w[index]
         add(Proto)
 
-    if "dict" in features:
+    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:
         class Proto(object):
             def getdict(self):
                 return self.w__dict__
@@ -253,32 +264,22 @@
             def user_setup(self, space, w_subtype):
                 self.space = space
                 self.w__class__ = w_subtype
-                if space.config.objspace.std.withsharingdict:
-                    from pypy.objspace.std import dictmultiobject
-                    self.w__dict__ = dictmultiobject.W_DictMultiObject(space,
-                            sharing=True)
-                elif space.config.objspace.std.withshadowtracking:
-                    from pypy.objspace.std import dictmultiobject
-                    self.w__dict__ = dictmultiobject.W_DictMultiObject(space)
-                    self.w__dict__.implementation = \
-                        dictmultiobject.ShadowDetectingDictImplementation(
-                                space, w_subtype)
-                else:
-                    self.w__dict__ = space.newdict()
+                self.w__dict__ = space.newdict(
+                    instance=True, classofinstance=w_subtype)
                 self.user_setup_slots(w_subtype.nslots)
 
             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__.implementation.set_shadows_anything()
+                    self.w__dict__.set_shadows_anything()
 
-            def getdictvalue_attr_is_in_class(self, space, w_name):
+            def getdictvalue_attr_is_in_class(self, space, name):
                 w_dict = self.w__dict__
                 if space.config.objspace.std.withshadowtracking:
-                    if not w_dict.implementation.shadows_anything():
+                    if not w_dict.shadows_anything():
                         return None
-                return space.finditem(w_dict, w_name)
+                return space.finditem_str(w_dict, name)
 
         add(Proto)
 

Modified: pypy/trunk/pypy/jit/tl/pypyjit.py
==============================================================================
--- pypy/trunk/pypy/jit/tl/pypyjit.py	(original)
+++ pypy/trunk/pypy/jit/tl/pypyjit.py	Tue Nov  3 11:42:42 2009
@@ -41,6 +41,7 @@
 config.objspace.usemodules._weakref = False
 config.objspace.usemodules._sre = False
 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	Tue Nov  3 11:42:42 2009
@@ -304,12 +304,7 @@
 class W_InstanceObject(Wrappable):
     def __init__(self, space, w_class, w_dict=None):
         if w_dict is None:
-            if space.config.objspace.std.withsharingdict:
-                from pypy.objspace.std import dictmultiobject
-                w_dict = dictmultiobject.W_DictMultiObject(space,
-                            sharing=True)
-            else:
-                w_dict = space.newdict()
+            w_dict = space.newdict(instance=True)
         assert isinstance(w_class, W_ClassObject)
         self.w_class = w_class
         self.w_dict = w_dict
@@ -388,7 +383,7 @@
         if w_meth is not None:
             space.call_function(w_meth, w_name, w_value)
         else:
-            self.setdictvalue(space, w_name, w_value)
+            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	Tue Nov  3 11:42:42 2009
@@ -772,8 +772,7 @@
         def is_sharing(space, w_inst):
             from pypy.objspace.std.sharingdict import SharedDictImplementation, W_DictMultiObject
             w_d = w_inst.getdict()
-            return space.wrap(isinstance(w_d, W_DictMultiObject) and
-                              isinstance(w_d.implementation, SharedDictImplementation))
+            return space.wrap(isinstance(w_d, SharedDictImplementation))
         cls.w_is_sharing = cls.space.wrap(gateway.interp2app(is_sharing))
 
 

Modified: pypy/trunk/pypy/module/operator/__init__.py
==============================================================================
--- pypy/trunk/pypy/module/operator/__init__.py	(original)
+++ pypy/trunk/pypy/module/operator/__init__.py	Tue Nov  3 11:42:42 2009
@@ -9,7 +9,7 @@
 
     def __init__(self, space, w_name):
         def create_lambda(name, alsoname):
-            return lambda space : self.getdictvalue(space, space.wrap(alsoname))
+            return lambda space : self.getdictvalue(space, alsoname)
         
         MixedModule.__init__(self, space, w_name)
         for name, alsoname in self.mapping.iteritems():

Modified: pypy/trunk/pypy/module/sys/__init__.py
==============================================================================
--- pypy/trunk/pypy/module/sys/__init__.py	(original)
+++ pypy/trunk/pypy/module/sys/__init__.py	Tue Nov  3 11:42:42 2009
@@ -100,12 +100,11 @@
         w_modules = self.get('modules')
         self.space.setitem(w_modules, w_name, w_module)
 
-    def getdictvalue(self, space, w_attr): 
+    def getdictvalue(self, space, attr):
         """ specialize access to dynamic exc_* attributes. """ 
-        value = MixedModule.getdictvalue(self, space, w_attr) 
+        value = MixedModule.getdictvalue(self, space, attr) 
         if value is not None: 
             return value
-        attr = space.str_w(w_attr)
         if attr == 'exc_type':
             operror = space.getexecutioncontext().sys_exc_info()
             if operror is None:

Modified: pypy/trunk/pypy/module/sys/test/test_sysmodule.py
==============================================================================
--- pypy/trunk/pypy/module/sys/test/test_sysmodule.py	(original)
+++ pypy/trunk/pypy/module/sys/test/test_sysmodule.py	Tue Nov  3 11:42:42 2009
@@ -65,6 +65,26 @@
         assert exc_val2 ==e2
         assert tb2.tb_lineno - tb.tb_lineno == 5
 
+    def test_dynamic_attributes(self):
+        try:
+            raise Exception
+        except Exception,e:
+            import sys
+            exc_type = sys.exc_type
+            exc_val = sys.exc_value
+            tb = sys.exc_traceback
+        try:
+            raise Exception   # 7 lines below the previous one
+        except Exception,e2:
+            exc_type2 = sys.exc_type
+            exc_val2 = sys.exc_value
+            tb2 = sys.exc_traceback
+        assert exc_type ==Exception
+        assert exc_val ==e
+        assert exc_type2 ==Exception
+        assert exc_val2 ==e2
+        assert tb2.tb_lineno - tb.tb_lineno == 7
+
     def test_exc_info_normalization(self):
         import sys
         try:

Modified: pypy/trunk/pypy/objspace/descroperation.py
==============================================================================
--- pypy/trunk/pypy/objspace/descroperation.py	(original)
+++ pypy/trunk/pypy/objspace/descroperation.py	Tue Nov  3 11:42:42 2009
@@ -36,9 +36,9 @@
         if w_descr is not None:
             if space.is_data_descr(w_descr):
                 return space.get(w_descr, w_obj)
-            w_value = w_obj.getdictvalue_attr_is_in_class(space, w_name)
+            w_value = w_obj.getdictvalue_attr_is_in_class(space, name)
         else:
-            w_value = w_obj.getdictvalue(space, w_name)
+            w_value = w_obj.getdictvalue(space, name)
         if w_value is not None:
             return w_value
         if w_descr is not None:
@@ -54,7 +54,7 @@
                 space.set(w_descr, w_obj, w_value)
                 return
             shadows_type = True
-        if w_obj.setdictvalue(space, w_name, w_value, shadows_type):
+        if w_obj.setdictvalue(space, name, w_value, shadows_type):
             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	Tue Nov  3 11:42:42 2009
@@ -54,11 +54,11 @@
         if w_descr is None:
             # this handles directly the common case
             #   module.function(args..)
-            w_value = w_obj.getdictvalue(space, w_name)
+            w_value = w_obj.getdictvalue(space, name)
         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, w_name)
+                w_value = w_obj.getdictvalue_attr_is_in_class(space, name)
                 if w_value is None:
                     # fast method path: a function object in the class,
                     # nothing in the instance
@@ -87,16 +87,16 @@
     """An optimized version of space.call_method()
     based on the same principle as above.
     """
-    w_name = space.wrap(methname)
     w_getattribute = space.lookup(w_obj, '__getattribute__')
     if w_getattribute is object_getattribute(space):
         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, w_name)
+            w_value = w_obj.getdictvalue_attr_is_in_class(space, methname)
             if w_value is None:
                 # fast method path: a function object in the class,
                 # nothing in the instance
                 return space.call_function(w_descr, w_obj, *arg_w)
+    w_name = space.wrap(methname)
     w_meth = space.getattr(w_obj, w_name)
     return space.call_function(w_meth, *arg_w)

Modified: pypy/trunk/pypy/objspace/std/celldict.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/celldict.py	(original)
+++ pypy/trunk/pypy/objspace/std/celldict.py	Tue Nov  3 11:42:42 2009
@@ -1,5 +1,4 @@
 from pypy.interpreter.pycode import CO_CONTAINSGLOBALS
-from pypy.objspace.std.dictmultiobject import DictImplementation
 from pypy.objspace.std.dictmultiobject import IteratorImplementation
 from pypy.objspace.std.dictmultiobject import W_DictMultiObject, _is_sane_hash
 from pypy.rlib import jit
@@ -16,7 +15,7 @@
     def __repr__(self):
         return "<ModuleCell: %s>" % (self.w_value, )
 
-class ModuleDictImplementation(DictImplementation):
+class ModuleDictImplementation(W_DictMultiObject):
     def __init__(self, space):
         self.space = space
         self.content = {}
@@ -45,24 +44,21 @@
             w_value = cell.invalidate()
             cell = impl.content[name] = ModuleCell(w_value)
 
-    def setitem(self, w_key, w_value):
+    def impl_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)
+            self.impl_setitem_str(self.space.str_w(w_key), w_value)
         else:
-            return self._as_rdict().setitem(w_key, w_value)
+            self._as_rdict().setitem(w_key, w_value)
 
-    def setitem_str(self, w_key, w_value, shadows_type=True):
-        name = self.space.str_w(w_key)
+    def impl_setitem_str(self, name, w_value, shadows_type=True):
         self.getcell(name).w_value = w_value
         
         if name in self.unshadowed_builtins:
             self.invalidate_unshadowed_builtin(name)
             del self.unshadowed_builtins[name]
 
-        return self
-
-    def delitem(self, w_key):
+    def impl_delitem(self, w_key):
         space = self.space
         w_key_type = space.type(w_key)
         if space.is_w(w_key_type, space.w_str):
@@ -72,84 +68,71 @@
                 raise KeyError
             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)
+            self._as_rdict().delitem(w_key)
         
-    def length(self):
+    def impl_length(self):
         return len(self.content)
 
-    def get(self, w_lookup):
+    def impl_getitem(self, w_lookup):
         space = self.space
         w_lookup_type = space.type(w_lookup)
         if space.is_w(w_lookup_type, space.w_str):
-            res = self.getcell(space.str_w(w_lookup), False)
-            if res is None:
-                return None
-            return res.w_value
+            return self.impl_getitem_str(space.str_w(w_lookup))
+
         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)
+            return self._as_rdict().getitem(w_lookup)
 
-    def iterkeys(self):
-        return ModuleDictKeyIteratorImplementation(self.space, self)
+    def impl_getitem_str(self, lookup):
+        res = self.getcell(lookup, False)
+        if res is None:
+            return None
+        return res.w_value
 
-    def itervalues(self):
-        return ModuleDictValueIteratorImplementation(self.space, self)
+    def impl_iter(self):
+        return ModuleDictIteratorImplementation(self.space, self)
 
-    def keys(self):
+    def impl_keys(self):
         space = self.space
         return [space.wrap(key) for key in self.content.iterkeys()]
 
-    def values(self):
+    def impl_values(self):
         return [cell.w_value for cell in self.content.itervalues()]
 
-    def items(self):
+    def impl_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)
+    def impl_clear(self):
+        # inefficient, but who cares
         for k, cell in self.content.iteritems():
-            newimpl.setitem(self.space.wrap(k), cell.w_value)
             cell.invalidate()
         for k in self.unshadowed_builtins:
             self.invalidate_unshadowed_builtin(k)
-        return newimpl
-
-# grrrrr. just a copy-paste from StrKeyIteratorImplementation in dictmultiobject
-class ModuleDictKeyIteratorImplementation(IteratorImplementation):
-    def __init__(self, space, dictimplementation):
-        IteratorImplementation.__init__(self, space, dictimplementation)
-        self.iterator = dictimplementation.content.iterkeys()
+        self.content.clear()
+        self.unshadowed_builtins.clear()
 
-    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 _as_rdict(self):
+        r_dict_content = self.initialize_as_rdict()
+        for k, cell in self.content.iteritems():
+            r_dict_content[self.space.wrap(k)] = cell.w_value
+            cell.invalidate()
+        for k in self.unshadowed_builtins:
+            self.invalidate_unshadowed_builtin(k)
+        self._clear_fields()
+        return self
 
-    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
+    def _clear_fields(self):
+        self.content = None
+        self.unshadowed_builtins = None
 
-class ModuleDictItemIteratorImplementation(IteratorImplementation):
+class ModuleDictIteratorImplementation(IteratorImplementation):
     def __init__(self, space, dictimplementation):
         IteratorImplementation.__init__(self, space, dictimplementation)
         self.iterator = dictimplementation.content.iteritems()
@@ -157,14 +140,9 @@
     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])
+            return (self.space.wrap(key), cell.w_value)
         else:
-            return None
-
-
-
-
-
+            return None, None
 
 
 class State(object):
@@ -217,8 +195,8 @@
     return None
 
 def getimplementation(w_dict):
-    if type(w_dict) is W_DictMultiObject:
-        return w_dict.implementation
+    if type(w_dict) is ModuleDictImplementation and w_dict.r_dict_content is None:
+        return w_dict
     else:
         return None
 
@@ -251,5 +229,5 @@
         if cell is not None:
             f.cache_for_globals[nameindex] = cell
             return cell.w_value
-    return f._load_global(f.getname_w(nameindex))
+    return f._load_global(f.getname_u(nameindex))
 load_global_fill_cache._dont_inline_ = True

Modified: pypy/trunk/pypy/objspace/std/dictmultiobject.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/dictmultiobject.py	(original)
+++ pypy/trunk/pypy/objspace/std/dictmultiobject.py	Tue Nov  3 11:42:42 2009
@@ -22,93 +22,246 @@
             space.is_w(w_lookup_type, space.w_float)
             )
 
+class W_DictMultiObject(W_Object):
+    from pypy.objspace.std.dicttype import dict_typedef as typedef
 
-# DictImplementation lattice
+    r_dict_content = None
 
-# a dictionary starts with an EmptyDictImplementation, and moves down
-# in this list:
-#
-#              EmptyDictImplementation
-#                /                 \
-#               |                   |
-#   StrDictImplementation           |
-#                \                 /
-#               RDictImplementation
-#
-# (in addition, any dictionary can go back to EmptyDictImplementation)
+    @staticmethod
+    def allocate_and_init_instance(space, w_type=None, module=False,
+                                   instance=False, classofinstance=None,
+                                   from_strdict_shared=None):
+        if from_strdict_shared is not None:
+            assert w_type is None
+            assert not module and not instance and classofinstance is None
+            w_self = StrDictImplementation(space)
+            w_self.content = from_strdict_shared
+            return w_self
+        if space.config.objspace.std.withcelldict and module:
+            from pypy.objspace.std.celldict import ModuleDictImplementation
+            assert w_type is None
+            return ModuleDictImplementation(space)
+        elif space.config.objspace.opcodes.CALL_LIKELY_BUILTIN and module:
+            assert w_type is None
+            return WaryDictImplementation(space)
+        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:
+            assert w_type is None
+            return StrDictImplementation(space)
+        else:
+            if w_type is None:
+                w_type = space.w_dict
+            w_self = space.allocate_instance(W_DictMultiObject, w_type)
+            W_DictMultiObject.__init__(w_self, space)
+            w_self.initialize_as_rdict()
+            return w_self
 
-class DictImplementation(object):
-    
-    def get(self, w_lookup):
+    def __init__(self, space):
+        self.space = space
+
+    def initialize_as_rdict(self):
+        assert self.r_dict_content is None
+        self.r_dict_content = r_dict(self.space.eq_w, self.space.hash_w)
+        return self.r_dict_content
+        
+
+    def initialize_content(w_self, list_pairs_w):
+        for w_k, w_v in list_pairs_w:
+            w_self.setitem(w_k, w_v)
+
+    def __repr__(w_self):
+        """ representation for debugging purposes """
+        return "%s()" % (w_self.__class__.__name__, )
+
+    def unwrap(w_dict, space):
+        result = {}
+        items = w_dict.items()
+        for w_pair in items:
+            key, val = space.unwrap(w_pair)
+            result[key] = val
+        return result
+
+    def missing_method(w_dict, space, w_key):
+        if not space.is_w(space.type(w_dict), space.w_dict):
+            w_missing = space.lookup(w_dict, "__missing__")
+            if w_missing is None:
+                return None
+            return space.call_function(w_missing, w_dict, w_key)
+        else:
+            return None
+
+    def set_str_keyed_item(w_dict, key, w_value, shadows_type=True):
+        w_dict.setitem_str(key, w_value, shadows_type)
+
+    # _________________________________________________________________ 
+    # implementation methods
+    def impl_getitem(self, w_key):
         #return w_value or None
         raise NotImplementedError("abstract base class")
 
-    def setitem_str(self,  w_key, w_value, shadows_type=True):
-        #return implementation
+    def impl_getitem_str(self, w_key):
+        #return w_value or None
         raise NotImplementedError("abstract base class")
 
-    def setitem(self,  w_key, w_value):
-        #return implementation
+    def impl_setitem_str(self,  key, w_value, shadows_type=True):
         raise NotImplementedError("abstract base class")
 
-    def delitem(self, w_key):
-        #return implementation
-        raise NotImplementedError("abstract base class")
- 
-    def length(self):
+    def impl_setitem(self,  w_key, w_value):
         raise NotImplementedError("abstract base class")
 
-    def iteritems(self):
+    def impl_delitem(self, w_key):
         raise NotImplementedError("abstract base class")
-    def iterkeys(self):
+ 
+    def impl_length(self):
         raise NotImplementedError("abstract base class")
-    def itervalues(self):
+
+    def impl_iter(self):
         raise NotImplementedError("abstract base class")
 
+    def impl_clear(self):
+        raise NotImplementedError("abstract base class")
 
-    def keys(self):
-        iterator = self.iterkeys()
+    def impl_keys(self):
+        iterator = self.impl_iter()
         result = []
         while 1:
-            w_key = iterator.next()
+            w_key, w_value = iterator.next()
             if w_key is not None:
                 result.append(w_key)
             else:
                 return result
-    def values(self):
-        iterator = self.itervalues()
+    def impl_values(self):
+        iterator = self.impl_iter()
         result = []
         while 1:
-            w_value = iterator.next()
+            w_key, w_value = iterator.next()
             if w_value is not None:
                 result.append(w_value)
             else:
                 return result
-    def items(self):
-        iterator = self.iteritems()
+    def impl_items(self):
+        iterator = self.impl_iter()
         result = []
         while 1:
-            w_item = iterator.next()
-            if w_item is not None:
-                result.append(w_item)
+            w_key, w_value = iterator.next()
+            if w_key is not None:
+                result.append(self.space.newtuple([w_key, w_value]))
             else:
                 return result
 
-#   the following method only makes sense when the option to use the
-#   CALL_LIKELY_BUILTIN opcode is set. Otherwise it won't even be seen
-#   by the annotator
-    def get_builtin_indexed(self, i):
-        w_key = self.space.wrap(OPTIMIZED_BUILTINS[i])
-        return self.get(w_key)
+    # the following method only makes sense when the option to use the
+    # CALL_LIKELY_BUILTIN opcode is set. Otherwise it won't even be seen
+    # by the annotator
+    def impl_get_builtin_indexed(self, i):
+        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):
+        return self.impl_fallback_setitem(self.space.wrap(key), w_value)
 
-# this method will only be seen whan a certain config option is used
-    def shadows_anything(self):
+    def impl_fallback_delitem(self, w_key):
+        del self.r_dict_content[w_key]
+        
+    def impl_fallback_length(self):
+        return len(self.r_dict_content)
+
+    def impl_fallback_getitem(self, w_key):
+        return self.r_dict_content.get(w_key, None)
+
+    def impl_fallback_getitem_str(self, key):
+        return self.r_dict_content.get(self.space.wrap(key), None)
+
+    def impl_fallback_iter(self):
+        return RDictIteratorImplementation(self.space, self)
+
+    def impl_fallback_keys(self):
+        return self.r_dict_content.keys()
+    def impl_fallback_values(self):
+        return self.r_dict_content.values()
+    def impl_fallback_items(self):
+        return [self.space.newtuple([w_key, w_val])
+                    for w_key, w_val in self.r_dict_content.iteritems()]
+
+    def impl_fallback_clear(self):
+        self.r_dict_content.clear()
+
+    def impl_fallback_get_builtin_indexed(self, i):
+        key = OPTIMIZED_BUILTINS[i]
+        return self.impl_fallback_getitem_str(key)
+
+    def impl_fallback_shadows_anything(self):
         return True
 
-    def set_shadows_anything(self):
+    def impl_fallback_set_shadows_anything(self):
         pass
 
 
+implementation_methods = [
+    ("getitem", 1),
+    ("getitem_str", 1),
+    ("length", 0),
+    ("setitem_str", 3),
+    ("setitem", 2),
+    ("delitem", 1),
+    ("iter", 0),
+    ("items", 0),
+    ("values", 0),
+    ("keys", 0),
+    ("clear", 0),
+    ("get_builtin_indexed", 1),
+    ("shadows_anything", 0),
+    ("set_shadows_anything", 0),
+]
+
+
+def _make_method(name, implname, fallback, numargs):
+    args = ", ".join(["a" + str(i) for i in range(numargs)])
+    code = """def %s(self, %s):
+        if self.r_dict_content is not None:
+            return self.%s(%s)
+        return self.%s(%s)""" % (name, args, fallback, args, implname, args)
+    d = {}
+    exec py.code.Source(code).compile() in d
+    implementation_method = d[name]
+    implementation_method.func_defaults = getattr(W_DictMultiObject, implname).func_defaults
+    return implementation_method
+
+def _install_methods():
+    for name, numargs in implementation_methods:
+        implname = "impl_" + name
+        fallbackname = "impl_fallback_" + name
+        func = _make_method(name, implname, fallbackname, numargs)
+        setattr(W_DictMultiObject, name, func)
+_install_methods()
+
+registerimplementation(W_DictMultiObject)
+
+# DictImplementation lattice
+# XXX fix me
+
 # Iterator Implementation base classes
 
 class IteratorImplementation(object):
@@ -120,19 +273,19 @@
 
     def next(self):
         if self.dictimplementation is None:
-            return None
+            return None, None
         if self.len != self.dictimplementation.length():
             self.len = -1   # Make this error state sticky
             raise OperationError(self.space.w_RuntimeError,
                      self.space.wrap("dictionary changed size during iteration"))
         # look for the next entry
-        w_result = self.next_entry()
-        if w_result is not None:
+        if self.pos < self.len:
+            result = self.next_entry()
             self.pos += 1
-            return w_result
+            return result
         # no more entries
         self.dictimplementation = None
-        return None
+        return None, None
 
     def next_entry(self):
         """ Purely abstract method
@@ -148,170 +301,92 @@
 
 # concrete subclasses of the above
 
-class EmptyDictImplementation(DictImplementation):
-    def __init__(self, space):
-        self.space = space
-
-    def get(self, w_lookup):
-        space = self.space
-        if not _is_str(space, w_lookup) and not _is_sane_hash(space,
-                                                        space.type(w_lookup)):
-            # give hash a chance to raise an exception
-            space.hash(w_lookup)
-        return None
-
-    def setitem(self, w_key, w_value):
-        space = self.space
-        if _is_str(space, w_key):
-            return StrDictImplementation(space).setitem_str(w_key, w_value)
-        else:
-            return space.DefaultDictImpl(space).setitem(w_key, w_value)
-    def setitem_str(self, w_key, w_value, shadows_type=True):
-        return StrDictImplementation(self.space).setitem_str(w_key, w_value)
-        #return SmallStrDictImplementation(self.space, w_key, w_value)
-
-    def delitem(self, w_key):
-        space = self.space
-        if not _is_str(space, w_key) and not _is_sane_hash(space,
-                                                           space.type(w_key)):
-            # count hash
-            space.hash(w_key)
-        raise KeyError
-    
-    def length(self):
-        return 0
-
-    def iteritems(self):
-        return EmptyIteratorImplementation(self.space, self)
-    def iterkeys(self):
-        return EmptyIteratorImplementation(self.space, self)
-    def itervalues(self):
-        return EmptyIteratorImplementation(self.space, self)
-
-    def keys(self):
-        return []
-    def values(self):
-        return []
-    def items(self):
-        return []
-
-class EmptyIteratorImplementation(IteratorImplementation):
-    def next_entry(self):
-        return None
-
-
-class StrDictImplementation(DictImplementation):
+class StrDictImplementation(W_DictMultiObject):
     def __init__(self, space):
         self.space = space
         self.content = {}
         
-    def setitem(self, w_key, w_value):
+    def impl_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)
+            self.impl_setitem_str(self.space.str_w(w_key), w_value)
         else:
-            return self._as_rdict().setitem(w_key, w_value)
+            self._as_rdict().setitem(w_key, w_value)
 
-    def setitem_str(self, w_key, w_value, shadows_type=True):
-        self.content[self.space.str_w(w_key)] = w_value
-        return self
+    def impl_setitem_str(self, key, w_value, shadows_type=True):
+        self.content[key] = w_value
 
-    def delitem(self, w_key):
+    def impl_delitem(self, w_key):
         space = self.space
         w_key_type = space.type(w_key)
         if space.is_w(w_key_type, space.w_str):
             del self.content[space.str_w(w_key)]
-            if self.content:
-                return self
-            else:
-                return space.emptydictimpl
+            return
         elif _is_sane_hash(space, w_key_type):
             raise KeyError
         else:
-            return self._as_rdict().delitem(w_key)
+            self._as_rdict().delitem(w_key)
         
-    def length(self):
+    def impl_length(self):
         return len(self.content)
 
-    def get(self, w_lookup):
+    def impl_getitem_str(self, key):
+        return self.content.get(key, None)
+
+    def impl_getitem(self, w_key):
         space = self.space
         # -- This is called extremely often.  Hack for performance --
-        if type(w_lookup) is space.StringObjectCls:
-            return self.content.get(w_lookup.unwrap(space), None)
+        if type(w_key) is space.StringObjectCls:
+            return self.impl_getitem_str(w_key.unwrap(space))
         # -- End of performance hack --
-        w_lookup_type = space.type(w_lookup)
+        w_lookup_type = space.type(w_key)
         if space.is_w(w_lookup_type, space.w_str):
-            return self.content.get(space.str_w(w_lookup), None)
+            return self.impl_getitem_str(space.str_w(w_key))
         elif _is_sane_hash(space, w_lookup_type):
             return None
         else:
-            return self._as_rdict().get(w_lookup)
+            return self._as_rdict().getitem(w_key)
 
-    def iteritems(self):
-        return StrItemIteratorImplementation(self.space, self)
+    def impl_iter(self):
+        return StrIteratorImplementation(self.space, self)
 
-    def iterkeys(self):
-        return StrKeyIteratorImplementation(self.space, self)
-
-    def itervalues(self):
-        return StrValueIteratorImplementation(self.space, self)
-
-    def keys(self):
+    def impl_keys(self):
         space = self.space
         return [space.wrap(key) for key in self.content.iterkeys()]
 
-    def values(self):
+    def impl_values(self):
         return self.content.values()
 
-    def items(self):
+    def impl_items(self):
         space = self.space
         return [space.newtuple([space.wrap(key), w_value])
                     for (key, w_value) in self.content.iteritems()]
 
+    def impl_clear(self):
+        self.content.clear()
+
 
     def _as_rdict(self):
-        newimpl = self.space.DefaultDictImpl(self.space)
+        r_dict_content = self.initialize_as_rdict()
         for k, w_v in self.content.items():
-            newimpl.setitem(self.space.wrap(k), w_v)
-        return newimpl
-
-# the following are very close copies of the base classes above
-
-class StrKeyIteratorImplementation(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 StrValueIteratorImplementation(IteratorImplementation):
-    def __init__(self, space, dictimplementation):
-        IteratorImplementation.__init__(self, space, dictimplementation)
-        self.iterator = dictimplementation.content.itervalues()
+            r_dict_content[self.space.wrap(k)] = w_v
+        self._clear_fields()
+        return self
 
-    def next_entry(self):
-        # note that this 'for' loop only runs once, at most
-        for w_value in self.iterator:
-            return w_value
-        else:
-            return None
+    def _clear_fields(self):
+        self.content = None
 
-class StrItemIteratorImplementation(IteratorImplementation):
+class StrIteratorImplementation(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, w_value in self.iterator:
-            return self.space.newtuple([self.space.wrap(key), w_value])
+        for str, w_value in self.iterator:
+            return self.space.wrap(str), w_value
         else:
-            return None
+            return None, None
 
 
 class ShadowDetectingDictImplementation(StrDictImplementation):
@@ -324,29 +399,29 @@
         else:
             self._shadows_anything = False
 
-    def setitem_str(self, w_key, w_value, shadows_type=True):
+    def impl_setitem_str(self, key, w_value, shadows_type=True):
         if shadows_type:
             self._shadows_anything = True
-        return StrDictImplementation.setitem_str(
-            self, w_key, w_value, shadows_type)
+        StrDictImplementation.impl_setitem_str(
+            self, key, w_value, shadows_type)
 
-    def setitem(self, w_key, w_value):
+    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
-            return StrDictImplementation.setitem_str(
-                self, w_key, w_value, False)
+            StrDictImplementation.impl_setitem_str(
+                self, self.space.str_w(w_key), w_value, False)
         else:
-            return self._as_rdict().setitem(w_key, w_value)
+            self._as_rdict().setitem(w_key, w_value)
 
-    def shadows_anything(self):
+    def impl_shadows_anything(self):
         return (self._shadows_anything or 
                 self.w_type.version_tag is not self.original_version_tag)
 
-    def set_shadows_anything(self):
+    def impl_set_shadows_anything(self):
         self._shadows_anything = True
 
 class WaryDictImplementation(StrDictImplementation):
@@ -354,15 +429,13 @@
         StrDictImplementation.__init__(self, space)
         self.shadowed = [None] * len(BUILTIN_TO_INDEX)
 
-    def setitem_str(self, w_key, w_value, shadows_type=True):
-        key = self.space.str_w(w_key)
+    def impl_setitem_str(self, key, w_value, shadows_type=True):
         i = BUILTIN_TO_INDEX.get(key, -1)
         if i != -1:
             self.shadowed[i] = w_value
         self.content[key] = w_value
-        return self
 
-    def delitem(self, w_key):
+    def impl_delitem(self, w_key):
         space = self.space
         w_key_type = space.type(w_key)
         if space.is_w(w_key_type, space.w_str):
@@ -371,96 +444,30 @@
             i = BUILTIN_TO_INDEX.get(key, -1)
             if i != -1:
                 self.shadowed[i] = None
-            return self
         elif _is_sane_hash(space, w_key_type):
             raise KeyError
         else:
-            return self._as_rdict().delitem(w_key)
+            self._as_rdict().delitem(w_key)
 
-    def get_builtin_indexed(self, i):
+    def impl_get_builtin_indexed(self, i):
         return self.shadowed[i]
 
-class RDictImplementation(DictImplementation):
-    def __init__(self, space):
-        self.space = space
-        self.content = r_dict(space.eq_w, space.hash_w)
-
-    def __repr__(self):
-        return "%s<%s>" % (self.__class__.__name__, self.content)
-        
-    def setitem(self, w_key, w_value):
-        self.content[w_key] = w_value
-        return self
-
-    def setitem_str(self, w_key, w_value, shadows_type=True):
-        return self.setitem(w_key, w_value)
-
-    def delitem(self, w_key):
-        del self.content[w_key]
-        if self.content:
-            return self
-        else:
-            return self.space.emptydictimpl
-        
-    def length(self):
-        return len(self.content)
-    def get(self, w_lookup):
-        return self.content.get(w_lookup, None)
-
-    def iteritems(self):
-        return RDictItemIteratorImplementation(self.space, self)
-    def iterkeys(self):
-        return RDictKeyIteratorImplementation(self.space, self)
-    def itervalues(self):
-        return RDictValueIteratorImplementation(self.space, self)
-
-    def keys(self):
-        return self.content.keys()
-    def values(self):
-        return self.content.values()
-    def items(self):
-        return [self.space.newtuple([w_key, w_val])
-                    for w_key, w_val in self.content.iteritems()]
-
-
-class RDictKeyIteratorImplementation(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 w_key in self.iterator:
-            return w_key
-        else:
-            return None
-
-class RDictValueIteratorImplementation(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 w_value in self.iterator:
-            return w_value
-        else:
-            return None
-
-class RDictItemIteratorImplementation(IteratorImplementation):
+class RDictIteratorImplementation(IteratorImplementation):
     def __init__(self, space, dictimplementation):
         IteratorImplementation.__init__(self, space, dictimplementation)
-        self.iterator = dictimplementation.content.iteritems()
+        self.iterator = dictimplementation.r_dict_content.iteritems()
 
     def next_entry(self):
         # note that this 'for' loop only runs once, at most
-        for w_key, w_value in self.iterator:
-            return self.space.newtuple([w_key, w_value])
+        for item in self.iterator:
+            return item
         else:
-            return None
+            return None, None
 
 
 
+# XXX fix this thing
 import time, py
 
 class DictInfo(object):
@@ -518,7 +525,7 @@
     def __del__(self):
         self.info.lifetime = time.time() - self.info.createtime
 
-class MeasuringDictImplementation(DictImplementation):
+class MeasuringDictImplementation(W_DictMultiObject):
     def __init__(self, space):
         self.space = space
         self.content = r_dict(space.eq_w, space.hash_w)
@@ -544,7 +551,7 @@
         else:
             self.info.misses += 1
 
-    def setitem(self, w_key, w_value):
+    def impl_setitem(self, w_key, w_value):
         if not self.info.seen_non_string_in_write and not self._is_str(w_key):
             self.info.seen_non_string_in_write = True
             self.info.size_on_non_string_seen_in_write = len(self.content)
@@ -552,11 +559,10 @@
         self.info.writes += 1
         self.content[w_key] = w_value
         self.info.maxcontents = max(self.info.maxcontents, len(self.content))
-        return self
-    def setitem_str(self, w_key, w_value, shadows_type=True):
+    def impl_setitem_str(self, key, w_value, shadows_type=True):
         self.info.setitem_strs += 1
-        return self.setitem(w_key, w_value)
-    def delitem(self, w_key):
+        self.impl_setitem(self.space.wrap(key), w_value)
+    def impl_delitem(self, w_key):
         if not self.info.seen_non_string_in_write \
                and not self.info.seen_non_string_in_read_first \
                and not self._is_str(w_key):
@@ -565,38 +571,39 @@
         self.info.delitems += 1
         self.info.writes += 1
         del self.content[w_key]
-        return self
 
-    def length(self):
+    def impl_length(self):
         self.info.lengths += 1
         return len(self.content)
-    def get(self, w_lookup):
+    def impl_getitem_str(self, key):
+        return self.impl_getitem(self.space.wrap(key))
+    def impl_getitem(self, w_key):
         self.info.gets += 1
-        self._read(w_lookup)
-        return self.content.get(w_lookup, None)
+        self._read(w_key)
+        return self.content.get(w_key, None)
 
-    def iteritems(self):
+    def impl_iteritems(self):
         self.info.iteritems += 1
         self.info.iterations += 1
         return RDictItemIteratorImplementation(self.space, self)
-    def iterkeys(self):
+    def impl_iterkeys(self):
         self.info.iterkeys += 1
         self.info.iterations += 1
         return RDictKeyIteratorImplementation(self.space, self)
-    def itervalues(self):
+    def impl_itervalues(self):
         self.info.itervalues += 1
         self.info.iterations += 1
         return RDictValueIteratorImplementation(self.space, self)
 
-    def keys(self):
+    def impl_keys(self):
         self.info.keys += 1
         self.info.listings += 1
         return self.content.keys()
-    def values(self):
+    def impl_values(self):
         self.info.values += 1
         self.info.listings += 1
         return self.content.values()
-    def items(self):
+    def impl_items(self):
         self.info.items += 1
         self.info.listings += 1
         return [self.space.newtuple([w_key, w_val])
@@ -630,71 +637,6 @@
     os.close(fd)
     os.write(2, "Reporting done.\n")
 
-class W_DictMultiObject(W_Object):
-    from pypy.objspace.std.dicttype import dict_typedef as typedef
-
-    def __init__(w_self, space, module=False, sharing=False):
-        if space.config.objspace.std.withcelldict and module:
-            from pypy.objspace.std.celldict import ModuleDictImplementation
-            w_self.implementation = ModuleDictImplementation(space)
-        elif space.config.objspace.opcodes.CALL_LIKELY_BUILTIN and module:
-            w_self.implementation = WaryDictImplementation(space)
-        elif space.config.objspace.std.withdictmeasurement:
-            w_self.implementation = MeasuringDictImplementation(space)
-        elif space.config.objspace.std.withsharingdict and sharing:
-            from pypy.objspace.std.sharingdict import SharedDictImplementation
-            w_self.implementation = SharedDictImplementation(space)
-        else:
-            w_self.implementation = space.emptydictimpl
-        w_self.space = space
-
-    def initialize_content(w_self, list_pairs_w):
-        impl = w_self.implementation
-        for w_k, w_v in list_pairs_w:
-            impl = impl.setitem(w_k, w_v)
-        w_self.implementation = impl
-
-    def initialize_from_strdict_shared(w_self, strdict):
-        impl = StrDictImplementation(w_self.space)
-        impl.content = strdict
-        w_self.implementation = impl
-
-    def __repr__(w_self):
-        """ representation for debugging purposes """
-        return "%s(%s)" % (w_self.__class__.__name__, w_self.implementation)
-
-    def unwrap(w_dict, space):
-        result = {}
-        items = w_dict.implementation.items()
-        for w_pair in items:
-            key, val = space.unwrap(w_pair)
-            result[key] = val
-        return result
-
-    def missing_method(w_dict, space, w_key):
-        if not space.is_w(space.type(w_dict), space.w_dict):
-            w_missing = space.lookup(w_dict, "__missing__")
-            if w_missing is None:
-                return None
-            return space.call_function(w_missing, w_dict, w_key)
-        else:
-            return None
-
-    def len(w_self):
-        return w_self.implementation.length()
-
-    def get(w_dict, w_key, w_default):
-        w_value = w_dict.implementation.get(w_key)
-        if w_value is not None:
-            return w_value
-        else:
-            return w_default
-
-    def set_str_keyed_item(w_dict, w_key, w_value, shadows_type=True):
-        w_dict.implementation = w_dict.implementation.setitem_str(
-            w_key, w_value, shadows_type)
-
-registerimplementation(W_DictMultiObject)
 
 
 init_signature = Signature(['seq_or_map'], None, 'kwargs')
@@ -715,7 +657,7 @@
                 raise OperationError(space.w_ValueError,
                              space.wrap("dict() takes a sequence of pairs"))
             w_k, w_v = pair
-            w_dict.implementation = w_dict.implementation.setitem(w_k, w_v)
+            w_dict.setitem(w_k, w_v)
     else:
         if space.is_true(w_src):
             from pypy.objspace.std.dicttype import update1
@@ -724,71 +666,67 @@
         from pypy.objspace.std.dicttype import update1
         update1(space, w_dict, w_kwds)
 
-def getitem__DictMulti_ANY(space, w_dict, w_lookup):
-    w_value = w_dict.implementation.get(w_lookup)
+def getitem__DictMulti_ANY(space, w_dict, w_key):
+    w_value = w_dict.getitem(w_key)
     if w_value is not None:
         return w_value
 
-    w_missing_item = w_dict.missing_method(space, w_lookup)
+    w_missing_item = w_dict.missing_method(space, w_key)
     if w_missing_item is not None:
         return w_missing_item
 
-    space.raise_key_error(w_lookup)
+    space.raise_key_error(w_key)
 
 def setitem__DictMulti_ANY_ANY(space, w_dict, w_newkey, w_newvalue):
-    w_dict.implementation = w_dict.implementation.setitem(w_newkey, w_newvalue)
+    w_dict.setitem(w_newkey, w_newvalue)
 
-def delitem__DictMulti_ANY(space, w_dict, w_lookup):
+def delitem__DictMulti_ANY(space, w_dict, w_key):
     try:
-        w_dict.implementation = w_dict.implementation.delitem(w_lookup)
+        w_dict.delitem(w_key)
     except KeyError:
-        space.raise_key_error(w_lookup)
+        space.raise_key_error(w_key)
     
 def len__DictMulti(space, w_dict):
-    return space.wrap(w_dict.implementation.length())
+    return space.wrap(w_dict.length())
 
-def contains__DictMulti_ANY(space, w_dict, w_lookup):
-    return space.newbool(w_dict.implementation.get(w_lookup) is not None)
+def contains__DictMulti_ANY(space, w_dict, w_key):
+    return space.newbool(w_dict.getitem(w_key) is not None)
 
 dict_has_key__DictMulti_ANY = contains__DictMulti_ANY
 
 def iter__DictMulti(space, w_dict):
-    return W_DictMultiIterObject(space, w_dict.implementation.iterkeys())
+    return W_DictMultiIterObject(space, w_dict.iter(), KEYSITER)
 
 def eq__DictMulti_DictMulti(space, w_left, w_right):
     if space.is_w(w_left, w_right):
         return space.w_True
 
-    if w_left.implementation.length() != w_right.implementation.length():
+    if w_left.length() != w_right.length():
         return space.w_False
-    iteratorimplementation = w_left.implementation.iteritems()
+    iteratorimplementation = w_left.iter()
     while 1:
-        w_item = iteratorimplementation.next()
-        if w_item is None:
+        w_key, w_val = iteratorimplementation.next()
+        if w_key is None:
             break
-        w_key = space.getitem(w_item, space.wrap(0))
-        w_val = space.getitem(w_item, space.wrap(1))
-        w_rightval = w_right.implementation.get(w_key)
+        w_rightval = w_right.getitem(w_key)
         if w_rightval is None:
             return space.w_False
         if not space.eq_w(w_val, w_rightval):
             return space.w_False
     return space.w_True
 
-def characterize(space, aimpl, bimpl):
+def characterize(space, w_a, w_b):
     """ (similar to CPython) 
     returns the smallest key in acontent for which b's value is different or absent and this value """
     w_smallest_diff_a_key = None
     w_its_value = None
-    iteratorimplementation = aimpl.iteritems()
+    iteratorimplementation = w_a.iter()
     while 1:
-        w_item = iteratorimplementation.next()
-        if w_item is None:
+        w_key, w_val = iteratorimplementation.next()
+        if w_key is None:
             break
-        w_key = space.getitem(w_item, space.wrap(0))
-        w_val = space.getitem(w_item, space.wrap(1))
         if w_smallest_diff_a_key is None or space.is_true(space.lt(w_key, w_smallest_diff_a_key)):
-            w_bvalue = bimpl.get(w_key)
+            w_bvalue = w_b.getitem(w_key)
             if w_bvalue is None:
                 w_its_value = w_val
                 w_smallest_diff_a_key = w_key
@@ -800,18 +738,16 @@
 
 def lt__DictMulti_DictMulti(space, w_left, w_right):
     # Different sizes, no problem
-    leftimpl = w_left.implementation
-    rightimpl = w_right.implementation
-    if leftimpl.length() < rightimpl.length():
+    if w_left.length() < w_right.length():
         return space.w_True
-    if leftimpl.length() > rightimpl.length():
+    if w_left.length() > w_right.length():
         return space.w_False
 
     # Same size
-    w_leftdiff, w_leftval = characterize(space, leftimpl, rightimpl)
+    w_leftdiff, w_leftval = characterize(space, w_left, w_right)
     if w_leftdiff is None:
         return space.w_False
-    w_rightdiff, w_rightval = characterize(space, rightimpl, leftimpl)
+    w_rightdiff, w_rightval = characterize(space, w_right, w_left)
     if w_rightdiff is None:
         # w_leftdiff is not None, w_rightdiff is None
         return space.w_True 
@@ -824,47 +760,51 @@
 
 def dict_copy__DictMulti(space, w_self):
     from pypy.objspace.std.dicttype import update1
-    w_new = W_DictMultiObject(space)
+    w_new = W_DictMultiObject.allocate_and_init_instance(space)
     update1(space, w_new, w_self)
     return w_new
 
 def dict_items__DictMulti(space, w_self):
-    return space.newlist(w_self.implementation.items())
+    return space.newlist(w_self.items())
 
 def dict_keys__DictMulti(space, w_self):
-    return space.newlist(w_self.implementation.keys())
+    return space.newlist(w_self.keys())
 
 def dict_values__DictMulti(space, w_self):
-    return space.newlist(w_self.implementation.values())
+    return space.newlist(w_self.values())
 
 def dict_iteritems__DictMulti(space, w_self):
-    return W_DictMultiIterObject(space, w_self.implementation.iteritems())
+    return W_DictMultiIterObject(space, w_self.iter(), ITEMSITER)
 
 def dict_iterkeys__DictMulti(space, w_self):
-    return W_DictMultiIterObject(space, w_self.implementation.iterkeys())
+    return W_DictMultiIterObject(space, w_self.iter(), KEYSITER)
 
 def dict_itervalues__DictMulti(space, w_self):
-    return W_DictMultiIterObject(space, w_self.implementation.itervalues())
+    return W_DictMultiIterObject(space, w_self.iter(), VALUESITER)
 
 def dict_clear__DictMulti(space, w_self):
-    w_self.implementation = space.emptydictimpl
+    w_self.clear()
 
-def dict_get__DictMulti_ANY_ANY(space, w_dict, w_lookup, w_default):
-    return w_dict.get(w_lookup, w_default)
+def dict_get__DictMulti_ANY_ANY(space, w_dict, w_key, w_default):
+    w_value = w_dict.getitem(w_key)
+    if w_value is not None:
+        return w_value
+    else:
+        return w_default
 
 def dict_pop__DictMulti_ANY(space, w_dict, w_key, w_defaults):
     defaults = space.unpackiterable(w_defaults)
     len_defaults = len(defaults)
     if len_defaults > 1:
         raise OperationError(space.w_TypeError, space.wrap("pop expected at most 2 arguments, got %d" % (1 + len_defaults, )))
-    w_item = w_dict.implementation.get(w_key)
+    w_item = w_dict.getitem(w_key)
     if w_item is None:
         if len_defaults > 0:
             return defaults[0]
         else:
             space.raise_key_error(w_key)
     else:
-        w_dict.implementation.delitem(w_key)
+        w_dict.delitem(w_key)
         return w_item
 
 app = gateway.applevel('''
@@ -895,7 +835,7 @@
 dictrepr = app.interphook("dictrepr")
 
 def repr__DictMulti(space, w_dict):
-    if w_dict.implementation.length() == 0:
+    if w_dict.length() == 0:
         return space.wrap('{}')
     ec = space.getexecutioncontext()
     w_currently_in_repr = ec._py_repr
@@ -908,12 +848,17 @@
 # Iteration
 
 
+KEYSITER = 0
+ITEMSITER = 1
+VALUESITER = 2
+
 class W_DictMultiIterObject(W_Object):
     from pypy.objspace.std.dicttype import dictiter_typedef as typedef
 
-    def __init__(w_self, space, iteratorimplementation):
+    def __init__(w_self, space, iteratorimplementation, itertype):
         w_self.space = space
         w_self.iteratorimplementation = iteratorimplementation
+        w_self.itertype = itertype
 
 registerimplementation(W_DictMultiIterObject)
 
@@ -922,16 +867,19 @@
 
 def next__DictMultiIterObject(space, w_dictiter):
     iteratorimplementation = w_dictiter.iteratorimplementation
-    w_result = iteratorimplementation.next()
-    if w_result is not None:
-        return w_result
+    w_key, w_value = iteratorimplementation.next()
+    if w_key is not None:
+        itertype = w_dictiter.itertype
+        if itertype == KEYSITER:
+            return w_key
+        elif itertype == VALUESITER:
+            return w_value
+        elif itertype == ITEMSITER:
+            return space.newtuple([w_key, w_value])
+        else:
+            assert 0, "should be unreachable"
     raise OperationError(space.w_StopIteration, space.w_None)
 
-# XXX __length_hint__()
-##def len__DictMultiIterObject(space, w_dictiter):
-##    iteratorimplementation = w_dictiter.iteratorimplementation
-##    return space.wrap(iteratorimplementation.length())
-
 # ____________________________________________________________
 
 from pypy.objspace.std import dicttype

Modified: pypy/trunk/pypy/objspace/std/dicttype.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/dicttype.py	(original)
+++ pypy/trunk/pypy/objspace/std/dicttype.py	Tue Nov  3 11:42:42 2009
@@ -141,8 +141,8 @@
 # ____________________________________________________________
 
 def descr__new__(space, w_dicttype, __args__):
-    w_obj = space.allocate_instance(space.DictObjectCls, w_dicttype)
-    space.DictObjectCls.__init__(w_obj, space)
+    from pypy.objspace.std.dictmultiobject import W_DictMultiObject
+    w_obj = W_DictMultiObject.allocate_and_init_instance(space, w_dicttype)
     return w_obj
 
 # ____________________________________________________________

Added: pypy/trunk/pypy/objspace/std/inlinedict.py
==============================================================================
--- (empty file)
+++ pypy/trunk/pypy/objspace/std/inlinedict.py	Tue Nov  3 11:42:42 2009
@@ -0,0 +1,139 @@
+import py
+from pypy.interpreter.typedef import check_new_dictionary
+from pypy.objspace.std.dictmultiobject import W_DictMultiObject
+from pypy.objspace.std.dictmultiobject import StrDictImplementation
+from pypy.objspace.std.dictmultiobject import IteratorImplementation
+from pypy.objspace.std.dictmultiobject import implementation_methods
+from pypy.tool.sourcetools import func_with_new_name
+
+def make_mixin(config):
+    if config.objspace.std.withsharingdict:
+        from pypy.objspace.std.sharingdict import SharedDictImplementation
+        return make_inlinedict_mixin(SharedDictImplementation, "structure")
+    else:
+        return make_inlinedict_mixin(StrDictImplementation, "content")
+
+def make_indirection_method(methname, numargs):
+    # *args don't work, the call normalization gets confused
+    args = ", ".join(["a" + str(i) for i in range(numargs)])
+    code = """def f(self, %s):
+    return self.w_obj.%s(%s)
+""" % (args, methname, args)
+    d = {}
+    exec py.code.Source(code).compile() in d
+    func = d["f"]
+    func.func_name = methname + "_indirect"
+    func.func_defaults = getattr(W_DictMultiObject, methname).func_defaults
+    return func
+
+def make_inlinedict_mixin(dictimplclass, attrname):
+    assert dictimplclass.__base__ is W_DictMultiObject
+    class IndirectionIterImplementation(IteratorImplementation):
+        def __init__(self, space, dictimpl, itemlist):
+            IteratorImplementation.__init__(self, space, dictimpl)
+            self.itemlist = itemlist
+
+        def next_entry(self):
+            return self.itemlist[self.pos]
+            
+    class IndirectionDictImplementation(W_DictMultiObject):
+        def __init__(self, space, w_obj):
+            self.space = space
+            self.w_obj = w_obj
+
+        def impl_iter(self):
+            # XXX sucky
+            items = []
+            for w_item in self.impl_items():
+                w_key, w_value = self.space.viewiterable(w_item)
+                items.append((w_key, w_value))
+            return IndirectionIterImplementation(self.space, self, items)
+
+    IndirectionDictImplementation.__name__ = "IndirectionDictImplementation" + dictimplclass.__name__
+
+    for methname, numargs in implementation_methods:
+        implname = "impl_" + methname
+        if implname != "impl_iter":
+            setattr(IndirectionDictImplementation, implname,
+                    make_indirection_method(implname, numargs))
+
+    init_dictattributes = func_with_new_name(dictimplclass.__init__.im_func,
+                                             "init_dictattributes")
+    make_rdict = func_with_new_name(dictimplclass._as_rdict.im_func,
+                                    "make_rdict")
+    clear_fields = func_with_new_name(dictimplclass._clear_fields.im_func,
+                                      "clear_fields")
+
+    class InlineDictMixin(object):
+
+        def user_setup(self, space, w_subtype):
+            self.space = space
+            self.w__class__ = w_subtype
+            self.w__dict__ = None
+            init_dictattributes(self, space)
+            assert getattr(self, attrname) is not None
+            self.user_setup_slots(w_subtype.nslots)
+
+        def getdict(self):
+            w__dict__ = self.w__dict__
+            if w__dict__ is None:
+                w__dict__ = IndirectionDictImplementation(self.space, self)
+                self.w__dict__ = w__dict__
+            assert isinstance(w__dict__, W_DictMultiObject)
+            return w__dict__
+
+        def _inlined_dict_valid(self):
+            return getattr(self, attrname) is not None
+
+        def getdictvalue(self, space, attr):
+            if self._inlined_dict_valid():
+                return self.impl_getitem_str(attr)
+            w_dict = self.getdict()
+            return w_dict.getitem_str(attr)
+
+        def getdictvalue_attr_is_in_class(self, space, attr):
+            return self.getdictvalue(space, attr)
+
+        def setdictvalue(self, space, attr, w_value, shadows_type=True):
+            if self._inlined_dict_valid():
+                # XXX don't ignore shadows_type
+                self.impl_setitem_str(attr, w_value)
+                return True
+            w_dict = self.getdict()
+            w_dict.setitem_str(attr, w_value)
+            return True
+
+        def deldictvalue(self, space, w_attr):
+            if self._inlined_dict_valid():
+                try:
+                    self.impl_delitem(w_attr)
+                except KeyError:
+                    return False
+                return True
+            w_dict = self.getdict()
+            try:
+                w_dict.delitem(w_attr)
+            except KeyError:
+                return False
+            return True
+
+        def setdict(self, space, w_dict):
+            self._clear_fields() # invalidate attributes on self
+            self.w__dict__ = check_new_dictionary(space, w_dict)
+
+        def _as_rdict(self):
+            make_rdict(self)
+            return self.getdict()
+
+        def initialize_as_rdict(self):
+            return self.getdict().initialize_as_rdict()
+        
+        _clear_fields = clear_fields
+
+    for methname, _ in implementation_methods:
+        implname = "impl_" + methname
+        meth = func_with_new_name(getattr(dictimplclass, implname).im_func,
+                                  implname)
+        if not hasattr(InlineDictMixin, implname):
+            setattr(InlineDictMixin, implname, meth)
+    return InlineDictMixin

Modified: pypy/trunk/pypy/objspace/std/marshal_impl.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/marshal_impl.py	(original)
+++ pypy/trunk/pypy/objspace/std/marshal_impl.py	Tue Nov  3 11:42:42 2009
@@ -355,7 +355,7 @@
 
 def marshal_w__DictMulti(space, w_dict, m):
     m.start(TYPE_DICT)
-    for w_tuple in w_dict.implementation.items():
+    for w_tuple in w_dict.items():
         w_key, w_value = space.viewiterable(w_tuple, 2)
         m.put_w_obj(w_key)
         m.put_w_obj(w_value)

Modified: pypy/trunk/pypy/objspace/std/model.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/model.py	(original)
+++ pypy/trunk/pypy/objspace/std/model.py	Tue Nov  3 11:42:42 2009
@@ -26,6 +26,7 @@
 
     def __init__(self, config):
         """NOT_RPYTHON: inititialization only"""
+        self.config = config
         # All the Python types that we want to provide in this StdObjSpace
         class result:
             from pypy.objspace.std.objecttype import object_typedef
@@ -250,7 +251,7 @@
             for cls in self.typeorder:
                 if (hasattr(cls, 'typedef') and cls.typedef is not None and
                     cls.typedef.acceptable_as_base_class):
-                    subclslist = enum_interplevel_subclasses(cls)
+                    subclslist = enum_interplevel_subclasses(self.config, cls)
                     for subcls in subclslist:
                         if cls in subcls.__bases__:   # only direct subclasses
                             # for user subclasses we only accept "generic"

Modified: pypy/trunk/pypy/objspace/std/objectobject.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/objectobject.py	(original)
+++ pypy/trunk/pypy/objspace/std/objectobject.py	Tue Nov  3 11:42:42 2009
@@ -1,4 +1,4 @@
-from pypy.objspace.std.objspace import *
+from pypy.objspace.std.objspace import W_Object, register_all
 
 
 class W_ObjectObject(W_Object):

Modified: pypy/trunk/pypy/objspace/std/objecttype.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/objecttype.py	(original)
+++ pypy/trunk/pypy/objspace/std/objecttype.py	Tue Nov  3 11:42:42 2009
@@ -63,7 +63,6 @@
                                  space.wrap("default __new__ takes "
                                             "no parameters"))
     w_obj = space.allocate_instance(W_ObjectObject, w_type)
-    #W_ObjectObject.__init__(w_obj)
     return w_obj
 
 def descr__init__(space, w_obj, __args__):

Modified: pypy/trunk/pypy/objspace/std/objspace.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/objspace.py	(original)
+++ pypy/trunk/pypy/objspace/std/objspace.py	Tue Nov  3 11:42:42 2009
@@ -140,13 +140,13 @@
                     w_globals = f.w_globals
                     num = oparg >> 8
                     assert isinstance(w_globals, W_DictMultiObject)
-                    w_value = w_globals.implementation.get_builtin_indexed(num)
+                    w_value = w_globals.get_builtin_indexed(num)
                     if w_value is None:
                         builtins = f.get_builtin()
                         assert isinstance(builtins, Module)
                         w_builtin_dict = builtins.w_dict
                         assert isinstance(w_builtin_dict, W_DictMultiObject)
-                        w_value = w_builtin_dict.implementation.get_builtin_indexed(num)
+                        w_value = w_builtin_dict.get_builtin_indexed(num)
         ##                 if w_value is not None:
         ##                     print "CALL_LIKELY_BUILTIN fast"
                     if w_value is None:
@@ -240,16 +240,9 @@
 
         self.FrameClass = StdObjSpaceFrame
 
-        # XXX store the dict class on the space to access it in various places
+        # store the dict class on the space to access it in various places
         from pypy.objspace.std import dictmultiobject
         self.DictObjectCls = dictmultiobject.W_DictMultiObject
-        self.emptydictimpl = dictmultiobject.EmptyDictImplementation(self)
-        if self.config.objspace.std.withbucketdict:
-            from pypy.objspace.std import dictbucket
-            self.DefaultDictImpl = dictbucket.BucketDictImplementation
-        else:
-            self.DefaultDictImpl = dictmultiobject.RDictImplementation
-        assert self.DictObjectCls in self.model.typeorder
 
         from pypy.objspace.std import tupleobject
         self.TupleObjectCls = tupleobject.W_TupleObject
@@ -577,11 +570,13 @@
         from pypy.objspace.std.listobject import W_ListObject
         return W_ListObject(list_w)
 
-    def newdict(self, module=False):
+    def newdict(self, module=False, instance=False, classofinstance=None,
+                from_strdict_shared=None):
         from pypy.objspace.std.dictmultiobject import W_DictMultiObject
-        if module:
-            return W_DictMultiObject(self, module=True)
-        return W_DictMultiObject(self)
+        return W_DictMultiObject.allocate_and_init_instance(
+                self, module=module, instance=instance,
+                classofinstance=classofinstance,
+                from_strdict_shared=from_strdict_shared)
 
     def newslice(self, w_start, w_end, w_step):
         return W_SliceObject(w_start, w_end, w_step)
@@ -615,12 +610,14 @@
         user-defined type, without actually __init__ializing the instance."""
         w_type = self.gettypeobject(cls.typedef)
         if self.is_w(w_type, w_subtype):
-            instance =  instantiate(cls)
+            instance = instantiate(cls)
         elif cls.typedef.acceptable_as_base_class:
             # the purpose of the above check is to avoid the code below
             # to be annotated at all for 'cls' if it is not necessary
             w_subtype = w_type.check_user_subclass(w_subtype)
-            subcls = get_unique_interplevel_subclass(cls, w_subtype.hasdict, w_subtype.nslots != 0, w_subtype.needsdel, w_subtype.weakrefable)
+            subcls = get_unique_interplevel_subclass(
+                    self.config, cls, w_subtype.hasdict, w_subtype.nslots != 0,
+                    w_subtype.needsdel, w_subtype.weakrefable)
             instance = instantiate(subcls)
             instance.user_setup(self, w_subtype)
         else:
@@ -672,7 +669,6 @@
         return self.int_w(l_w[0]), self.int_w(l_w[1]), self.int_w(l_w[2])
 
     def is_(self, w_one, w_two):
-        # XXX a bit of hacking to gain more speed 
         if w_one is w_two:
             return self.w_True
         return self.w_False
@@ -712,7 +708,7 @@
         e = None
         if w_descr is not None:
             if not self.is_data_descr(w_descr):
-                w_value = w_obj.getdictvalue_attr_is_in_class(self, w_name)
+                w_value = w_obj.getdictvalue_attr_is_in_class(self, name)
                 if w_value is not None:
                     return w_value
             try:
@@ -721,7 +717,7 @@
                 if not e.match(self, self.w_AttributeError):
                     raise
         else:
-            w_value = w_obj.getdictvalue(self, w_name)
+            w_value = w_obj.getdictvalue(self, name)
             if w_value is not None:
                 return w_value
 
@@ -733,18 +729,27 @@
         else:
             raiseattrerror(self, w_obj, name)
 
+    def finditem_str(self, w_obj, key):
+        # performance shortcut to avoid creating the OperationError(KeyError)
+        if (isinstance(w_obj, self.DictObjectCls) and
+                not w_obj.user_overridden_class):
+            return w_obj.getitem_str(key)
+        return ObjSpace.finditem_str(self, w_obj, key)
+
     def finditem(self, w_obj, w_key):
         # performance shortcut to avoid creating the OperationError(KeyError)
-        if type(w_obj) is self.DictObjectCls:
-            return w_obj.get(w_key, None)
+        if (isinstance(w_obj, self.DictObjectCls) and
+                not w_obj.user_overridden_class):
+            return w_obj.getitem(w_key)
         return ObjSpace.finditem(self, w_obj, w_key)
 
-    def set_str_keyed_item(self, w_obj, w_key, w_value, shadows_type=True):
+    def set_str_keyed_item(self, w_obj, key, w_value, shadows_type=True):
         # performance shortcut to avoid creating the OperationError(KeyError)
-        if type(w_obj) is self.DictObjectCls:
-            w_obj.set_str_keyed_item(w_key, w_value, shadows_type)
+        if (isinstance(w_obj, self.DictObjectCls) and
+                not w_obj.user_overridden_class):
+            w_obj.set_str_keyed_item(key, w_value, shadows_type)
         else:
-            self.setitem(w_obj, w_key, w_value)
+            self.setitem(w_obj, self.wrap(key), w_value)
 
     def getindex_w(self, w_obj, w_exception, objdescr=None):
         # Performance shortcut for the common case of w_obj being an int.

Modified: pypy/trunk/pypy/objspace/std/proxyobject.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/proxyobject.py	(original)
+++ pypy/trunk/pypy/objspace/std/proxyobject.py	Tue Nov  3 11:42:42 2009
@@ -34,19 +34,19 @@
             raise OperationError(space.w_TypeError,
                                  space.wrap("You cannot override __class__ for transparent proxies"))
         
-        def getdictvalue(self, space, w_attr):
+        def getdictvalue(self, space, attr):
             try:
                 return space.call_function(self.w_controller, space.wrap('__getattribute__'),
-                   w_attr)
+                   space.wrap(attr))
             except OperationError, e:
                 if not e.match(space, space.w_AttributeError):
                     raise
                 return None
         
-        def setdictvalue(self, space, w_attr, w_value, shadows_type=True):
+        def setdictvalue(self, space, attr, w_value, shadows_type=True):
             try:
                 space.call_function(self.w_controller, space.wrap('__setattr__'),
-                   w_attr, w_value)
+                   space.wrap(attr), w_value)
                 return True
             except OperationError, e:
                 if not e.match(space, space.w_AttributeError):
@@ -64,19 +64,12 @@
                 return False
         
         def getdict(self):
-            return self.getdictvalue(self.space, self.space.wrap('__dict__'))
+            return self.getdictvalue(self.space, '__dict__')
         
         def setdict(self, space, w_dict):
-            if not self.setdictvalue(space, space.wrap('__dict__'), w_dict):
+            if not self.setdictvalue(space, '__dict__', w_dict):
                 baseobjspace.W_Root.setdict(self, space, w_dict)
         
-##        def __getattr__(self, attr):
-##            # NOT_RPYTHON
-##            try:
-##                return self.getdictvalue(self.space, self.space.wrap(attr))
-##            except OperationError, e:
-##                raise AttributeError(attr)
-        
     W_Transparent.__name__ = name
     return W_Transparent
 

Modified: pypy/trunk/pypy/objspace/std/sharingdict.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/sharingdict.py	(original)
+++ pypy/trunk/pypy/objspace/std/sharingdict.py	Tue Nov  3 11:42:42 2009
@@ -1,4 +1,3 @@
-from pypy.objspace.std.dictmultiobject import DictImplementation, StrDictImplementation
 from pypy.objspace.std.dictmultiobject import IteratorImplementation
 from pypy.objspace.std.dictmultiobject import W_DictMultiObject, _is_sane_hash
 from pypy.rlib.jit import purefunction, hint, we_are_jitted, unroll_safe
@@ -75,41 +74,42 @@
         self.emptylist = []
 
 
-class SharedDictImplementation(DictImplementation):
+class SharedDictImplementation(W_DictMultiObject):
 
     def __init__(self, space):
         self.space = space
         self.structure = space.fromcache(State).empty_structure
         self.entries = space.fromcache(State).emptylist
 
-    def get(self, w_lookup):
+    def impl_getitem(self, w_lookup):
         space = self.space
         w_lookup_type = space.type(w_lookup)
         if space.is_w(w_lookup_type, space.w_str):
-            lookup = space.str_w(w_lookup)
-            i = self.structure.lookup_position(lookup)
-            if i == -1:
-                return None
-            return self.entries[i]
+            return self.impl_getitem_str(space.str_w(w_lookup))
         elif _is_sane_hash(space, w_lookup_type):
             return None
         else:
-            return self._as_rdict().get(w_lookup)
+            return self._as_rdict().getitem(w_lookup)
 
-    def setitem(self, w_key, w_value):
+    def impl_getitem_str(self, lookup):
+        i = self.structure.lookup_position(lookup)
+        if i == -1:
+            return None
+        return self.entries[i]
+
+    def impl_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)
+            self.impl_setitem_str(self.space.str_w(w_key), w_value)
         else:
-            return self._as_rdict().setitem(w_key, w_value)
+            self._as_rdict().setitem(w_key, w_value)
 
     @unroll_safe
-    def setitem_str(self, w_key, w_value, shadows_type=True):
-        key = self.space.str_w(w_key)
+    def impl_setitem_str(self, key, w_value, shadows_type=True):
         i = self.structure.lookup_position(key)
         if i != -1:
             self.entries[i] = w_value
-            return self
+            return
         new_structure = self.structure.get_next_structure(key)
         if new_structure.length > len(self.entries):
             new_entries = [None] * new_structure.size_estimate()
@@ -120,9 +120,8 @@
         self.entries[new_structure.length - 1] = w_value
         assert self.structure.length + 1 == new_structure.length
         self.structure = new_structure
-        return self
             
-    def delitem(self, w_key):
+    def impl_delitem(self, w_key):
         space = self.space
         w_key_type = space.type(w_key)
         if space.is_w(w_key_type, space.w_str):
@@ -131,64 +130,47 @@
                 key == self.structure.last_key):
                 self.entries[self.structure.length - 1] = None
                 self.structure = self.structure.back_struct
-                return self
-            return self._as_rdict().delitem(w_key)
+                return
+            self._as_rdict().delitem(w_key)
         elif _is_sane_hash(space, w_key_type):
             raise KeyError
         else:
-            return self._as_rdict().delitem(w_key)
+            self._as_rdict().delitem(w_key)
         
-    def length(self):
+    def impl_length(self):
         return self.structure.length
 
-    def iteritems(self):
-        return SharedItemIteratorImplementation(self.space, self)
-
-    def iterkeys(self):
-        return SharedKeyIteratorImplementation(self.space, self)
+    def impl_iter(self):
+        return SharedIteratorImplementation(self.space, self)
 
-    def itervalues(self):
-        return SharedValueIteratorImplementation(self.space, self)
-
-    def keys(self):
+    def impl_keys(self):
         space = self.space
         return [space.wrap(key)
-                    for (key, item) in self.structure.keys.iteritems()
-                        if item >= 0]
+                    for (key, item) in self.structure.keys.iteritems()]
 
-    def values(self):
+    def impl_values(self):
         return self.entries[:self.structure.length]
 
-    def items(self):
+    def impl_items(self):
         space = self.space
         return [space.newtuple([space.wrap(key), self.entries[item]])
-                    for (key, item) in self.structure.keys.iteritems()
-                        if item >= 0]
-
-    def _as_rdict(self, as_strdict=False):
-        if as_strdict:
-            newimpl = StrDictImplementation(self.space)
-        else:
-            newimpl = self.space.DefaultDictImpl(self.space)
+                    for (key, item) in self.structure.keys.iteritems()]
+    def impl_clear(self):
+        space = self.space
+        self.structure = space.fromcache(State).empty_structure
+        self.entries = space.fromcache(State).emptylist
+    def _as_rdict(self):
+        r_dict_content = self.initialize_as_rdict()
         for k, i in self.structure.keys.items():
-            if i >= 0:
-                newimpl.setitem_str(self.space.wrap(k), self.entries[i])
-        return newimpl
+            r_dict_content[self.space.wrap(k)] = self.entries[i]
+        self._clear_fields()
+        return self
 
+    def _clear_fields(self):
+        self.structure = None
+        self.entries = None
 
-class SharedValueIteratorImplementation(IteratorImplementation):
-    def __init__(self, space, dictimplementation):
-        IteratorImplementation.__init__(self, space, dictimplementation)
-        self.values = dictimplementation.entries
-
-    def next(self):
-        if self.pos < self.len:
-            return self.values[self.pos]
-        else:
-            self.values = None
-            return None
-
-class SharedItemIteratorImplementation(IteratorImplementation):
+class SharedIteratorImplementation(IteratorImplementation):
     def __init__(self, space, dictimplementation):
         IteratorImplementation.__init__(self, space, dictimplementation)
         self.iterator = dictimplementation.structure.keys.iteritems()
@@ -198,19 +180,6 @@
         assert isinstance(implementation, SharedDictImplementation)
         for key, index in self.iterator:
             w_value = implementation.entries[index]
-            return self.space.newtuple([self.space.wrap(key), w_value])
-        else:
-            return None
-
-class SharedKeyIteratorImplementation(IteratorImplementation):
-    def __init__(self, space, dictimplementation):
-        IteratorImplementation.__init__(self, space, dictimplementation)
-        self.iterator = dictimplementation.structure.keys.iteritems()
-
-    def next_entry(self):
-        implementation = self.dictimplementation
-        assert isinstance(implementation, SharedDictImplementation)
-        for key, index in self.iterator:
-            return self.space.wrap(key)
+            return self.space.wrap(key), w_value
         else:
-            return None
+            return None, None

Modified: pypy/trunk/pypy/objspace/std/test/test_celldict.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/test/test_celldict.py	(original)
+++ pypy/trunk/pypy/objspace/std/test/test_celldict.py	Tue Nov  3 11:42:42 2009
@@ -26,7 +26,7 @@
         def rescue_builtins(space):
             w_dict = space.builtin.getdict()
             content = {}
-            for key, cell in w_dict.implementation.content.iteritems():
+            for key, cell in w_dict.content.iteritems():
                 newcell = ModuleCell()
                 newcell.w_value = cell.w_value
                 content[key] = newcell
@@ -35,9 +35,9 @@
         cls.w_rescue_builtins = cls.space.wrap(rescue_builtins) 
         def restore_builtins(space):
             w_dict = space.builtin.getdict()
-            if not isinstance(w_dict.implementation, ModuleDictImplementation):
-                w_dict.implementation = ModuleDictImplementation(space)
-            w_dict.implementation.content = stored_builtins.pop()
+            assert isinstance(w_dict, ModuleDictImplementation)
+            w_dict.content = stored_builtins.pop()
+            w_dict.fallback = None
         restore_builtins = gateway.interp2app(restore_builtins)
         cls.w_restore_builtins = cls.space.wrap(restore_builtins) 
 

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	Tue Nov  3 11:42:42 2009
@@ -1,10 +1,10 @@
 from pypy.interpreter.error import OperationError
 from pypy.objspace.std.dictmultiobject import \
      W_DictMultiObject, setitem__DictMulti_ANY_ANY, getitem__DictMulti_ANY, \
-     EmptyDictImplementation, RDictImplementation, StrDictImplementation, \
-     MeasuringDictImplementation
+     StrDictImplementation
 
 from pypy.objspace.std.celldict import ModuleDictImplementation
+from pypy.objspace.std.sharingdict import SharedDictImplementation
 from pypy.conftest import gettestobjspace
 
 
@@ -15,13 +15,13 @@
 
     def test_empty(self):
         space = self.space
-        d = self.space.DictObjectCls(space)
+        d = self.space.newdict()
         assert not self.space.is_true(d)
 
     def test_nonempty(self):
         space = self.space
         wNone = space.w_None
-        d = self.space.DictObjectCls(space)
+        d = self.space.newdict()
         d.initialize_content([(wNone, wNone)])
         assert space.is_true(d)
         i = space.getitem(d, wNone)
@@ -32,7 +32,7 @@
         space = self.space
         wk1 = space.wrap('key')
         wone = space.wrap(1)
-        d = self.space.DictObjectCls(space)
+        d = self.space.newdict()
         d.initialize_content([(space.wrap('zero'),space.wrap(0))])
         space.setitem(d,wk1,wone)
         wback = space.getitem(d,wk1)
@@ -41,7 +41,7 @@
     def test_delitem(self):
         space = self.space
         wk1 = space.wrap('key')
-        d = self.space.DictObjectCls(space)
+        d = self.space.newdict()
         d.initialize_content( [(space.wrap('zero'),space.wrap(0)),
                                (space.wrap('one'),space.wrap(1)),
                                (space.wrap('two'),space.wrap(2))])
@@ -52,7 +52,7 @@
                             space.getitem,d,space.wrap('one'))
 
     def test_wrap_dict(self):
-        assert isinstance(self.space.wrap({}), self.space.DictObjectCls)
+        assert isinstance(self.space.wrap({}), W_DictMultiObject)
 
 
     def test_dict_compare(self):
@@ -134,8 +134,7 @@
         space = self.space
         w = space.wrap
         d = {"a": w(1), "b": w(2)}
-        w_d = space.DictObjectCls(space)
-        w_d.initialize_from_strdict_shared(d)
+        w_d = space.newdict(from_strdict_shared=d)
         assert self.space.eq_w(space.getitem(w_d, w("a")), w(1))
         assert self.space.eq_w(space.getitem(w_d, w("b")), w(2))
         
@@ -143,8 +142,7 @@
         space = self.space
         w = space.wrap
         d = {"a": w(1), "b": w(2)}
-        w_d = space.DictObjectCls(space)
-        w_d.initialize_from_strdict_shared(d)
+        w_d = space.newdict(from_strdict_shared=d)
         assert self.space.eq_w(space.getitem(w_d, w("a")), w(1))
         assert self.space.eq_w(space.getitem(w_d, w("b")), w(2))
         d["c"] = w(41)
@@ -552,7 +550,11 @@
         raises(KeyError, "d['def']")
 
 
-class C: pass
+
+class FakeString(str):
+    def unwrap(self, space):
+        self.unwrapped = True
+        return str(self)
 
 # the minimal 'space' needed to use a W_DictMultiObject
 class FakeSpace:
@@ -587,9 +589,25 @@
     def newtuple(self, l):
         return tuple(l)
 
+    def newdict(self, module=False, instance=False, classofinstance=None,
+                from_strdict_shared=None):
+        return W_DictMultiObject.allocate_and_init_instance(
+                self, module=module, instance=instance,
+                classofinstance=classofinstance,
+                from_strdict_shared=from_strdict_shared)
+
+    def allocate_instance(self, cls, type):
+        return object.__new__(cls)
+
+    def fromcache(self, cls):
+        return cls(self)
+
     w_StopIteration = StopIteration
     w_None = None
-    StringObjectCls = None  # xxx untested: shortcut in StrDictImpl.getitem
+    StringObjectCls = FakeString
+    w_dict = None
+    iter = iter
+    viewiterable = list
 
 
 class Config:
@@ -599,6 +617,7 @@
             withsharingdict = False
             withsmalldicts = False
             withcelldict = False
+            withshadowtracking = False
         class opcodes:
             CALL_LIKELY_BUILTIN = False
 
@@ -608,143 +627,147 @@
 class TestDictImplementation:
     def setup_method(self,method):
         self.space = FakeSpace()
-        self.space.emptydictimpl = EmptyDictImplementation(self.space)
-        self.space.DefaultDictImpl = RDictImplementation
 
     def test_stressdict(self):
         from random import randint
-        d = self.space.DictObjectCls(self.space)
+        d = self.space.newdict()
         N = 10000
         pydict = {}
         for i in range(N):
             x = randint(-N, N)
             setitem__DictMulti_ANY_ANY(self.space, d, x, i)
             pydict[x] = i
-        for x in pydict:
-            assert pydict[x] == getitem__DictMulti_ANY(self.space, d, x)
+        for key, value in pydict.iteritems():
+            assert value == getitem__DictMulti_ANY(self.space, d, key)
 
-class TestRDictImplementation:
-    ImplementionClass = RDictImplementation
-    DevolvedClass = RDictImplementation
-    EmptyClass = EmptyDictImplementation
-    DefaultDictImpl = RDictImplementation
+class BaseTestRDictImplementation:
 
     def setup_method(self,method):
-        self.space = FakeSpace()
-        self.space.emptydictimpl = EmptyDictImplementation(self.space)
-        self.space.DefaultDictImpl = self.DefaultDictImpl
-        self.string = self.space.wrap("fish")
-        self.string2 = self.space.wrap("fish2")
+        self.fakespace = FakeSpace()
+        self.string = self.fakespace.wrap("fish")
+        self.string2 = self.fakespace.wrap("fish2")
         self.impl = self.get_impl()
 
     def get_impl(self):
-        "Needs to be empty, or one entry with key self.string"
-        return self.ImplementionClass(self.space)
+        return self.ImplementionClass(self.fakespace)
+
+    def fill_impl(self):
+        self.impl.setitem(self.string, 1000)
+        self.impl.setitem(self.string2, 2000)
+
+    def check_not_devolved(self):
+        assert self.impl.r_dict_content is None
 
     def test_setitem(self):
-        assert self.impl.setitem(self.string, 1000) is self.impl
+        self.impl.setitem(self.string, 1000)
         assert self.impl.length() == 1
-        assert self.impl.get(self.string) == 1000
+        assert self.impl.getitem(self.string) == 1000
+        assert self.impl.getitem_str(self.string) == 1000
+        self.check_not_devolved()
 
     def test_setitem_str(self):
-        assert self.impl.setitem_str(self.space.str_w(self.string), 1000) is self.impl
+        self.impl.setitem_str(self.fakespace.str_w(self.string), 1000)
         assert self.impl.length() == 1
-        assert self.impl.get(self.string) == 1000
+        assert self.impl.getitem(self.string) == 1000
+        assert self.impl.getitem_str(self.string) == 1000
+        self.check_not_devolved()
 
     def test_delitem(self):
-        self.impl.setitem(self.string, 1000)
-        self.impl.setitem(self.string2, 2000)
+        self.fill_impl()
         assert self.impl.length() == 2
-        newimpl =  self.impl.delitem(self.string)
+        self.impl.delitem(self.string2)
         assert self.impl.length() == 1
-        assert newimpl is self.impl
-        newimpl = self.impl.delitem(self.string2)
+        self.impl.delitem(self.string)
         assert self.impl.length() == 0
-        assert isinstance(newimpl, self.EmptyClass)
+        self.check_not_devolved()
 
     def test_keys(self):
-        self.impl.setitem(self.string, 1000)
-        self.impl.setitem(self.string2, 2000)
+        self.fill_impl()
         keys = self.impl.keys()
         keys.sort()
         assert keys == [self.string, self.string2]
+        self.check_not_devolved()
 
     def test_values(self):
-        self.impl.setitem(self.string, 1000)
-        self.impl.setitem(self.string2, 2000)
+        self.fill_impl()
         values = self.impl.values()
         values.sort()
         assert values == [1000, 2000]
+        self.check_not_devolved()
 
     def test_items(self):
-        self.impl.setitem(self.string, 1000)
-        self.impl.setitem(self.string2, 2000)
+        self.fill_impl()
         items = self.impl.items()
         items.sort()
         assert items == zip([self.string, self.string2], [1000, 2000])
+        self.check_not_devolved()
 
-    def test_iterkeys(self):
-        self.impl.setitem(self.string, 1000)
-        self.impl.setitem(self.string2, 2000)
-        iteratorimplementation = self.impl.iterkeys()
-        keys = []
-        while 1:
-            key = iteratorimplementation.next()
-            if key is None:
-                break
-            keys.append(key)
-        keys.sort()
-        assert keys == [self.string, self.string2]
-
-    def test_itervalues(self):
-        self.impl.setitem(self.string, 1000)
-        self.impl.setitem(self.string2, 2000)
-        iteratorimplementation = self.impl.itervalues()
-        values = []
-        while 1:
-            value = iteratorimplementation.next()
-            if value is None:
-                break
-            values.append(value)
-        values.sort()
-        assert values == [1000, 2000]
-
-    def test_iteritems(self):
-        self.impl.setitem(self.string, 1000)
-        self.impl.setitem(self.string2, 2000)
-        iteratorimplementation = self.impl.iteritems()
+    def test_iter(self):
+        self.fill_impl()
+        iteratorimplementation = self.impl.iter()
         items = []
         while 1:
             item = iteratorimplementation.next()
-            if item is None:
+            if item == (None, None):
                 break
             items.append(item)
         items.sort()
         assert items == zip([self.string, self.string2], [1000, 2000])
+        self.check_not_devolved()
 
     def test_devolve(self):
         impl = self.impl
         for x in xrange(100):
-            impl = impl.setitem(self.space.str_w(str(x)), x)
-            impl = impl.setitem(x, x)
-        assert isinstance(impl, self.DevolvedClass)
+            impl.setitem(self.fakespace.str_w(str(x)), x)
+            impl.setitem(x, x)
+        assert impl.r_dict_content is not None
 
-class TestStrDictImplementation(TestRDictImplementation):
+class TestStrDictImplementation(BaseTestRDictImplementation):
     ImplementionClass = StrDictImplementation
 
-class TestMeasuringDictImplementation(TestRDictImplementation):
-    ImplementionClass = MeasuringDictImplementation
-    DevolvedClass = MeasuringDictImplementation
-    EmptyClass = MeasuringDictImplementation
+    def test_str_shortcut(self):
+        self.fill_impl()
+        s = FakeString(self.string)
+        assert self.impl.getitem(s) == 1000
+        assert s.unwrapped
+
+## class TestMeasuringDictImplementation(BaseTestRDictImplementation):
+##     ImplementionClass = MeasuringDictImplementation
+##     DevolvedClass = MeasuringDictImplementation
+
+class TestModuleDictImplementation(BaseTestRDictImplementation):
+    ImplementionClass = ModuleDictImplementation
 
-class TestModuleDictImplementation(TestRDictImplementation):
+class TestModuleDictImplementationWithBuiltinNames(BaseTestRDictImplementation):
     ImplementionClass = ModuleDictImplementation
-    EmptyClass = ModuleDictImplementation
 
-class TestModuleDictImplementationWithBuiltinNames(TestRDictImplementation):
+    string = "int"
+    string2 = "isinstance"
+
+class TestSharedDictImplementation(BaseTestRDictImplementation):
+    ImplementionClass = SharedDictImplementation
+
+
+class BaseTestDevolvedDictImplementation(BaseTestRDictImplementation):
+    def fill_impl(self):
+        BaseTestRDictImplementation.fill_impl(self)
+        self.impl._as_rdict()
+
+    def check_not_devolved(self):
+        pass
+
+class TestDevolvedStrDictImplementation(BaseTestDevolvedDictImplementation):
+    ImplementionClass = StrDictImplementation
+
+class TestDevolvedModuleDictImplementation(BaseTestDevolvedDictImplementation):
+    ImplementionClass = ModuleDictImplementation
+
+class TestDevolvedModuleDictImplementationWithBuiltinNames(BaseTestDevolvedDictImplementation):
     ImplementionClass = ModuleDictImplementation
-    EmptyClass = ModuleDictImplementation
 
     string = "int"
     string2 = "isinstance"
 
+class TestDevolvedSharedDictImplementation(BaseTestDevolvedDictImplementation):
+    ImplementionClass = SharedDictImplementation
+

Added: pypy/trunk/pypy/objspace/std/test/test_inlinedict.py
==============================================================================
--- (empty file)
+++ pypy/trunk/pypy/objspace/std/test/test_inlinedict.py	Tue Nov  3 11:42:42 2009
@@ -0,0 +1,127 @@
+from pypy.conftest import gettestobjspace
+from pypy.objspace.std.inlinedict import make_inlinedict_mixin
+from pypy.objspace.std.dictmultiobject import StrDictImplementation
+from pypy.objspace.std.test.test_dictmultiobject import FakeSpace
+from pypy.objspace.std.test.test_dictmultiobject import BaseTestRDictImplementation
+from pypy.objspace.std.sharingdict import SharedDictImplementation
+
+class FakeSubtype:
+    nslots = 0
+
+class TestMixin(object):
+    Mixin = make_inlinedict_mixin(StrDictImplementation, "content")
+    class FakeObject(Mixin):
+        def user_setup_slots(self, nslots):
+            pass
+
+    fakespace = FakeSpace()
+
+    def make_obj(self):
+        obj = self.FakeObject()
+        obj.user_setup(self.fakespace, FakeSubtype)
+        obj.setdictvalue(self.fakespace, "hello", 1)
+        obj.setdictvalue(self.fakespace, "world", 2)
+        assert obj._inlined_dict_valid()
+        assert obj.w__dict__ is None
+        return obj
+
+    def test_setgetdel_dictvalue(self):
+        obj = self.make_obj()
+        assert obj.getdictvalue(self.fakespace, "hello") == 1
+        assert obj.getdictvalue(self.fakespace, "world") == 2
+        assert obj.getdictvalue(self.fakespace, "bla") is None
+        assert not obj.deldictvalue(self.fakespace, "bla")
+        obj.deldictvalue(self.fakespace, "world")
+        assert obj.getdictvalue(self.fakespace, "world") is None
+        obj.deldictvalue(self.fakespace, "hello")
+        assert obj.getdictvalue(self.fakespace, "hello") is None
+
+
+    def test_getdict(self):
+        obj = self.make_obj()
+        w_dict = obj.getdict()
+        assert obj.getdict() is w_dict # always get the same dict
+        assert obj.w__dict__ is w_dict
+
+        assert w_dict.getitem("hello") == 1
+        assert w_dict.getitem("world") == 2
+        w_dict.setitem("hello", 4)
+        w_dict.setitem("world", 5)
+        assert obj.getdictvalue(self.fakespace, "hello") == 4
+        assert obj.getdictvalue(self.fakespace, "world") == 5
+
+    def test_setdict(self):
+        obj1 = self.make_obj()
+        w_dict1 = obj1.getdict()
+        obj2 = self.make_obj()
+        w_dict2 = obj2.getdict()
+        w_dict2.setitem(4, 1) # devolve dict
+        w_dict2.setitem(5, 2)
+        obj2.setdict(self.space, w_dict1)
+        assert obj2.getdictvalue(self.fakespace, "hello") == 1
+        assert obj2.getdictvalue(self.fakespace, "world") == 2
+        obj1.setdictvalue(self.fakespace, "hello", 4)
+        obj1.setdictvalue(self.fakespace, "world", 5)
+        assert obj2.getdictvalue(self.fakespace, "hello") == 4
+        assert obj2.getdictvalue(self.fakespace, "world") == 5
+
+
+    def test_dict_devolves_via_dict(self):
+        obj = self.make_obj()
+        w_dict = obj.getdict()
+        w_dict.setitem(4, 1)
+        w_dict.setitem(5, 2)
+        assert dict(w_dict.r_dict_content) == {4: 1, 5: 2, "hello": 1, "world": 2}
+        assert obj.getdictvalue(self.fakespace, "hello") == 1
+        assert obj.getdictvalue(self.fakespace, "world") == 2
+        assert obj.getdictvalue(self.fakespace, 4) == 1
+        assert obj.getdictvalue(self.fakespace, 5) == 2
+        obj.deldictvalue(self.fakespace, "world")
+        assert obj.getdictvalue(self.fakespace, "world") is None
+        obj.deldictvalue(self.fakespace, "hello")
+        assert obj.getdictvalue(self.fakespace, "hello") is None
+
+class TestMixinShared(TestMixin):
+    Mixin = make_inlinedict_mixin(SharedDictImplementation, "structure")
+    class FakeObject(Mixin):
+        def user_setup_slots(self, nslots):
+            pass
+
+class TestIndirectDict(BaseTestRDictImplementation):
+    Mixin = make_inlinedict_mixin(StrDictImplementation, "content")
+    class FakeObject(Mixin):
+        def user_setup_slots(self, nslots):
+            pass
+
+    def get_impl(self):
+        obj = self.FakeObject()
+        obj.user_setup(self.fakespace, FakeSubtype)
+        return obj.getdict()
+
+
+class TestIndirectDictShared(TestIndirectDict):
+    Mixin = make_inlinedict_mixin(SharedDictImplementation, "structure")
+    class FakeObject(Mixin):
+        def user_setup_slots(self, nslots):
+            pass
+
+
+
+
+class TestInlineDict(object):
+    def setup_class(cls):
+        cls.space = gettestobjspace(**{"objspace.std.withinlineddict": True})
+
+    def test_simple(self):
+        w_a = self.space.appexec([], """():
+            class A(object):
+                pass
+            a = A()
+            a.x = 12
+            a.y = 13
+            return a
+        """)
+        assert w_a.w__dict__ is None
+        assert self.space.int_w(w_a.content['x']) == 12
+        assert self.space.int_w(w_a.content['y']) == 13
+

Modified: pypy/trunk/pypy/objspace/std/test/test_obj.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/test/test_obj.py	(original)
+++ pypy/trunk/pypy/objspace/std/test/test_obj.py	Tue Nov  3 11:42:42 2009
@@ -1,4 +1,3 @@
-# -*- coding: iso-8859-1 -*-
 from pypy.conftest import option
 
 class AppTestObject:

Modified: pypy/trunk/pypy/objspace/std/test/test_shadowtracking.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/test/test_shadowtracking.py	(original)
+++ pypy/trunk/pypy/objspace/std/test/test_shadowtracking.py	Tue Nov  3 11:42:42 2009
@@ -13,15 +13,15 @@
             a = A()
             return a
         """)
-        assert not w_inst.w__dict__.implementation.shadows_anything()
+        assert not w_inst.getdict().shadows_anything()
         space.appexec([w_inst], """(a):
             a.g = "foo"
         """)
-        assert not w_inst.w__dict__.implementation.shadows_anything()
+        assert not w_inst.getdict().shadows_anything()
         space.appexec([w_inst], """(a):
             a.f = "foo"
         """)
-        assert w_inst.w__dict__.implementation.shadows_anything()
+        assert w_inst.getdict().shadows_anything()
 
     def test_shadowing_via__dict__(self):
         space = self.space
@@ -32,15 +32,15 @@
             a = A()
             return a
         """)
-        assert not w_inst.w__dict__.implementation.shadows_anything()
+        assert not w_inst.getdict().shadows_anything()
         space.appexec([w_inst], """(a):
             a.__dict__["g"] = "foo"
         """)
-        assert not w_inst.w__dict__.implementation.shadows_anything()
+        assert not w_inst.getdict().shadows_anything()
         space.appexec([w_inst], """(a):
             a.__dict__["f"] = "foo"
         """)
-        assert w_inst.w__dict__.implementation.shadows_anything()
+        assert w_inst.getdict().shadows_anything()
 
     def test_changing__dict__(self):
         space = self.space
@@ -51,11 +51,11 @@
             a = A()
             return a
         """)
-        assert not w_inst.w__dict__.implementation.shadows_anything()
+        assert not w_inst.getdict().shadows_anything()
         space.appexec([w_inst], """(a):
             a.__dict__ = {}
         """)
-        assert w_inst.w__dict__.implementation.shadows_anything()
+        assert w_inst.getdict().shadows_anything()
 
     def test_changing__class__(self):
         space = self.space
@@ -66,14 +66,14 @@
             a = A()
             return a
         """)
-        assert not w_inst.w__dict__.implementation.shadows_anything()
+        assert not w_inst.getdict().shadows_anything()
         space.appexec([w_inst], """(a):
             class B(object):
                 def g(self):
                     return 42
             a.__class__ = B
         """)
-        assert w_inst.w__dict__.implementation.shadows_anything()
+        assert w_inst.getdict().shadows_anything()
 
     def test_changing_the_type(self):
         space = self.space
@@ -84,13 +84,13 @@
             a.x = 72
             return a
         """)
-        assert not w_inst.w__dict__.implementation.shadows_anything()
+        assert not w_inst.getdict().shadows_anything()
         w_x = space.appexec([w_inst], """(a):
             a.__class__.x = 42
             return a.x
         """)
         assert space.unwrap(w_x) == 72
-        assert w_inst.w__dict__.implementation.shadows_anything()
+        assert w_inst.getdict().shadows_anything()
 
 class AppTestShadowTracking(object):
     def setup_class(cls):

Modified: pypy/trunk/pypy/objspace/std/typeobject.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/typeobject.py	(original)
+++ pypy/trunk/pypy/objspace/std/typeobject.py	Tue Nov  3 11:42:42 2009
@@ -131,10 +131,7 @@
     def compute_default_mro(w_self):
         return compute_C3_mro(w_self.space, w_self)
 
-    def getdictvalue(w_self, space, w_attr):
-        return w_self.getdictvalue_w(space, space.str_w(w_attr))
-    
-    def getdictvalue_w(w_self, space, attr):
+    def getdictvalue(w_self, space, attr):
         w_value = w_self.dict_w.get(attr, None)
         if w_self.lazyloaders and w_value is None:
             if attr in w_self.lazyloaders:
@@ -172,7 +169,7 @@
             if w_class is w_starttype:
                 look = True
             elif look:
-                w_value = w_class.getdictvalue_w(space, name)
+                w_value = w_class.getdictvalue(space, name)
                 if w_value is not None:
                     return w_value
         return None
@@ -182,7 +179,7 @@
     def _lookup(w_self, key):
         space = w_self.space
         for w_class in w_self.mro_w:
-            w_value = w_class.getdictvalue_w(space, key)
+            w_value = w_class.getdictvalue(space, key)
             if w_value is not None:
                 return w_value
         return None
@@ -193,7 +190,7 @@
         # attribute was found
         space = w_self.space
         for w_class in w_self.mro_w:
-            w_value = w_class.getdictvalue_w(space, key)
+            w_value = w_class.getdictvalue(space, key)
             if w_value is not None:
                 return w_class, w_value
         return None, None
@@ -273,7 +270,7 @@
         "NOT_RPYTHON.  Forces the lazy attributes to be computed."
         if 'lazyloaders' in w_self.__dict__:
             for attr in w_self.lazyloaders.keys():
-                w_self.getdictvalue_w(w_self.space, attr)
+                w_self.getdictvalue(w_self.space, attr)
             del w_self.lazyloaders
         return False
 
@@ -281,8 +278,7 @@
         if w_self.lazyloaders:
             w_self._freeze_()    # force un-lazification
         space = w_self.space
-        newdic = space.DictObjectCls(space)
-        newdic.initialize_from_strdict_shared(w_self.dict_w)
+        newdic = space.newdict(from_strdict_shared=w_self.dict_w)
         return W_DictProxyObject(newdic)
 
     def unwrap(w_self, space):

Modified: pypy/trunk/pypy/objspace/std/typetype.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/typetype.py	(original)
+++ pypy/trunk/pypy/objspace/std/typetype.py	Tue Nov  3 11:42:42 2009
@@ -174,7 +174,7 @@
         return space.wrap("""type(object) -> the object's type
 type(name, bases, dict) -> a new type""")
     w_type = _check(space, w_type)
-    w_result = w_type.getdictvalue_w(space, '__doc__')
+    w_result = w_type.getdictvalue(space, '__doc__')
     if w_result is None:
         return space.w_None
     else:

Modified: pypy/trunk/pypy/objspace/taint.py
==============================================================================
--- pypy/trunk/pypy/objspace/taint.py	(original)
+++ pypy/trunk/pypy/objspace/taint.py	Tue Nov  3 11:42:42 2009
@@ -20,14 +20,11 @@
 ##    def getdict(self):
 ##        return taint(self.w_obj.getdict())
 
-##    def getdictvalue_w(self, space, attr):
-##        return taint(self.w_obj.getdictvalue_w(space, attr))
+##    def getdictvalue(self, space, attr):
+##        return taint(self.w_obj.getdictvalue(space, attr))
 
-##    def getdictvalue(self, space, w_attr):
-##        return taint(self.w_obj.getdictvalue(space, w_attr))
-
-##    def setdictvalue(self, space, w_attr, w_value):
-##        return self.w_obj.setdictvalue(space, w_attr, w_value)
+##    def setdictvalue(self, space, attr, w_value):
+##        return self.w_obj.setdictvalue(space, attr, w_value)
 
 ##    ...
 



More information about the Pypy-commit mailing list