[pypy-commit] pypy share-mapdict-methods: - try to reduce duplication of methods by putting a lot of the methods that

cfbolz pypy.commits at gmail.com
Wed Apr 27 11:22:10 EDT 2016


Author: Carl Friedrich Bolz <cfbolz at gmx.de>
Branch: share-mapdict-methods
Changeset: r83990:a1a3b6a39592
Date: 2016-04-27 18:13 +0300
http://bitbucket.org/pypy/pypy/changeset/a1a3b6a39592/

Log:	- try to reduce duplication of methods by putting a lot of the
	methods that mapdicts defines into W_Root. That way, the methods
	aren't duplicated into every user-defined subclass.

	- only inline five fields into the user-defined subclasses of
	object, and all new-style classes

diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -5,7 +5,7 @@
 from rpython.rlib import jit, types
 from rpython.rlib.debug import make_sure_not_resized
 from rpython.rlib.objectmodel import (we_are_translated, newlist_hint,
-     compute_unique_id, specialize)
+     compute_unique_id, specialize, import_from_mixin)
 from rpython.rlib.signature import signature
 from rpython.rlib.rarithmetic import r_uint, SHRT_MIN, SHRT_MAX, \
     INT_MIN, INT_MAX, UINT_MAX, USHRT_MAX
@@ -16,6 +16,8 @@
 from pypy.interpreter.argument import Arguments
 from pypy.interpreter.miscutils import ThreadLocals, make_weak_value_dictionary
 
+from pypy.objspace.std.basemapdictobject import RootObjectMapdictMixin
+
 
 __all__ = ['ObjSpace', 'OperationError', 'W_Root']
 
@@ -30,8 +32,9 @@
     __slots__ = ('__weakref__',)
     user_overridden_class = False
 
-    def getdict(self, space):
-        return None
+    # a lot of the default functionality assumes mapdict now.
+    # import those methods
+    import_from_mixin(RootObjectMapdictMixin)
 
     def getdictvalue(self, space, attr):
         w_dict = self.getdict(space)
@@ -46,29 +49,18 @@
             return True
         return False
 
-    def deldictvalue(self, space, attr):
-        w_dict = self.getdict(space)
-        if w_dict is not None:
-            try:
-                space.delitem(w_dict, space.wrap(attr))
-                return True
-            except OperationError, ex:
-                if not ex.match(space, space.w_KeyError):
-                    raise
-        return False
+    # deldictvalue, getdict, setdict are mixed in from basemapdictobject
+    # def deldictvalue(self, space, attrname):
+    # def getdict(self, space):
+    # def setdict(self, space, w_dict):
 
-    def setdict(self, space, w_dict):
-        raise oefmt(space.w_TypeError,
-                     "attribute '__dict__' of %T objects is not writable",
-                     self)
 
     # to be used directly only by space.type implementations
     def getclass(self, space):
         return space.gettypeobject(self.typedef)
 
-    def setclass(self, space, w_subtype):
-        raise OperationError(space.w_TypeError,
-                             space.wrap("__class__ assignment: only for heap types"))
+    # setclass is mixed in from basemapdictobject
+    # def setclass(self, space, w_cls):
 
     def user_setup(self, space, w_subtype):
         raise NotImplementedError("only for interp-level user subclasses "
@@ -106,14 +98,10 @@
         return space.wrap("<%s at 0x%s%s>" % (info, addrstring,
                                               moreinfo))
 
-    def getslotvalue(self, index):
-        raise NotImplementedError
-
-    def setslotvalue(self, index, w_val):
-        raise NotImplementedError
-
-    def delslotvalue(self, index):
-        raise NotImplementedError
+    # mixed in from basemapdictobject are: getslotvalue, setslotvalue, delslotvalue
+    # def getslotvalue(self, index):
+    # def setslotvalue(self, index, w_val):
+    # def delslotvalue(self, slotindex):
 
     def descr_call_mismatch(self, space, opname, RequiredClass, args):
         if RequiredClass is None:
@@ -125,15 +113,10 @@
 
     # used by _weakref implemenation
 
-    def getweakref(self):
-        return None
-
-    def setweakref(self, space, weakreflifeline):
-        raise oefmt(space.w_TypeError,
-                    "cannot create weak reference to '%T' object", self)
-
-    def delweakref(self):
-        pass
+    # mixed in from basemapdictobject are: getweakref, setweakref, delweakref
+    # def getweakref(self):
+    # def setweakref(self, space, weakreflifeline):
+    # def delweakref(self):
 
     def clear_all_weakrefs(self):
         """Call this at the beginning of interp-level __del__() methods
@@ -171,19 +154,6 @@
             self.__already_enqueued_for_destruction += (callback,)
         space.user_del_action.register_callback(self, callback, descrname)
 
-    # hooks that the mapdict implementations needs:
-    def _get_mapdict_map(self):
-        return None
-    def _set_mapdict_map(self, map):
-        raise NotImplementedError
-    def _mapdict_read_storage(self, index):
-        raise NotImplementedError
-    def _mapdict_write_storage(self, index, value):
-        raise NotImplementedError
-    def _mapdict_storage_length(self):
-        raise NotImplementedError
-    def _set_mapdict_storage_and_map(self, storage, map):
-        raise NotImplementedError
 
     # -------------------------------------------------------------------
 
diff --git a/pypy/interpreter/test/test_typedef.py b/pypy/interpreter/test/test_typedef.py
--- a/pypy/interpreter/test/test_typedef.py
+++ b/pypy/interpreter/test/test_typedef.py
@@ -362,6 +362,26 @@
         """)
         assert seen == [1]
 
+    def test_mapdict_number_of_slots(self):
+        space = self.space
+        a, b, c = space.unpackiterable(space.appexec([], """():
+            class A(object):
+                pass
+            a = A()
+            a.x = 1
+            class B:
+                pass
+            b = B()
+            b.x = 1
+            class C(int):
+                pass
+            c = C(1)
+            c.x = 1
+            return a, b, c
+        """), 3)
+        assert not hasattr(a, "storage")
+        assert not hasattr(b, "storage")
+        assert hasattr(c, "storage")
 
 class AppTestTypeDef:
 
@@ -423,3 +443,4 @@
         def f():
             return x
         assert f.__closure__[0].cell_contents is x
+
diff --git a/pypy/interpreter/typedef.py b/pypy/interpreter/typedef.py
--- a/pypy/interpreter/typedef.py
+++ b/pypy/interpreter/typedef.py
@@ -124,22 +124,23 @@
 
 def _getusercls(config, cls, wants_del, reallywantdict=False):
     from rpython.rlib import objectmodel
+    from pypy.objspace.std.objectobject import W_ObjectObject
+    from pypy.module.__builtin__.interp_classobj import W_InstanceObject
     from pypy.objspace.std.mapdict import (BaseUserClassMapdict,
-            MapdictDictSupport, MapdictWeakrefSupport,
-            _make_storage_mixin_size_n)
+            MapdictDictSupport,
+            _make_storage_mixin_size_n, MapdictStorageMixin)
     typedef = cls.typedef
     name = cls.__name__ + "User"
 
-    mixins_needed = [BaseUserClassMapdict, _make_storage_mixin_size_n()]
+    mixins_needed = [BaseUserClassMapdict]
+    if cls is W_ObjectObject or cls is W_InstanceObject:
+        mixins_needed.append(_make_storage_mixin_size_n())
+    else:
+        mixins_needed.append(MapdictStorageMixin)
     if reallywantdict or not typedef.hasdict:
         # the type has no dict, mapdict to provide the dict
         mixins_needed.append(MapdictDictSupport)
         name += "Dict"
-    if not typedef.weakrefable:
-        # the type does not support weakrefs yet, mapdict to provide weakref
-        # support
-        mixins_needed.append(MapdictWeakrefSupport)
-        name += "Weakrefable"
     if wants_del:
         name += "Del"
         parent_destructor = getattr(cls, '__del__', None)
diff --git a/pypy/objspace/std/basemapdictobject.py b/pypy/objspace/std/basemapdictobject.py
new file mode 100644
--- /dev/null
+++ b/pypy/objspace/std/basemapdictobject.py
@@ -0,0 +1,192 @@
+# this file contains the shared objspace method implementation that are
+# imported into W_Root. All W_Root objects have these methods, but most of them
+# really only make sense for user-defined subclasses. It is however important
+# that they are shared by all subclasses of W_Root.
+
+
+DICT = 0
+SPECIAL = 1
+INVALID = 2
+SLOTS_STARTING_FROM = 3
+
+
+class RootObjectMapdictMixin(object):
+    # hooks that the mapdict implementations needs.
+    # these will be overridden in user-defined subclasses
+
+    def _get_mapdict_map(self):
+        # if this method returns None, there is no map, thus the class is no
+        # user-defined subclass
+        return None
+
+    def _set_mapdict_map(self, map):
+        raise NotImplementedError
+
+    def _mapdict_read_storage(self, index):
+        raise NotImplementedError
+
+    def _mapdict_write_storage(self, index, value):
+        raise NotImplementedError
+
+    def _mapdict_storage_length(self):
+        raise NotImplementedError
+
+    def _set_mapdict_storage_and_map(self, storage, map):
+        raise NotImplementedError
+
+    def _mapdict_init_empty(self, map):
+        raise NotImplementedError
+
+    # ____________________________________________________________
+    # objspace interface
+
+
+    # class handling
+
+    # getclass is not done here, it makes sense to really specialize this per class
+
+    def setclass(self, space, w_cls):
+        from pypy.interpreter.error import OperationError
+        map = self._get_mapdict_map()
+        if map is None:
+            raise OperationError(space.w_TypeError,
+                                 space.wrap("__class__ assignment: only for heap types"))
+        new_obj = map.set_terminator(self, w_cls.terminator)
+        self._set_mapdict_storage_and_map(new_obj.storage, new_obj.map)
+
+
+    # dict handling
+
+    # getdictvalue and setdictvalue are not done here, for performance reasons
+
+    def deldictvalue(self, space, attrname):
+        from pypy.interpreter.error import OperationError
+        map = self._get_mapdict_map()
+        if map is None:
+            # check whether it has a dict and use that
+            w_dict = self.getdict(space)
+            if w_dict is not None:
+                try:
+                    space.delitem(w_dict, space.wrap(attrname))
+                    return True
+                except OperationError, ex:
+                    if not ex.match(space, space.w_KeyError):
+                        raise
+            return False
+        new_obj = map.delete(self, attrname, DICT)
+        if new_obj is None:
+            return False
+        self._set_mapdict_storage_and_map(new_obj.storage, new_obj.map)
+        return True
+
+    def getdict(self, space):
+        from pypy.objspace.std.mapdict import MapDictStrategy
+        from pypy.objspace.std.dictmultiobject import  W_DictMultiObject
+        from pypy.objspace.std.dictmultiobject import  W_DictObject
+        map = self._get_mapdict_map()
+        if map is None:
+            return None
+        terminator = map.terminator
+        if not terminator.has_dict:
+            return None
+        w_dict = map.read(self, "dict", SPECIAL)
+        if w_dict is not None:
+            assert isinstance(w_dict, W_DictMultiObject)
+            return w_dict
+
+        strategy = space.fromcache(MapDictStrategy)
+        storage = strategy.erase(self)
+        w_dict = W_DictObject(space, strategy, storage)
+        flag = map.write(self, "dict", SPECIAL, w_dict)
+        assert flag
+        return w_dict
+
+    def setdict(self, space, w_dict):
+        from pypy.interpreter.error import OperationError, oefmt
+        from pypy.objspace.std.mapdict import MapDictStrategy
+        from pypy.objspace.std.dictmultiobject import  W_DictMultiObject
+        map = self._get_mapdict_map()
+        if map is None or not map.terminator.has_dict:
+            raise oefmt(space.w_TypeError,
+                         "attribute '__dict__' of %T objects is not writable",
+                         self)
+        terminator = map.terminator
+        if not space.isinstance_w(w_dict, space.w_dict):
+            raise OperationError(space.w_TypeError,
+                    space.wrap("setting dictionary to a non-dict"))
+        assert isinstance(w_dict, W_DictMultiObject)
+        w_olddict = self.getdict(space)
+        assert isinstance(w_olddict, W_DictMultiObject)
+        # The old dict has got 'self' as dstorage, but we are about to
+        # change self's ("dict", SPECIAL) attribute to point to the
+        # new dict.  If the old dict was using the MapDictStrategy, we
+        # have to force it now: otherwise it would remain an empty
+        # shell that continues to delegate to 'self'.
+        if type(w_olddict.get_strategy()) is MapDictStrategy:
+            w_olddict.get_strategy().switch_to_object_strategy(w_olddict)
+        flag = self._get_mapdict_map().write(self, "dict", SPECIAL, w_dict)
+        assert flag
+
+
+    # slots
+
+    def getslotvalue(self, slotindex):
+        map = self._get_mapdict_map()
+        if map is None:
+            # not a user-defined subclass
+            raise NotImplementedError
+        index = SLOTS_STARTING_FROM + slotindex
+        return map.read(self, "slot", index)
+
+    def setslotvalue(self, slotindex, w_value):
+        map = self._get_mapdict_map()
+        if map is None:
+            # not a user-defined subclass
+            raise NotImplementedError
+        index = SLOTS_STARTING_FROM + slotindex
+        map.write(self, "slot", index, w_value)
+
+    def delslotvalue(self, slotindex):
+        map = self._get_mapdict_map()
+        if map is None:
+            # not a user-defined subclass
+            raise NotImplementedError
+        index = SLOTS_STARTING_FROM + slotindex
+        new_obj = map.delete(self, "slot", index)
+        if new_obj is None:
+            return False
+        self._set_mapdict_storage_and_map(new_obj.storage, new_obj.map)
+        return True
+
+
+    # weakrefs
+
+    def getweakref(self):
+        from pypy.module._weakref.interp__weakref import WeakrefLifeline
+        map = self._get_mapdict_map()
+        if map is None:
+            return None # not a user-defined subclass
+        lifeline = map.read(self, "weakref", SPECIAL)
+        if lifeline is None:
+            return None
+        assert isinstance(lifeline, WeakrefLifeline)
+        return lifeline
+    getweakref._cannot_really_call_random_things_ = True
+
+    def setweakref(self, space, weakreflifeline):
+        from pypy.module._weakref.interp__weakref import WeakrefLifeline
+        map = self._get_mapdict_map()
+        if map is None:
+            # not a user-defined subclass
+            raise oefmt(space.w_TypeError,
+                        "cannot create weak reference to '%T' object", self)
+        assert isinstance(weakreflifeline, WeakrefLifeline)
+        map.write(self, "weakref", SPECIAL, weakreflifeline)
+    setweakref._cannot_really_call_random_things_ = True
+
+    def delweakref(self):
+        map = self._get_mapdict_map()
+        if map is None:
+            return
+        map.write(self, "weakref", SPECIAL, None)
+    delweakref._cannot_really_call_random_things_ = True
diff --git a/pypy/objspace/std/mapdict.py b/pypy/objspace/std/mapdict.py
--- a/pypy/objspace/std/mapdict.py
+++ b/pypy/objspace/std/mapdict.py
@@ -10,6 +10,8 @@
     W_DictObject,
 )
 from pypy.objspace.std.typeobject import MutableCell
+from pypy.objspace.std.basemapdictobject import (DICT, SPECIAL,
+        SLOTS_STARTING_FROM, INVALID)
 
 
 erase_item, unerase_item = rerased.new_erasing_pair("mapdict storage item")
@@ -277,7 +279,7 @@
     def copy(self, obj):
         result = Object()
         result.space = self.space
-        result._init_empty(self)
+        result._mapdict_init_empty(self)
         return result
 
     def length(self):
@@ -286,7 +288,7 @@
     def set_terminator(self, obj, terminator):
         result = Object()
         result.space = self.space
-        result._init_empty(terminator)
+        result._mapdict_init_empty(terminator)
         return result
 
     def remove_dict_entries(self, obj):
@@ -297,6 +299,9 @@
 
 class DictTerminator(Terminator):
     _immutable_fields_ = ['devolved_dict_terminator']
+
+    has_dict = True
+
     def __init__(self, space, w_cls):
         Terminator.__init__(self, space, w_cls)
         self.devolved_dict_terminator = DevolvedDictTerminator(space, w_cls)
@@ -304,11 +309,13 @@
     def materialize_r_dict(self, space, obj, dict_w):
         result = Object()
         result.space = space
-        result._init_empty(self.devolved_dict_terminator)
+        result._mapdict_init_empty(self.devolved_dict_terminator)
         return result
 
 
 class NoDictTerminator(Terminator):
+    has_dict = False
+
     def _write_terminator(self, obj, name, index, w_value):
         if index == DICT:
             return False
@@ -316,6 +323,8 @@
 
 
 class DevolvedDictTerminator(Terminator):
+    has_dict = True
+
     def _read_terminator(self, obj, name, index):
         if index == DICT:
             space = self.space
@@ -417,11 +426,6 @@
     def __repr__(self):
         return "<PlainAttribute %s %s %s %r>" % (self.name, self.index, self.storageindex, self.back)
 
-def _become(w_obj, new_obj):
-    # this is like the _become method, really, but we cannot use that due to
-    # RPython reasons
-    w_obj._set_mapdict_storage_and_map(new_obj.storage, new_obj.map)
-
 class MapAttrCache(object):
     def __init__(self, space):
         SIZE = 1 << space.config.objspace.std.methodcachesizeexp
@@ -445,11 +449,6 @@
 # ____________________________________________________________
 # object implementation
 
-DICT = 0
-SPECIAL = 1
-INVALID = 2
-SLOTS_STARTING_FROM = 3
-
 # a little bit of a mess of mixin classes that implement various pieces of
 # objspace user object functionality in terms of mapdict
 
@@ -457,16 +456,13 @@
     # everything that's needed to use mapdict for a user subclass at all.
     # This immediately makes slots possible.
 
-    # assumes presence of _init_empty, _mapdict_read_storage,
+    # assumes presence of _mapdict_init_empty, _mapdict_read_storage,
     # _mapdict_write_storage, _mapdict_storage_length,
     # _set_mapdict_storage_and_map
 
     # _____________________________________________
     # methods needed for mapdict
 
-    def _become(self, new_obj):
-        self._set_mapdict_storage_and_map(new_obj.storage, new_obj.map)
-
     def _get_mapdict_map(self):
         return jit.promote(self.map)
     def _set_mapdict_map(self, map):
@@ -480,59 +476,13 @@
     def getclass(self, space):
         return self._get_mapdict_map().terminator.w_cls
 
-    def setclass(self, space, w_cls):
-        new_obj = self._get_mapdict_map().set_terminator(self, w_cls.terminator)
-        self._become(new_obj)
-
     def user_setup(self, space, w_subtype):
         from pypy.module.__builtin__.interp_classobj import W_InstanceObject
         self.space = space
         assert (not self.typedef.hasdict or
                 isinstance(w_subtype.terminator, NoDictTerminator) or
                 self.typedef is W_InstanceObject.typedef)
-        self._init_empty(w_subtype.terminator)
-
-
-    # methods needed for slots
-
-    def getslotvalue(self, slotindex):
-        index = SLOTS_STARTING_FROM + slotindex
-        return self._get_mapdict_map().read(self, "slot", index)
-
-    def setslotvalue(self, slotindex, w_value):
-        index = SLOTS_STARTING_FROM + slotindex
-        self._get_mapdict_map().write(self, "slot", index, w_value)
-
-    def delslotvalue(self, slotindex):
-        index = SLOTS_STARTING_FROM + slotindex
-        new_obj = self._get_mapdict_map().delete(self, "slot", index)
-        if new_obj is None:
-            return False
-        self._become(new_obj)
-        return True
-
-
-class MapdictWeakrefSupport(object):
-    # stuff used by the _weakref implementation
-
-    def getweakref(self):
-        from pypy.module._weakref.interp__weakref import WeakrefLifeline
-        lifeline = self._get_mapdict_map().read(self, "weakref", SPECIAL)
-        if lifeline is None:
-            return None
-        assert isinstance(lifeline, WeakrefLifeline)
-        return lifeline
-    getweakref._cannot_really_call_random_things_ = True
-
-    def setweakref(self, space, weakreflifeline):
-        from pypy.module._weakref.interp__weakref import WeakrefLifeline
-        assert isinstance(weakreflifeline, WeakrefLifeline)
-        self._get_mapdict_map().write(self, "weakref", SPECIAL, weakreflifeline)
-    setweakref._cannot_really_call_random_things_ = True
-
-    def delweakref(self):
-        self._get_mapdict_map().write(self, "weakref", SPECIAL, None)
-    delweakref._cannot_really_call_random_things_ = True
+        self._mapdict_init_empty(w_subtype.terminator)
 
 
 class MapdictDictSupport(object):
@@ -545,61 +495,9 @@
     def setdictvalue(self, space, attrname, w_value):
         return self._get_mapdict_map().write(self, attrname, DICT, w_value)
 
-    def deldictvalue(self, space, attrname):
-        new_obj = self._get_mapdict_map().delete(self, attrname, DICT)
-        if new_obj is None:
-            return False
-        self._become(new_obj)
-        return True
-
-    def getdict(self, space):
-        return _obj_getdict(self, space)
-
-    def setdict(self, space, w_dict):
-        _obj_setdict(self, space, w_dict)
-
-# a couple of helpers for the classes above, factored out to reduce
-# the translated code size
-
- at objectmodel.dont_inline
-def _obj_getdict(self, space):
-    terminator = self._get_mapdict_map().terminator
-    assert isinstance(terminator, DictTerminator) or isinstance(terminator, DevolvedDictTerminator)
-    w_dict = self._get_mapdict_map().read(self, "dict", SPECIAL)
-    if w_dict is not None:
-        assert isinstance(w_dict, W_DictMultiObject)
-        return w_dict
-
-    strategy = space.fromcache(MapDictStrategy)
-    storage = strategy.erase(self)
-    w_dict = W_DictObject(space, strategy, storage)
-    flag = self._get_mapdict_map().write(self, "dict", SPECIAL, w_dict)
-    assert flag
-    return w_dict
-
- at objectmodel.dont_inline
-def _obj_setdict(self, space, w_dict):
-    from pypy.interpreter.error import OperationError
-    terminator = self._get_mapdict_map().terminator
-    assert isinstance(terminator, DictTerminator) or isinstance(terminator, DevolvedDictTerminator)
-    if not space.isinstance_w(w_dict, space.w_dict):
-        raise OperationError(space.w_TypeError,
-                space.wrap("setting dictionary to a non-dict"))
-    assert isinstance(w_dict, W_DictMultiObject)
-    w_olddict = self.getdict(space)
-    assert isinstance(w_olddict, W_DictMultiObject)
-    # The old dict has got 'self' as dstorage, but we are about to
-    # change self's ("dict", SPECIAL) attribute to point to the
-    # new dict.  If the old dict was using the MapDictStrategy, we
-    # have to force it now: otherwise it would remain an empty
-    # shell that continues to delegate to 'self'.
-    if type(w_olddict.get_strategy()) is MapDictStrategy:
-        w_olddict.get_strategy().switch_to_object_strategy(w_olddict)
-    flag = self._get_mapdict_map().write(self, "dict", SPECIAL, w_dict)
-    assert flag
 
 class MapdictStorageMixin(object):
-    def _init_empty(self, map):
+    def _mapdict_init_empty(self, map):
         from rpython.rlib.debug import make_sure_not_resized
         self.map = map
         self.storage = make_sure_not_resized([None] * map.size_estimate())
@@ -622,7 +520,6 @@
     objectmodel.import_from_mixin(MapdictStorageMixin)
 
     objectmodel.import_from_mixin(BaseUserClassMapdict)
-    objectmodel.import_from_mixin(MapdictWeakrefSupport)
 
 
 class Object(W_Root):
@@ -630,7 +527,6 @@
     objectmodel.import_from_mixin(MapdictStorageMixin)
 
     objectmodel.import_from_mixin(BaseUserClassMapdict)
-    objectmodel.import_from_mixin(MapdictWeakrefSupport)
     objectmodel.import_from_mixin(MapdictDictSupport)
 
 
@@ -643,7 +539,7 @@
     rangenmin1 = unroll.unrolling_iterable(range(nmin1))
     valnmin1 = "_value%s" % nmin1
     class subcls(object):
-        def _init_empty(self, map):
+        def _mapdict_init_empty(self, map):
             for i in rangenmin1:
                 setattr(self, "_value%s" % i, None)
             setattr(self, valnmin1, erase_item(None))
@@ -731,7 +627,7 @@
     def get_empty_storage(self):
         w_result = Object()
         terminator = self.space.fromcache(get_terminator_for_dicts)
-        w_result._init_empty(terminator)
+        w_result._mapdict_init_empty(terminator)
         return self.erase(w_result)
 
     def switch_to_object_strategy(self, w_dict):
@@ -811,7 +707,7 @@
     def clear(self, w_dict):
         w_obj = self.unerase(w_dict.dstorage)
         new_obj = w_obj._get_mapdict_map().remove_dict_entries(w_obj)
-        _become(w_obj, new_obj)
+        w_obj._set_mapdict_storage_and_map(new_obj.storage, new_obj.map)
 
     def popitem(self, w_dict):
         curr = self.unerase(w_dict.dstorage)._get_mapdict_map().search(DICT)
@@ -833,10 +729,10 @@
         return MapDictIteratorItems(self.space, self, w_dict)
 
 
-def materialize_r_dict(space, obj, dict_w):
-    map = obj._get_mapdict_map()
-    new_obj = map.materialize_r_dict(space, obj, dict_w)
-    _become(obj, new_obj)
+def materialize_r_dict(space, w_obj, dict_w):
+    map = w_obj._get_mapdict_map()
+    new_obj = map.materialize_r_dict(space, w_obj, dict_w)
+    w_obj._set_mapdict_storage_and_map(new_obj.storage, new_obj.map)
 
 class MapDictIteratorKeys(BaseKeyIterator):
     def __init__(self, space, strategy, dictimplementation):


More information about the pypy-commit mailing list