[pypy-commit] pypy remove-list-smm-2: hg merge remove-dict-smm

Manuel Jacob noreply at buildbot.pypy.org
Fri May 17 16:24:47 CEST 2013


Author: Manuel Jacob
Branch: remove-list-smm-2
Changeset: r64259:45c2aa4fb0ed
Date: 2013-05-17 15:18 +0200
http://bitbucket.org/pypy/pypy/changeset/45c2aa4fb0ed/

Log:	hg merge remove-dict-smm

diff --git a/lib-python/2.7/socket.py b/lib-python/2.7/socket.py
--- a/lib-python/2.7/socket.py
+++ b/lib-python/2.7/socket.py
@@ -324,7 +324,12 @@
                 if self._close:
                     self._sock.close()
                 else:
-                    self._sock._decref_socketios()
+                    try:
+                        self._sock._decref_socketios()
+                    except AttributeError:
+                        pass  # bah, someone built a _fileobject manually
+                              # with some unexpected replacement of the
+                              # _socketobject class
             self._sock = None
 
     def __del__(self):
diff --git a/lib-python/2.7/test/test_codecs.py b/lib-python/2.7/test/test_codecs.py
--- a/lib-python/2.7/test/test_codecs.py
+++ b/lib-python/2.7/test/test_codecs.py
@@ -2,7 +2,11 @@
 import unittest
 import codecs
 import locale
-import sys, StringIO, _testcapi
+import sys, StringIO
+try:
+    import _testcapi
+except ImportError:
+    _testcapi = None
 
 class Queue(object):
     """
@@ -1387,8 +1391,7 @@
                     decodedresult += reader.read()
                 self.assertEqual(decodedresult, s, "%r != %r (encoding=%r)" % (decodedresult, s, encoding))
 
-            if (encoding not in broken_incremental_coders and
-                hasattr(_testcapi, 'codec_incrementalencoder')):
+            if encoding not in broken_incremental_coders and _testcapi:
                 # check incremental decoder/encoder (fetched via the Python
                 # and C API) and iterencode()/iterdecode()
                 try:
diff --git a/lib-python/2.7/test/test_descr.py b/lib-python/2.7/test/test_descr.py
--- a/lib-python/2.7/test/test_descr.py
+++ b/lib-python/2.7/test/test_descr.py
@@ -2080,9 +2080,8 @@
         except ImportError:
             pass
         else:
-            if hasattr(_testcapi, 'test_with_docstring'):
-                class X(object):
-                    p = property(_testcapi.test_with_docstring)
+            class X(object):
+                p = property(_testcapi.test_with_docstring)
 
     def test_properties_plus(self):
         class C(object):
diff --git a/lib-python/2.7/test/test_traceback.py b/lib-python/2.7/test/test_traceback.py
--- a/lib-python/2.7/test/test_traceback.py
+++ b/lib-python/2.7/test/test_traceback.py
@@ -180,7 +180,7 @@
 
     def test_traceback_format(self):
         if traceback_print is None:
-            return
+            raise unittest.SkipTest('Requires _testcapi')
         try:
             raise KeyError('blah')
         except KeyError:
diff --git a/lib-python/2.7/test/test_unicode.py b/lib-python/2.7/test/test_unicode.py
--- a/lib-python/2.7/test/test_unicode.py
+++ b/lib-python/2.7/test/test_unicode.py
@@ -1612,7 +1612,7 @@
         try:
             from _testcapi import unicode_encodedecimal
         except ImportError:
-            return
+            raise unittest.SkipTest('Requires _testcapi')
         self.assertEqual(unicode_encodedecimal(u'123'),
                          b'123')
         self.assertEqual(unicode_encodedecimal(u'\u0663.\u0661\u0664'),
diff --git a/lib-python/conftest.py b/lib-python/conftest.py
--- a/lib-python/conftest.py
+++ b/lib-python/conftest.py
@@ -130,7 +130,7 @@
     RegrTest('test_bz2.py', usemodules='bz2'),
     RegrTest('test_calendar.py'),
     RegrTest('test_call.py', core=True),
-    RegrTest('test_capi.py'),
+    RegrTest('test_capi.py', usemodules='cpyext'),
     RegrTest('test_cd.py'),
     RegrTest('test_cfgparser.py'),
     RegrTest('test_cgi.py'),
@@ -177,7 +177,7 @@
     RegrTest('test_cprofile.py'),
     RegrTest('test_crypt.py', usemodules='crypt'),
     RegrTest('test_csv.py', usemodules='_csv'),
-    RegrTest('test_ctypes.py', usemodules="_rawffi thread"),
+    RegrTest('test_ctypes.py', usemodules="_rawffi thread cpyext"),
     RegrTest('test_curses.py'),
     RegrTest('test_datetime.py', usemodules='binascii struct'),
     RegrTest('test_dbm.py'),
diff --git a/lib_pypy/_testcapi.py b/lib_pypy/_testcapi.py
--- a/lib_pypy/_testcapi.py
+++ b/lib_pypy/_testcapi.py
@@ -57,6 +57,6 @@
 try:
     import cpyext
 except ImportError:
-    pass
+    raise ImportError("No module named '_testcapi'")
 else:
     compile_shared()
diff --git a/pypy/doc/conf.py b/pypy/doc/conf.py
--- a/pypy/doc/conf.py
+++ b/pypy/doc/conf.py
@@ -47,7 +47,7 @@
 # The short X.Y version.
 version = '2.0'
 # The full version, including alpha/beta/rc tags.
-release = '2.0.0'
+release = '2.0.1'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
diff --git a/pypy/doc/how-to-release.rst b/pypy/doc/how-to-release.rst
--- a/pypy/doc/how-to-release.rst
+++ b/pypy/doc/how-to-release.rst
@@ -22,7 +22,8 @@
   will capture the revision number of this change for the release;
   some of the next updates may be done before or after branching; make
   sure things are ported back to the trunk and to the branch as
-  necessary
+  necessary; also update the version number in pypy/doc/conf.py,
+  and in pypy/doc/index.rst
 * update pypy/doc/contributor.rst (and possibly LICENSE)
 * rename pypy/doc/whatsnew_head.rst to whatsnew_VERSION.rst
   and create a fresh whatsnew_head.rst after the release
diff --git a/pypy/doc/index.rst b/pypy/doc/index.rst
--- a/pypy/doc/index.rst
+++ b/pypy/doc/index.rst
@@ -40,7 +40,7 @@
 
 * `FAQ`_: some frequently asked questions.
 
-* `Release 2.0`_: the latest official release
+* `Release 2.0.1`_: the latest official release
 
 * `PyPy Blog`_: news and status info about PyPy 
 
@@ -110,7 +110,7 @@
 .. _`Getting Started`: getting-started.html
 .. _`Papers`: extradoc.html
 .. _`Videos`: video-index.html
-.. _`Release 2.0`: http://pypy.org/download.html
+.. _`Release 2.0.1`: http://pypy.org/download.html
 .. _`speed.pypy.org`: http://speed.pypy.org
 .. _`RPython toolchain`: translation.html
 .. _`potential project ideas`: project-ideas.html
diff --git a/pypy/doc/release-2.0.1.rst b/pypy/doc/release-2.0.1.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/release-2.0.1.rst
@@ -0,0 +1,46 @@
+==============================
+PyPy 2.0.1 - Bohr Smørrebrød
+==============================
+
+We're pleased to announce PyPy 2.0.1.  This is a stable bugfix release
+over `2.0`_.  You can download it here:
+  
+    http://pypy.org/download.html
+
+The fixes are mainly about fatal errors or crashes in our stdlib.  See
+below for more details.
+
+What is PyPy?
+=============
+
+PyPy is a very compliant Python interpreter, almost a drop-in replacement for
+CPython 2.7. It's fast (`pypy 2.0 and cpython 2.7.3`_ performance comparison)
+due to its integrated tracing JIT compiler.
+
+This release supports x86 machines running Linux 32/64, Mac OS X 64 or
+Windows 32.  Support for ARM is progressing but not bug-free yet.
+
+.. _`pypy 2.0 and cpython 2.7.3`: http://speed.pypy.org
+
+Highlights
+==========
+
+- fix an occasional crash in the JIT that ends in `RPython Fatal error:
+  NotImplementedError`__.
+
+- `id(x)` is now always a positive number (except on int/float/long/complex).
+  This fixes an issue in ``_sqlite.py`` (mostly for 32-bit Linux).
+
+- fix crashes of callback-from-C-functions (with cffi) when used together
+  with Stackless features, on asmgcc (i.e. Linux only).  Now `gevent should
+  work better`__.
+
+- work around an eventlet issue with `socket._decref_socketios()`__.
+
+.. __: https://bugs.pypy.org/issue1482
+.. __: http://mail.python.org/pipermail/pypy-dev/2013-May/011362.html
+.. __: https://bugs.pypy.org/issue1468
+.. _2.0: release-2.0.0.html
+
+Cheers,
+arigo et. al. for the PyPy team
diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
--- a/pypy/doc/whatsnew-head.rst
+++ b/pypy/doc/whatsnew-head.rst
@@ -16,3 +16,9 @@
 
 .. branch: remove-set-smm
 Remove multi-methods on sets
+
+.. branch: numpy-subarrays
+Implement subarrays for numpy
+
+.. branch: remove-dict-smm
+Remove multi-methods on dict
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -242,6 +242,11 @@
     def __spacebind__(self, space):
         return self
 
+    def unwrap(self, space):
+        """NOT_RPYTHON"""
+        # _____ this code is here to support testing only _____
+        return self
+
 
 class W_InterpIterable(W_Root):
     def __init__(self, space, w_iterable):
diff --git a/pypy/interpreter/test/test_app_main.py b/pypy/interpreter/test/test_app_main.py
--- a/pypy/interpreter/test/test_app_main.py
+++ b/pypy/interpreter/test/test_app_main.py
@@ -920,7 +920,7 @@
             import app_main
             app_main.setup_bootstrap_path('/tmp/pypy-c') # stdlib not found
             assert sys.executable == ''
-            assert sys.path == old_sys_path + [self.goal_dir]
+            assert sys.path == old_sys_path
 
             app_main.setup_bootstrap_path(self.fake_exe)
             assert sys.executable == self.fake_exe
diff --git a/pypy/module/_cffi_backend/cdataobj.py b/pypy/module/_cffi_backend/cdataobj.py
--- a/pypy/module/_cffi_backend/cdataobj.py
+++ b/pypy/module/_cffi_backend/cdataobj.py
@@ -114,8 +114,11 @@
     ge = _make_comparison('ge')
 
     def hash(self):
-        h = (objectmodel.compute_identity_hash(self.ctype) ^
-             rffi.cast(lltype.Signed, self._cdata))
+        h = rffi.cast(lltype.Signed, self._cdata)
+        # To hash pointers in dictionaries.  Assumes that h shows some
+        # alignment (to 4, 8, maybe 16 bytes), so we use the following
+        # formula to avoid the trailing bits being always 0.
+        h = h ^ (h >> 4)
         return self.space.wrap(h)
 
     def getitem(self, w_index):
diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py
--- a/pypy/module/_cffi_backend/test/_backend_test_c.py
+++ b/pypy/module/_cffi_backend/test/_backend_test_c.py
@@ -365,8 +365,9 @@
     BInt = new_primitive_type("int")
     BFloat = new_primitive_type("float")
     for i in range(1, 20):
-        if (hash(cast(BChar, chr(i))) !=
-            hash(cast(BInt, i))):
+        x1 = cast(BChar, chr(i))
+        x2 = cast(BInt, i)
+        if hash(x1) != hash(x2):
             break
     else:
         raise AssertionError("hashes are equal")
@@ -2723,6 +2724,14 @@
     assert x.__name__ == '<cdata>'
     assert hasattr(x, '__doc__')
 
+def test_different_types_of_ptr_equality():
+    BVoidP = new_pointer_type(new_void_type())
+    BIntP = new_pointer_type(new_primitive_type("int"))
+    x = cast(BVoidP, 12345)
+    assert x == cast(BIntP, 12345)
+    assert x != cast(BIntP, 12344)
+    assert hash(x) == hash(cast(BIntP, 12345))
+
 def test_version():
     # this test is here mostly for PyPy
     assert __version__ == "0.6"
diff --git a/pypy/module/_ffi/test/test_funcptr.py b/pypy/module/_ffi/test/test_funcptr.py
--- a/pypy/module/_ffi/test/test_funcptr.py
+++ b/pypy/module/_ffi/test/test_funcptr.py
@@ -74,9 +74,9 @@
         from _ffi import CDLL, types
         # this should return *all* loaded libs, dlopen(NULL)
         dll = CDLL(None)
-        # Assume CPython, or PyPy compiled with cpyext
-        res = dll.getfunc('Py_IsInitialized', [], types.slong)()
-        assert res == 1
+        # libm should be loaded
+        res = dll.getfunc('sqrt', [types.double], types.double)(1.0)
+        assert res == 1.0
 
     def test_callfunc(self):
         from _ffi import CDLL, types
@@ -139,7 +139,7 @@
 
     def test_pointer_args(self):
         """
-            extern int dummy; // defined in test_void_result 
+            extern int dummy; // defined in test_void_result
             DLLEXPORT int* get_dummy_ptr() { return &dummy; }
             DLLEXPORT void set_val_to_ptr(int* ptr, int val) { *ptr = val; }
         """
@@ -158,7 +158,7 @@
 
     def test_convert_pointer_args(self):
         """
-            extern int dummy; // defined in test_void_result 
+            extern int dummy; // defined in test_void_result
             DLLEXPORT int* get_dummy_ptr(); // defined in test_pointer_args
             DLLEXPORT void set_val_to_ptr(int* ptr, int val); // ditto
         """
@@ -170,7 +170,7 @@
             def _as_ffi_pointer_(self, ffitype):
                 assert ffitype is types.void_p
                 return self.value
-        
+
         libfoo = CDLL(self.libfoo_name)
         get_dummy = libfoo.getfunc('get_dummy', [], types.sint)
         get_dummy_ptr = libfoo.getfunc('get_dummy_ptr', [], types.void_p)
@@ -259,7 +259,7 @@
 
     def test_typed_pointer_args(self):
         """
-            extern int dummy; // defined in test_void_result 
+            extern int dummy; // defined in test_void_result
             DLLEXPORT int* get_dummy_ptr(); // defined in test_pointer_args
             DLLEXPORT void set_val_to_ptr(int* ptr, int val); // ditto
         """
@@ -551,7 +551,7 @@
         from _ffi import CDLL, types
         libfoo = CDLL(self.libfoo_name)
         raises(TypeError, "libfoo.getfunc('sum_xy', [types.void], types.sint)")
-        
+
     def test_OSError_loading(self):
         from _ffi import CDLL, types
         raises(OSError, "CDLL('I do not exist')")
@@ -606,7 +606,7 @@
         from _rawffi import FUNCFLAG_STDCALL
         libm = CDLL(self.libm_name)
         pow_addr = libm.getaddressindll('pow')
-        wrong_pow = FuncPtr.fromaddr(pow_addr, 'pow', 
+        wrong_pow = FuncPtr.fromaddr(pow_addr, 'pow',
                 [types.double, types.double], types.double, FUNCFLAG_STDCALL)
         try:
             wrong_pow(2, 3) == 8
@@ -622,7 +622,7 @@
         from _rawffi import FUNCFLAG_STDCALL
         kernel = WinDLL('Kernel32.dll')
         sleep_addr = kernel.getaddressindll('Sleep')
-        sleep = FuncPtr.fromaddr(sleep_addr, 'sleep', [types.uint], 
+        sleep = FuncPtr.fromaddr(sleep_addr, 'sleep', [types.uint],
                             types.void, FUNCFLAG_STDCALL)
         sleep(10)
 
diff --git a/pypy/module/sys/initpath.py b/pypy/module/sys/initpath.py
--- a/pypy/module/sys/initpath.py
+++ b/pypy/module/sys/initpath.py
@@ -68,7 +68,7 @@
     If it cannot be found, return (None, None).
     """
     if executable == '':
-        return None, None
+        executable = 'pypy-c'
     search = executable
     while True:
         dirname = resolvedirof(search)
diff --git a/pypy/module/sys/system.py b/pypy/module/sys/system.py
--- a/pypy/module/sys/system.py
+++ b/pypy/module/sys/system.py
@@ -1,6 +1,6 @@
 """Information about the current system."""
 from pypy.interpreter import gateway
-from rpython.rlib import rfloat, rbigint
+from rpython.rlib import rbigint, rfloat
 from rpython.rtyper.lltypesystem import rffi
 
 
@@ -47,7 +47,6 @@
     return space.call_function(w_float_info, space.newtuple(info_w))
 
 def get_long_info(space):
-    #assert rbigint.SHIFT == 31
     bits_per_digit = rbigint.SHIFT
     sizeof_digit = rffi.sizeof(rbigint.STORE_TYPE)
     info_w = [
@@ -58,7 +57,4 @@
     return space.call_function(w_long_info, space.newtuple(info_w))
 
 def get_float_repr_style(space):
-    if rfloat.USE_SHORT_FLOAT_REPR:
-        return space.wrap("short")
-    else:
-        return space.wrap("legacy")
+    return space.wrap("short" if rfloat.USE_SHORT_FLOAT_REPR else "legacy")
diff --git a/pypy/module/sys/test/test_initpath.py b/pypy/module/sys/test/test_initpath.py
--- a/pypy/module/sys/test/test_initpath.py
+++ b/pypy/module/sys/test/test_initpath.py
@@ -16,9 +16,12 @@
     build_hierarchy(tmpdir)
     path, prefix = find_stdlib(None, str(pypy))
     assert prefix == tmpdir
-    # shouldn't find stdlib if executable == '' even if parent dir has a stdlib
-    monkeypatch.chdir(tmpdir.join('bin'))
-    assert find_stdlib(None, '') == (None, None)
+    # in executable is None look for stdlib based on the working directory
+    # see lib-python/2.7/test/test_sys.py:test_executable
+    _, prefix = find_stdlib(None, '')
+    cwd = os.path.dirname(os.path.realpath(__file__))
+    assert prefix is not None
+    assert cwd.startswith(str(prefix))
 
 @py.test.mark.skipif('not hasattr(os, "symlink")')
 def test_find_stdlib_follow_symlink(tmpdir):
diff --git a/pypy/objspace/fake/checkmodule.py b/pypy/objspace/fake/checkmodule.py
--- a/pypy/objspace/fake/checkmodule.py
+++ b/pypy/objspace/fake/checkmodule.py
@@ -5,7 +5,6 @@
 def checkmodule(*modnames):
     config = get_pypy_config(translating=True)
     space = FakeObjSpace(config)
-    space.setup()
     seeobj_w = []
     for modname in modnames:
         mod = __import__('pypy.module.%s' % modname, None, None, ['__doc__'])
diff --git a/pypy/objspace/fake/objspace.py b/pypy/objspace/fake/objspace.py
--- a/pypy/objspace/fake/objspace.py
+++ b/pypy/objspace/fake/objspace.py
@@ -110,6 +110,7 @@
     def __init__(self, config=None):
         self._seen_extras = []
         ObjSpace.__init__(self, config=config)
+        self.setup()
 
     def _freeze_(self):
         return True
diff --git a/pypy/objspace/std/dictmultiobject.py b/pypy/objspace/std/dictmultiobject.py
--- a/pypy/objspace/std/dictmultiobject.py
+++ b/pypy/objspace/std/dictmultiobject.py
@@ -1,19 +1,19 @@
-import py, sys
-from pypy.objspace.std.model import registerimplementation, W_Object
-from pypy.objspace.std.register_all import register_all
-from pypy.objspace.std.setobject import set_typedef as settypedef
-from pypy.objspace.std.setobject import frozenset_typedef as frozensettypedef
+from pypy.interpreter import gateway
+from pypy.interpreter.baseobjspace import W_Root
 from pypy.interpreter.error import OperationError, operationerrfmt
+from pypy.interpreter.mixedmodule import MixedModule
 from pypy.interpreter.signature import Signature
+from pypy.objspace.std.stdtypedef import StdTypeDef
 
+from rpython.rlib import rerased, jit
+from rpython.rlib.debug import mark_dict_non_null
 from rpython.rlib.objectmodel import r_dict, specialize, newlist_hint
-from rpython.rlib.debug import mark_dict_non_null
 from rpython.tool.sourcetools import func_with_new_name
 
-from rpython.rlib import rerased, jit
 
 UNROLL_CUTOFF = 5
 
+
 def _is_str(space, w_key):
     return space.is_w(space.type(w_key), space.w_str)
 
@@ -40,9 +40,20 @@
                                     w_dct.length() <= UNROLL_CUTOFF)
 
 
-class W_DictMultiObject(W_Object):
-    from pypy.objspace.std.dicttype import dict_typedef as typedef
+def negate(f):
+    def _negator(self, space, w_other):
+        # no need to use space.is_ / space.not_
+        tmp = f(self, space, w_other)
+        if tmp is space.w_NotImplemented:
+            return space.w_NotImplemented
+        elif tmp is space.w_False:
+            return space.w_True
+        else:
+            return space.w_False
+    _negator.func_name = 'negate-%s' % f.func_name
+    return _negator
 
+class W_DictMultiObject(W_Root):
     @staticmethod
     def allocate_and_init_instance(space, w_type=None, module=False,
                                    instance=False, strdict=False, kwargs=False):
@@ -108,6 +119,230 @@
     def setitem_str(self, key, w_value):
         self.strategy.setitem_str(self, key, w_value)
 
+    @staticmethod
+    def descr_new(space, w_dicttype, __args__):
+        w_obj = W_DictMultiObject.allocate_and_init_instance(space, w_dicttype)
+        return w_obj
+
+    @staticmethod
+    def descr_fromkeys(space, w_type, w_keys, w_fill=None):
+        if w_fill is None:
+            w_fill = space.w_None
+        if space.is_w(w_type, space.w_dict):
+            w_dict = W_DictMultiObject.allocate_and_init_instance(space, w_type)
+
+            strlist = space.listview_str(w_keys)
+            if strlist is not None:
+                for key in strlist:
+                    w_dict.setitem_str(key, w_fill)
+            else:
+                for w_key in space.listview(w_keys):
+                    w_dict.setitem(w_key, w_fill)
+        else:
+            w_dict = space.call_function(w_type)
+            for w_key in space.listview(w_keys):
+                space.setitem(w_dict, w_key, w_fill)
+        return w_dict
+
+    def descr_init(self, space, __args__):
+        init_or_update(space, self, __args__, 'dict')
+
+    def descr_repr(self, space):
+        ec = space.getexecutioncontext()
+        w_currently_in_repr = ec._py_repr
+        if w_currently_in_repr is None:
+            w_currently_in_repr = ec._py_repr = space.newdict()
+        return dictrepr(space, w_currently_in_repr, self)
+
+    def descr_eq(self, space, w_other):
+        if space.is_w(self, w_other):
+            return space.w_True
+        if not isinstance(w_other, W_DictMultiObject):
+            return space.w_NotImplemented
+
+        if self.length() != w_other.length():
+            return space.w_False
+        iteratorimplementation = self.iteritems()
+        while 1:
+            w_key, w_val = iteratorimplementation.next_item()
+            if w_key is None:
+                break
+            w_rightval = w_other.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 descr_lt(self, space, w_other):
+        if not isinstance(w_other, W_DictMultiObject):
+            return space.w_NotImplemented
+        return self._compare_lt(space, w_other)
+
+    def descr_gt(self, space, w_other):
+        if not isinstance(w_other, W_DictMultiObject):
+            return space.w_NotImplemented
+        return w_other._compare_lt(space, self)
+
+    def _compare_lt(self, space, w_other):
+        # Different sizes, no problem
+        if self.length() < w_other.length():
+            return space.w_True
+        if self.length() > w_other.length():
+            return space.w_False
+
+        # Same size
+        w_leftdiff, w_leftval = characterize(space, self, w_other)
+        if w_leftdiff is None:
+            return space.w_False
+        w_rightdiff, w_rightval = characterize(space, w_other, self)
+        if w_rightdiff is None:
+            # w_leftdiff is not None, w_rightdiff is None
+            return space.w_True
+        w_res = space.lt(w_leftdiff, w_rightdiff)
+        if (not space.is_true(w_res) and
+            space.eq_w(w_leftdiff, w_rightdiff) and
+            w_rightval is not None):
+            w_res = space.lt(w_leftval, w_rightval)
+        return w_res
+
+    descr_ne = negate(descr_eq)
+    descr_le = negate(descr_gt)
+    descr_ge = negate(descr_lt)
+
+    def descr_len(self, space):
+        return space.wrap(self.length())
+
+    def descr_iter(self, space):
+        return W_DictMultiIterKeysObject(space, self.iterkeys())
+
+    def descr_contains(self, space, w_key):
+        return space.newbool(self.getitem(w_key) is not None)
+
+    def descr_getitem(self, space, w_key):
+        w_value = self.getitem(w_key)
+        if w_value is not None:
+            return w_value
+
+        w_missing_item = self.missing_method(space, w_key)
+        if w_missing_item is not None:
+            return w_missing_item
+
+        space.raise_key_error(w_key)
+
+    def descr_setitem(self, space, w_newkey, w_newvalue):
+        self.setitem(w_newkey, w_newvalue)
+
+    def descr_delitem(self, space, w_key):
+        try:
+            self.delitem(w_key)
+        except KeyError:
+            space.raise_key_error(w_key)
+
+    def descr_reversed(self, space):
+        raise OperationError(space.w_TypeError, space.wrap('argument to reversed() must be a sequence'))
+
+    def descr_copy(self, space):
+        """D.copy() -> a shallow copy of D"""
+        w_new = W_DictMultiObject.allocate_and_init_instance(space)
+        update1_dict_dict(space, w_new, self)
+        return w_new
+
+    def descr_items(self, space):
+        """D.items() -> list of D's (key, value) pairs, as 2-tuples"""
+        return space.newlist(self.items())
+
+    def descr_keys(self, space):
+        """D.keys() -> list of D's keys"""
+        return self.w_keys()
+
+    def descr_values(self, space):
+        """D.values() -> list of D's values"""
+        return space.newlist(self.values())
+
+    def descr_iteritems(self, space):
+        """D.iteritems() -> an iterator over the (key, value) items of D"""
+        return W_DictMultiIterItemsObject(space, self.iteritems())
+
+    def descr_iterkeys(self, space):
+        """D.iterkeys() -> an iterator over the keys of D"""
+        return W_DictMultiIterKeysObject(space, self.iterkeys())
+
+    def descr_itervalues(self, space):
+        """D.itervalues() -> an iterator over the values of D"""
+        return W_DictMultiIterValuesObject(space, self.itervalues())
+
+    def descr_viewitems(self, space):
+        """D.viewitems() -> a set-like object providing a view on D's items"""
+        return W_DictViewItemsObject(space, self)
+
+    def descr_viewkeys(self, space):
+        """D.viewkeys() -> a set-like object providing a view on D's keys"""
+        return W_DictViewKeysObject(space, self)
+
+    def descr_viewvalues(self, space):
+        """D.viewvalues() -> an object providing a view on D's values"""
+        return W_DictViewValuesObject(space, self)
+
+    def descr_has_key(self, space, w_key):
+        """D.has_key(k) -> True if D has a key k, else False"""
+        return space.newbool(self.getitem(w_key) is not None)
+
+    def descr_clear(self, space):
+        """D.clear() -> None.  Remove all items from D."""
+        self.clear()
+
+    @gateway.unwrap_spec(w_default=gateway.WrappedDefault(None))
+    def descr_get(self, space, w_key, w_default):
+        """D.get(k[,d]) -> D[k] if k in D, else d.  d defaults to None."""
+        w_value = self.getitem(w_key)
+        if w_value is not None:
+            return w_value
+        else:
+            return w_default
+
+    @gateway.unwrap_spec(defaults_w='args_w')
+    def descr_pop(self, space, w_key, defaults_w):
+        """D.pop(k[,d]) -> v, remove specified key and return the
+        corresponding value\nIf key is not found, d is returned if given,
+        otherwise KeyError is raised
+        """
+        len_defaults = len(defaults_w)
+        if len_defaults > 1:
+            raise operationerrfmt(space.w_TypeError,
+                                  "pop expected at most 2 arguments, got %d",
+                                  1 + len_defaults)
+        w_item = self.getitem(w_key)
+        if w_item is None:
+            if len_defaults > 0:
+                return defaults_w[0]
+            else:
+                space.raise_key_error(w_key)
+        else:
+            self.delitem(w_key)
+            return w_item
+
+    def descr_popitem(self, space):
+        """D.popitem() -> (k, v), remove and return some (key, value) pair as
+        a\n2-tuple; but raise KeyError if D is empty"""
+        try:
+            w_key, w_value = self.popitem()
+        except KeyError:
+            raise OperationError(space.w_KeyError,
+                                 space.wrap("popitem(): dictionary is empty"))
+        return space.newtuple([w_key, w_value])
+
+    @gateway.unwrap_spec(w_default=gateway.WrappedDefault(None))
+    def descr_setdefault(self, space, w_key, w_default):
+        """D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D"""
+        return self.setdefault(w_key, w_default)
+
+    def descr_update(self, space, __args__):
+        """D.update(E, **F) -> None.  Update D from E and F: for k in E: D[k]
+        = E[k]\n(if E has keys else: for (k, v) in E: D[k] = v) then: for k in
+        F: D[k] = F[k]"""
+        init_or_update(space, self, __args__, 'dict.update')
+
 
 def _add_indirections():
     dict_methods = "getitem getitem_str setitem setdefault \
@@ -128,8 +363,87 @@
 
 _add_indirections()
 
+
+app = gateway.applevel('''
+    def dictrepr(currently_in_repr, d):
+        if len(d) == 0:
+            return "{}"
+        dict_id = id(d)
+        if dict_id in currently_in_repr:
+            return '{...}'
+        currently_in_repr[dict_id] = 1
+        try:
+            items = []
+            # XXX for now, we cannot use iteritems() at app-level because
+            #     we want a reasonable result instead of a RuntimeError
+            #     even if the dict is mutated by the repr() in the loop.
+            for k, v in dict.items(d):
+                items.append(repr(k) + ": " + repr(v))
+            return "{" +  ', '.join(items) + "}"
+        finally:
+            try:
+                del currently_in_repr[dict_id]
+            except:
+                pass
+''', filename=__file__)
+
+dictrepr = app.interphook("dictrepr")
+
+
+W_DictMultiObject.typedef = StdTypeDef("dict",
+    __doc__ = '''dict() -> new empty dictionary.
+dict(mapping) -> new dictionary initialized from a mapping object\'s
+    (key, value) pairs.
+dict(seq) -> new dictionary initialized as if via:
+    d = {}
+    for k, v in seq:
+        d[k] = v
+dict(**kwargs) -> new dictionary initialized with the name=value pairs
+    in the keyword argument list.  For example:  dict(one=1, two=2)''',
+    __new__ = gateway.interp2app(W_DictMultiObject.descr_new),
+    fromkeys = gateway.interp2app(W_DictMultiObject.descr_fromkeys,
+                                  as_classmethod=True),
+    __hash__ = None,
+    __repr__ = gateway.interp2app(W_DictMultiObject.descr_repr),
+    __init__ = gateway.interp2app(W_DictMultiObject.descr_init),
+
+    __eq__ = gateway.interp2app(W_DictMultiObject.descr_eq),
+    __ne__ = gateway.interp2app(W_DictMultiObject.descr_ne),
+    __lt__ = gateway.interp2app(W_DictMultiObject.descr_lt),
+    __le__ = gateway.interp2app(W_DictMultiObject.descr_le),
+    __gt__ = gateway.interp2app(W_DictMultiObject.descr_gt),
+    __ge__ = gateway.interp2app(W_DictMultiObject.descr_ge),
+
+    __len__ = gateway.interp2app(W_DictMultiObject.descr_len),
+    __iter__ = gateway.interp2app(W_DictMultiObject.descr_iter),
+    __contains__ = gateway.interp2app(W_DictMultiObject.descr_contains),
+
+    __getitem__ = gateway.interp2app(W_DictMultiObject.descr_getitem),
+    __setitem__ = gateway.interp2app(W_DictMultiObject.descr_setitem),
+    __delitem__ = gateway.interp2app(W_DictMultiObject.descr_delitem),
+
+    __reversed__ = gateway.interp2app(W_DictMultiObject.descr_reversed),
+    copy = gateway.interp2app(W_DictMultiObject.descr_copy),
+    items = gateway.interp2app(W_DictMultiObject.descr_items),
+    keys = gateway.interp2app(W_DictMultiObject.descr_keys),
+    values = gateway.interp2app(W_DictMultiObject.descr_values),
+    iteritems = gateway.interp2app(W_DictMultiObject.descr_iteritems),
+    iterkeys = gateway.interp2app(W_DictMultiObject.descr_iterkeys),
+    itervalues = gateway.interp2app(W_DictMultiObject.descr_itervalues),
+    viewkeys = gateway.interp2app(W_DictMultiObject.descr_viewkeys),
+    viewitems = gateway.interp2app(W_DictMultiObject.descr_viewitems),
+    viewvalues = gateway.interp2app(W_DictMultiObject.descr_viewvalues),
+    has_key = gateway.interp2app(W_DictMultiObject.descr_has_key),
+    clear = gateway.interp2app(W_DictMultiObject.descr_clear),
+    get = gateway.interp2app(W_DictMultiObject.descr_get),
+    pop = gateway.interp2app(W_DictMultiObject.descr_pop),
+    popitem = gateway.interp2app(W_DictMultiObject.descr_popitem),
+    setdefault = gateway.interp2app(W_DictMultiObject.descr_setdefault),
+    update = gateway.interp2app(W_DictMultiObject.descr_update),
+    )
+
+
 class DictStrategy(object):
-
     def __init__(self, space):
         self.space = space
 
@@ -171,7 +485,6 @@
         # it ends up taking n**2 time, because the next() calls below
         # will take longer and longer.  But all interesting strategies
         # provide a better one.
-        space = self.space
         iterator = self.iteritems(w_dict)
         w_key, w_value = iterator.next_item()
         self.delitem(w_dict, w_key)
@@ -195,8 +508,8 @@
     def view_as_kwargs(self, w_dict):
         return (None, None)
 
+
 class EmptyDictStrategy(DictStrategy):
-
     erase, unerase = rerased.new_erasing_pair("empty")
     erase = staticmethod(erase)
     unerase = staticmethod(unerase)
@@ -301,6 +614,7 @@
     def getiteritems(self, w_dict):
         return iter([(None, None)])
 
+
 # Iterator Implementation base classes
 
 def _new_next(TP):
@@ -308,7 +622,7 @@
         EMPTY = None
     else:
         EMPTY = None, None
-    
+
     def next(self):
         if self.dictimplementation is None:
             return EMPTY
@@ -372,7 +686,7 @@
         wrapvalue = lambda space, key : key
     else:
         wrapvalue = dictimpl.wrapvalue.im_func
-    
+
     class IterClassKeys(BaseKeyIterator):
         def __init__(self, space, strategy, impl):
             self.iterator = strategy.getiterkeys(impl)
@@ -424,11 +738,6 @@
 
 create_iterator_classes(EmptyDictStrategy)
 
-registerimplementation(W_DictMultiObject)
-
-# DictImplementation lattice
-# XXX fix me
-
 
 # concrete subclasses of the above
 
@@ -543,7 +852,6 @@
 
 
 class ObjectDictStrategy(AbstractTypedStrategy, DictStrategy):
-
     erase, unerase = rerased.new_erasing_pair("object")
     erase = staticmethod(erase)
     unerase = staticmethod(unerase)
@@ -576,8 +884,8 @@
 
 create_iterator_classes(ObjectDictStrategy)
 
+
 class StringDictStrategy(AbstractTypedStrategy, DictStrategy):
-
     erase, unerase = rerased.new_erasing_pair("string")
     erase = staticmethod(erase)
     unerase = staticmethod(unerase)
@@ -642,7 +950,6 @@
 
 
 class UnicodeDictStrategy(AbstractTypedStrategy, DictStrategy):
-
     erase, unerase = rerased.new_erasing_pair("unicode")
     erase = staticmethod(erase)
     unerase = staticmethod(unerase)
@@ -744,9 +1051,6 @@
 
 create_iterator_classes(IntDictStrategy)
 
-init_signature = Signature(['seq_or_map'], None, 'kwargs')
-init_defaults = [None]
-
 
 def update1(space, w_dict, w_data):
     if space.findattr(w_data, space.wrap("keys")) is None:
@@ -788,6 +1092,9 @@
         w_dict.setitem(w_key, w_value)
 
 
+init_signature = Signature(['seq_or_map'], None, 'kwargs')
+init_defaults = [None]
+
 def init_or_update(space, w_dict, __args__, funcname):
     w_src, w_kwds = __args__.parse_obj(
             None, funcname,
@@ -798,61 +1105,6 @@
     if space.is_true(w_kwds):
         update1(space, w_dict, w_kwds)
 
-def init__DictMulti(space, w_dict, __args__):
-    init_or_update(space, w_dict, __args__, 'dict')
-
-def dict_update__DictMulti(space, w_dict, __args__):
-    init_or_update(space, w_dict, __args__, 'dict.update')
-
-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_key)
-    if w_missing_item is not None:
-        return w_missing_item
-
-    space.raise_key_error(w_key)
-
-def setitem__DictMulti_ANY_ANY(space, w_dict, w_newkey, w_newvalue):
-    w_dict.setitem(w_newkey, w_newvalue)
-
-def delitem__DictMulti_ANY(space, w_dict, w_key):
-    try:
-        w_dict.delitem(w_key)
-    except KeyError:
-        space.raise_key_error(w_key)
-
-def len__DictMulti(space, w_dict):
-    return space.wrap(w_dict.length())
-
-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_DictMultiIterKeysObject(space, w_dict.iterkeys())
-
-def eq__DictMulti_DictMulti(space, w_left, w_right):
-    if space.is_w(w_left, w_right):
-        return space.w_True
-
-    if w_left.length() != w_right.length():
-        return space.w_False
-    iteratorimplementation = w_left.iteritems()
-    while 1:
-        w_key, w_val = iteratorimplementation.next_item()
-        if w_key is None:
-            break
-        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, 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 """
@@ -874,105 +1126,11 @@
                     w_smallest_diff_a_key = w_key
     return w_smallest_diff_a_key, w_its_value
 
-def lt__DictMulti_DictMulti(space, w_left, w_right):
-    # Different sizes, no problem
-    if w_left.length() < w_right.length():
-        return space.w_True
-    if w_left.length() > w_right.length():
-        return space.w_False
-
-    # Same size
-    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, w_right, w_left)
-    if w_rightdiff is None:
-        # w_leftdiff is not None, w_rightdiff is None
-        return space.w_True
-    w_res = space.lt(w_leftdiff, w_rightdiff)
-    if (not space.is_true(w_res) and
-        space.eq_w(w_leftdiff, w_rightdiff) and
-        w_rightval is not None):
-        w_res = space.lt(w_leftval, w_rightval)
-    return w_res
-
-def dict_copy__DictMulti(space, w_self):
-    w_new = W_DictMultiObject.allocate_and_init_instance(space)
-    update1_dict_dict(space, w_new, w_self)
-    return w_new
-
-def dict_items__DictMulti(space, w_self):
-    return space.newlist(w_self.items())
-
-def dict_keys__DictMulti(space, w_self):
-    return w_self.w_keys()
-
-def dict_values__DictMulti(space, w_self):
-    return space.newlist(w_self.values())
-
-def dict_iteritems__DictMulti(space, w_self):
-    return W_DictMultiIterItemsObject(space, w_self.iteritems())
-
-def dict_iterkeys__DictMulti(space, w_self):
-    return W_DictMultiIterKeysObject(space, w_self.iterkeys())
-
-def dict_itervalues__DictMulti(space, w_self):
-    return W_DictMultiIterValuesObject(space, w_self.itervalues())
-
-def dict_viewitems__DictMulti(space, w_self):
-    return W_DictViewItemsObject(space, w_self)
-
-def dict_viewkeys__DictMulti(space, w_self):
-    return W_DictViewKeysObject(space, w_self)
-
-def dict_viewvalues__DictMulti(space, w_self):
-    return W_DictViewValuesObject(space, w_self)
-
-def dict_clear__DictMulti(space, w_self):
-    w_self.clear()
-
-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_setdefault__DictMulti_ANY_ANY(space, w_dict, w_key, w_default):
-    return w_dict.setdefault(w_key, w_default)
-
-def dict_pop__DictMulti_ANY(space, w_dict, w_key, defaults_w):
-    len_defaults = len(defaults_w)
-    if len_defaults > 1:
-        raise operationerrfmt(space.w_TypeError,
-                              "pop expected at most 2 arguments, got %d",
-                              1 + len_defaults)
-    w_item = w_dict.getitem(w_key)
-    if w_item is None:
-        if len_defaults > 0:
-            return defaults_w[0]
-        else:
-            space.raise_key_error(w_key)
-    else:
-        w_dict.delitem(w_key)
-        return w_item
-
-def dict_popitem__DictMulti(space, w_dict):
-    try:
-        w_key, w_value = w_dict.popitem()
-    except KeyError:
-        raise OperationError(space.w_KeyError,
-                             space.wrap("popitem(): dictionary is empty"))
-    return space.newtuple([w_key, w_value])
-
 
 # ____________________________________________________________
 # Iteration
 
-
-class W_BaseDictMultiIterObject(W_Object):
-    from pypy.objspace.std.dicttype import dictiter_typedef as typedef
-
+class W_BaseDictMultiIterObject(W_Root):
     _immutable_fields_ = ["iteratorimplementation"]
 
     ignore_for_isinstance_cache = True
@@ -981,139 +1139,199 @@
         w_self.space = space
         w_self.iteratorimplementation = iteratorimplementation
 
+    def descr_iter(self, space):
+        return self
+
+    def descr_length_hint(self, space):
+        return space.wrap(self.iteratorimplementation.length())
+
+    def descr_reduce(self, space):
+        """
+        This is a slightly special case of pickling.
+        Since iteration over a dict is a bit hairy,
+        we do the following:
+        - create a clone of the dict iterator
+        - run it to the original position
+        - collect all remaining elements into a list
+        At unpickling time, we just use that list
+        and create an iterator on it.
+        This is of course not the standard way.
+
+        XXX to do: remove this __reduce__ method and do
+        a registration with copy_reg, instead.
+        """
+        w_mod    = space.getbuiltinmodule('_pickle_support')
+        mod      = space.interp_w(MixedModule, w_mod)
+        new_inst = mod.get('dictiter_surrogate_new')
+        w_typeobj = space.gettypeobject(W_BaseDictMultiIterObject.typedef)
+
+        raise OperationError(
+            space.w_TypeError,
+            space.wrap("can't pickle dictionary-keyiterator objects"))
+        # XXXXXX get that working again
+
+        # we cannot call __init__ since we don't have the original dict
+        if isinstance(self, W_DictIter_Keys):
+            w_clone = space.allocate_instance(W_DictIter_Keys, w_typeobj)
+        elif isinstance(self, W_DictIter_Values):
+            w_clone = space.allocate_instance(W_DictIter_Values, w_typeobj)
+        elif isinstance(self, W_DictIter_Items):
+            w_clone = space.allocate_instance(W_DictIter_Items, w_typeobj)
+        else:
+            msg = "unsupported dictiter type '%s' during pickling" % (self,)
+            raise OperationError(space.w_TypeError, space.wrap(msg))
+        w_clone.space = space
+        w_clone.content = self.content
+        w_clone.len = self.len
+        w_clone.pos = 0
+        w_clone.setup_iterator()
+        # spool until we have the same pos
+        while w_clone.pos < self.pos:
+            w_obj = w_clone.next_entry()
+            w_clone.pos += 1
+        stuff = [w_clone.next_entry() for i in range(w_clone.pos, w_clone.len)]
+        w_res = space.newlist(stuff)
+        tup      = [
+            w_res
+        ]
+        w_ret = space.newtuple([new_inst, space.newtuple(tup)])
+        return w_ret
+
+
 class W_DictMultiIterKeysObject(W_BaseDictMultiIterObject):
-    pass
+    def descr_next(self, space):
+        iteratorimplementation = self.iteratorimplementation
+        w_key = iteratorimplementation.next_key()
+        if w_key is not None:
+            return w_key
+        raise OperationError(space.w_StopIteration, space.w_None)
 
 class W_DictMultiIterValuesObject(W_BaseDictMultiIterObject):
-    pass
+    def descr_next(self, space):
+        iteratorimplementation = self.iteratorimplementation
+        w_value = iteratorimplementation.next_value()
+        if w_value is not None:
+            return w_value
+        raise OperationError(space.w_StopIteration, space.w_None)
 
 class W_DictMultiIterItemsObject(W_BaseDictMultiIterObject):
-    pass
+    def descr_next(self, space):
+        iteratorimplementation = self.iteratorimplementation
+        w_key, w_value = iteratorimplementation.next_item()
+        if w_key is not None:
+            return space.newtuple([w_key, w_value])
+        raise OperationError(space.w_StopIteration, space.w_None)
 
-registerimplementation(W_DictMultiIterKeysObject)
-registerimplementation(W_DictMultiIterValuesObject)
-registerimplementation(W_DictMultiIterItemsObject)
+W_DictMultiIterItemsObject.typedef = StdTypeDef(
+    "dict_iteritems",
+    __iter__ = gateway.interp2app(W_DictMultiIterItemsObject.descr_iter),
+    next = gateway.interp2app(W_DictMultiIterItemsObject.descr_next),
+    __length_hint__ = gateway.interp2app(W_BaseDictMultiIterObject.descr_length_hint)
+    )
 
-def iter__DictMultiIterKeysObject(space, w_dictiter):
-    return w_dictiter
+W_DictMultiIterKeysObject.typedef = StdTypeDef(
+    "dict_iterkeys",
+    __iter__ = gateway.interp2app(W_DictMultiIterKeysObject.descr_iter),
+    next = gateway.interp2app(W_DictMultiIterKeysObject.descr_next),
+    __length_hint__ = gateway.interp2app(W_BaseDictMultiIterObject.descr_length_hint)
+    )
 
-def next__DictMultiIterKeysObject(space, w_dictiter):
-    iteratorimplementation = w_dictiter.iteratorimplementation
-    w_key = iteratorimplementation.next_key()
-    if w_key is not None:
-        return w_key
-    raise OperationError(space.w_StopIteration, space.w_None)
+W_DictMultiIterValuesObject.typedef = StdTypeDef(
+    "dict_itervalues",
+    __iter__ = gateway.interp2app(W_DictMultiIterValuesObject.descr_iter),
+    next = gateway.interp2app(W_DictMultiIterValuesObject.descr_next),
+    __length_hint__ = gateway.interp2app(W_BaseDictMultiIterObject.descr_length_hint)
+    )
 
-def iter__DictMultiIterValuesObject(space, w_dictiter):
-    return w_dictiter
-
-def next__DictMultiIterValuesObject(space, w_dictiter):
-    iteratorimplementation = w_dictiter.iteratorimplementation
-    w_value = iteratorimplementation.next_value()
-    if w_value is not None:
-        return w_value
-    raise OperationError(space.w_StopIteration, space.w_None)
-
-def iter__DictMultiIterItemsObject(space, w_dictiter):
-    return w_dictiter
-
-def next__DictMultiIterItemsObject(space, w_dictiter):
-    iteratorimplementation = w_dictiter.iteratorimplementation
-    w_key, w_value = iteratorimplementation.next_item()
-    if w_key is not None:
-        return space.newtuple([w_key, w_value])
-    raise OperationError(space.w_StopIteration, space.w_None)
 
 # ____________________________________________________________
 # Views
 
-class W_DictViewObject(W_Object):
+class W_DictViewObject(W_Root):
     def __init__(w_self, space, w_dict):
         w_self.w_dict = w_dict
 
-class W_DictViewKeysObject(W_DictViewObject):
-    from pypy.objspace.std.dicttype import dict_keys_typedef as typedef
-registerimplementation(W_DictViewKeysObject)
+    def descr_repr(self, space):
+        w_seq = space.call_function(space.w_list, self)
+        w_repr = space.repr(w_seq)
+        return space.wrap("%s(%s)" % (space.type(self).getname(space),
+                                      space.str_w(w_repr)))
+
+    def descr_eq(self, space, w_otherview):
+        if not space.eq_w(space.len(self), space.len(w_otherview)):
+            return space.w_False
+
+        w_iter = space.iter(self)
+        while True:
+            try:
+                w_item = space.next(w_iter)
+            except OperationError, e:
+                if not e.match(space, space.w_StopIteration):
+                    raise
+                break
+            if not space.is_true(space.contains(w_otherview, w_item)):
+                return space.w_False
+        return space.w_True
+
+    def descr_len(self, space):
+        return space.len(self.w_dict)
+
+    def descr_and(self, space, w_otherview):
+        w_set = space.call_function(space.w_set, self)
+        space.call_method(w_set, "intersection_update", w_otherview)
+        return w_set
+
+    def descr_or(self, space, w_otherview):
+        w_set = space.call_function(space.w_set, self)
+        space.call_method(w_set, "update", w_otherview)
+        return w_set
+
+    def descr_xor(self, space, w_otherview):
+        w_set = space.call_function(space.w_set, self)
+        space.call_method(w_set, "symmetric_difference_update", w_otherview)
+        return w_set
 
 class W_DictViewItemsObject(W_DictViewObject):
-    from pypy.objspace.std.dicttype import dict_items_typedef as typedef
-registerimplementation(W_DictViewItemsObject)
+    def descr_iter(self, space):
+        return W_DictMultiIterItemsObject(space, self.w_dict.iteritems())
+
+class W_DictViewKeysObject(W_DictViewObject):
+    def descr_iter(self, space):
+        return W_DictMultiIterKeysObject(space, self.w_dict.iterkeys())
 
 class W_DictViewValuesObject(W_DictViewObject):
-    from pypy.objspace.std.dicttype import dict_values_typedef as typedef
-registerimplementation(W_DictViewValuesObject)
+    def descr_iter(self, space):
+        return W_DictMultiIterValuesObject(space, self.w_dict.itervalues())
 
-def len__DictViewKeys(space, w_dictview):
-    return space.len(w_dictview.w_dict)
-len__DictViewItems = len__DictViewValues = len__DictViewKeys
+W_DictViewItemsObject.typedef = StdTypeDef(
+    "dict_items",
+    __repr__ = gateway.interp2app(W_DictViewItemsObject.descr_repr),
+    __eq__ = gateway.interp2app(W_DictViewItemsObject.descr_eq),
+    __len__ = gateway.interp2app(W_DictViewItemsObject.descr_len),
+    __iter__ = gateway.interp2app(W_DictViewItemsObject.descr_iter),
+    __and__ = gateway.interp2app(W_DictViewItemsObject.descr_and),
+    __or__ = gateway.interp2app(W_DictViewItemsObject.descr_or),
+    __xor__ = gateway.interp2app(W_DictViewItemsObject.descr_xor)
+    )
 
-def iter__DictViewKeys(space, w_dictview):
-    return dict_iterkeys__DictMulti(space, w_dictview.w_dict)
-def iter__DictViewItems(space, w_dictview):
-    return dict_iteritems__DictMulti(space, w_dictview.w_dict)
-def iter__DictViewValues(space, w_dictview):
-    return dict_itervalues__DictMulti(space, w_dictview.w_dict)
+W_DictViewKeysObject.typedef = StdTypeDef(
+    "dict_keys",
+    __repr__ = gateway.interp2app(W_DictViewKeysObject.descr_repr),
+    __eq__ = gateway.interp2app(W_DictViewKeysObject.descr_eq),
+    __len__ = gateway.interp2app(W_DictViewKeysObject.descr_len),
+    __iter__ = gateway.interp2app(W_DictViewKeysObject.descr_iter),
+    __and__ = gateway.interp2app(W_DictViewKeysObject.descr_and),
+    __or__ = gateway.interp2app(W_DictViewKeysObject.descr_or),
+    __xor__ = gateway.interp2app(W_DictViewKeysObject.descr_xor)
+    )
 
-def all_contained_in(space, w_dictview, w_otherview):
-    w_iter = space.iter(w_dictview)
-
-    while True:
-        try:
-            w_item = space.next(w_iter)
-        except OperationError, e:
-            if not e.match(space, space.w_StopIteration):
-                raise
-            break
-        if not space.is_true(space.contains(w_otherview, w_item)):
-            return space.w_False
-
-    return space.w_True
-
-def eq__DictViewKeys_DictViewKeys(space, w_dictview, w_otherview):
-    if space.eq_w(space.len(w_dictview), space.len(w_otherview)):
-        return all_contained_in(space, w_dictview, w_otherview)
-    return space.w_False
-eq__DictViewKeys_settypedef = eq__DictViewKeys_DictViewKeys
-eq__DictViewKeys_frozensettypedef = eq__DictViewKeys_DictViewKeys
-
-eq__DictViewKeys_DictViewItems = eq__DictViewKeys_DictViewKeys
-eq__DictViewItems_DictViewItems = eq__DictViewKeys_DictViewKeys
-eq__DictViewItems_settypedef = eq__DictViewItems_DictViewItems
-eq__DictViewItems_frozensettypedef = eq__DictViewItems_DictViewItems
-
-def repr__DictViewKeys(space, w_dictview):
-    w_seq = space.call_function(space.w_list, w_dictview)
-    w_repr = space.repr(w_seq)
-    return space.wrap("%s(%s)" % (space.type(w_dictview).getname(space),
-                                  space.str_w(w_repr)))
-repr__DictViewItems  = repr__DictViewKeys
-repr__DictViewValues = repr__DictViewKeys
-
-def and__DictViewKeys_DictViewKeys(space, w_dictview, w_otherview):
-    w_set = space.call_function(space.w_set, w_dictview)
-    space.call_method(w_set, "intersection_update", w_otherview)
-    return w_set
-and__DictViewKeys_settypedef = and__DictViewKeys_DictViewKeys
-and__DictViewItems_DictViewItems = and__DictViewKeys_DictViewKeys
-and__DictViewItems_settypedef = and__DictViewKeys_DictViewKeys
-
-def or__DictViewKeys_DictViewKeys(space, w_dictview, w_otherview):
-    w_set = space.call_function(space.w_set, w_dictview)
-    space.call_method(w_set, "update", w_otherview)
-    return w_set
-or__DictViewKeys_settypedef = or__DictViewKeys_DictViewKeys
-or__DictViewItems_DictViewItems = or__DictViewKeys_DictViewKeys
-or__DictViewItems_settypedef = or__DictViewKeys_DictViewKeys
-
-def xor__DictViewKeys_DictViewKeys(space, w_dictview, w_otherview):
-    w_set = space.call_function(space.w_set, w_dictview)
-    space.call_method(w_set, "symmetric_difference_update", w_otherview)
-    return w_set
-xor__DictViewKeys_settypedef = xor__DictViewKeys_DictViewKeys
-xor__DictViewItems_DictViewItems = xor__DictViewKeys_DictViewKeys
-xor__DictViewItems_settypedef = xor__DictViewKeys_DictViewKeys
-
-# ____________________________________________________________
-
-from pypy.objspace.std import dicttype
-register_all(vars(), dicttype)
+W_DictViewValuesObject.typedef = StdTypeDef(
+    "dict_values",
+    __repr__ = gateway.interp2app(W_DictViewValuesObject.descr_repr),
+    __eq__ = gateway.interp2app(W_DictViewValuesObject.descr_eq),
+    __len__ = gateway.interp2app(W_DictViewValuesObject.descr_len),
+    __iter__ = gateway.interp2app(W_DictViewValuesObject.descr_iter),
+    __and__ = gateway.interp2app(W_DictViewValuesObject.descr_and),
+    __or__ = gateway.interp2app(W_DictViewValuesObject.descr_or),
+    __xor__ = gateway.interp2app(W_DictViewValuesObject.descr_xor)
+    )
diff --git a/pypy/objspace/std/dicttype.py b/pypy/objspace/std/dicttype.py
deleted file mode 100644
--- a/pypy/objspace/std/dicttype.py
+++ /dev/null
@@ -1,221 +0,0 @@
-from pypy.interpreter.error import OperationError
-from pypy.interpreter.mixedmodule import MixedModule
-from pypy.interpreter import gateway
-from pypy.objspace.std.stdtypedef import StdTypeDef, SMM
-from pypy.objspace.std.register_all import register_all
-
-dict_copy       = SMM('copy',          1,
-                      doc='D.copy() -> a shallow copy of D')
-dict_items      = SMM('items',         1,
-                      doc="D.items() -> list of D's (key, value) pairs, as"
-                          ' 2-tuples')
-dict_keys       = SMM('keys',          1,
-                      doc="D.keys() -> list of D's keys")
-dict_values     = SMM('values',        1,
-                      doc="D.values() -> list of D's values")
-dict_has_key    = SMM('has_key',       2,
-                      doc='D.has_key(k) -> True if D has a key k, else False')
-dict_clear      = SMM('clear',         1,
-                      doc='D.clear() -> None.  Remove all items from D.')
-dict_get        = SMM('get',           3, defaults=(None,),
-                      doc='D.get(k[,d]) -> D[k] if k in D, else d.  d defaults'
-                          ' to None.')
-dict_pop        = SMM('pop',           2, varargs_w=True,
-                      doc='D.pop(k[,d]) -> v, remove specified key and return'
-                          ' the corresponding value\nIf key is not found, d is'
-                          ' returned if given, otherwise KeyError is raised')
-dict_popitem    = SMM('popitem',       1,
-                      doc='D.popitem() -> (k, v), remove and return some (key,'
-                          ' value) pair as a\n2-tuple; but raise KeyError if D'
-                          ' is empty')
-dict_setdefault = SMM('setdefault',    3, defaults=(None,),
-                      doc='D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d'
-                          ' if k not in D')
-dict_update     = SMM('update',        1, general__args__=True,
-                      doc='D.update(E, **F) -> None.  Update D from E and F:'
-                          ' for k in E: D[k] = E[k]\n(if E has keys else: for'
-                          ' (k, v) in E: D[k] = v) then: for k in F: D[k] ='
-                          ' F[k]')
-dict_iteritems  = SMM('iteritems',     1,
-                      doc='D.iteritems() -> an iterator over the (key, value)'
-                          ' items of D')
-dict_iterkeys   = SMM('iterkeys',      1,
-                      doc='D.iterkeys() -> an iterator over the keys of D')
-dict_itervalues = SMM('itervalues',    1,
-                      doc='D.itervalues() -> an iterator over the values of D')
-dict_viewkeys   = SMM('viewkeys',      1,
-                      doc="D.viewkeys() -> a set-like object providing a view on D's keys")
-dict_viewitems  = SMM('viewitems',     1,
-                      doc="D.viewitems() -> a set-like object providing a view on D's items")
-dict_viewvalues = SMM('viewvalues',    1,
-                      doc="D.viewvalues() -> an object providing a view on D's values")
-dict_reversed   = SMM('__reversed__',      1)
-
-def dict_reversed__ANY(space, w_dict):
-    raise OperationError(space.w_TypeError, space.wrap('argument to reversed() must be a sequence'))
-
-register_all(vars(), globals())
-
-def descr_fromkeys(space, w_type, w_keys, w_fill=None):
-    from pypy.objspace.std.dictmultiobject import W_DictMultiObject
-    if w_fill is None:
-        w_fill = space.w_None
-    if space.is_w(w_type, space.w_dict):
-        w_dict = W_DictMultiObject.allocate_and_init_instance(space, w_type)
-
-        strlist = space.listview_str(w_keys)
-        if strlist is not None:
-            for key in strlist:
-                w_dict.setitem_str(key, w_fill)
-        else:
-            for w_key in space.listview(w_keys):
-                w_dict.setitem(w_key, w_fill)
-    else:
-        w_dict = space.call_function(w_type)
-        for w_key in space.listview(w_keys):
-            space.setitem(w_dict, w_key, w_fill)
-    return w_dict
-
-
-app = gateway.applevel('''
-    def dictrepr(currently_in_repr, d):
-        if len(d) == 0:
-            return "{}"
-        dict_id = id(d)
-        if dict_id in currently_in_repr:
-            return '{...}'
-        currently_in_repr[dict_id] = 1
-        try:
-            items = []
-            # XXX for now, we cannot use iteritems() at app-level because
-            #     we want a reasonable result instead of a RuntimeError
-            #     even if the dict is mutated by the repr() in the loop.
-            for k, v in dict.items(d):
-                items.append(repr(k) + ": " + repr(v))
-            return "{" +  ', '.join(items) + "}"
-        finally:
-            try:
-                del currently_in_repr[dict_id]
-            except:
-                pass
-''', filename=__file__)
-
-dictrepr = app.interphook("dictrepr")
-
-
-def descr_repr(space, w_dict):
-    ec = space.getexecutioncontext()
-    w_currently_in_repr = ec._py_repr
-    if w_currently_in_repr is None:
-        w_currently_in_repr = ec._py_repr = space.newdict()
-    return dictrepr(space, w_currently_in_repr, w_dict)
-
-
-# ____________________________________________________________
-
-def descr__new__(space, w_dicttype, __args__):
-    from pypy.objspace.std.dictmultiobject import W_DictMultiObject
-    w_obj = W_DictMultiObject.allocate_and_init_instance(space, w_dicttype)
-    return w_obj
-
-# ____________________________________________________________
-
-dict_typedef = StdTypeDef("dict",
-    __doc__ = '''dict() -> new empty dictionary.
-dict(mapping) -> new dictionary initialized from a mapping object\'s
-    (key, value) pairs.
-dict(seq) -> new dictionary initialized as if via:
-    d = {}
-    for k, v in seq:
-        d[k] = v
-dict(**kwargs) -> new dictionary initialized with the name=value pairs
-    in the keyword argument list.  For example:  dict(one=1, two=2)''',
-    __new__ = gateway.interp2app(descr__new__),
-    __hash__ = None,
-    __repr__ = gateway.interp2app(descr_repr),
-    fromkeys = gateway.interp2app(descr_fromkeys, as_classmethod=True),
-    )
-dict_typedef.registermethods(globals())
-
-# ____________________________________________________________
-
-def descr_dictiter__length_hint__(space, w_self):
-    from pypy.objspace.std.dictmultiobject import W_BaseDictMultiIterObject
-    assert isinstance(w_self, W_BaseDictMultiIterObject)
-    return space.wrap(w_self.iteratorimplementation.length())
-
-
-def descr_dictiter__reduce__(w_self, space):
-    """
-    This is a slightly special case of pickling.
-    Since iteration over a dict is a bit hairy,
-    we do the following:
-    - create a clone of the dict iterator
-    - run it to the original position
-    - collect all remaining elements into a list
-    At unpickling time, we just use that list
-    and create an iterator on it.
-    This is of course not the standard way.
-
-    XXX to do: remove this __reduce__ method and do
-    a registration with copy_reg, instead.
-    """
-    w_mod    = space.getbuiltinmodule('_pickle_support')
-    mod      = space.interp_w(MixedModule, w_mod)
-    new_inst = mod.get('dictiter_surrogate_new')
-    w_typeobj = space.gettypeobject(dictiter_typedef)
-
-    raise OperationError(
-        space.w_TypeError,
-        space.wrap("can't pickle dictionary-keyiterator objects"))
-    # XXXXXX get that working again
-
-    # we cannot call __init__ since we don't have the original dict
-    if isinstance(w_self, W_DictIter_Keys):
-        w_clone = space.allocate_instance(W_DictIter_Keys, w_typeobj)
-    elif isinstance(w_self, W_DictIter_Values):
-        w_clone = space.allocate_instance(W_DictIter_Values, w_typeobj)
-    elif isinstance(w_self, W_DictIter_Items):
-        w_clone = space.allocate_instance(W_DictIter_Items, w_typeobj)
-    else:
-        msg = "unsupported dictiter type '%s' during pickling" % (w_self, )
-        raise OperationError(space.w_TypeError, space.wrap(msg))
-    w_clone.space = space
-    w_clone.content = w_self.content
-    w_clone.len = w_self.len
-    w_clone.pos = 0
-    w_clone.setup_iterator()
-    # spool until we have the same pos
-    while w_clone.pos < w_self.pos:
-        w_obj = w_clone.next_entry()
-        w_clone.pos += 1
-    stuff = [w_clone.next_entry() for i in range(w_clone.pos, w_clone.len)]
-    w_res = space.newlist(stuff)
-    tup      = [
-        w_res
-    ]
-    w_ret = space.newtuple([new_inst, space.newtuple(tup)])
-    return w_ret
-
-# ____________________________________________________________
-
-
-dictiter_typedef = StdTypeDef("dictionaryiterator",
-    __length_hint__ = gateway.interp2app(descr_dictiter__length_hint__),
-    __reduce__      = gateway.interp2app(descr_dictiter__reduce__),
-    )
-
-# ____________________________________________________________
-# Dict views
-
-dict_keys_typedef = StdTypeDef(
-    "dict_keys",
-    )
-
-dict_items_typedef = StdTypeDef(
-    "dict_items",
-    )
-
-dict_values_typedef = StdTypeDef(
-    "dict_values",
-    )
diff --git a/pypy/objspace/std/marshal_impl.py b/pypy/objspace/std/marshal_impl.py
--- a/pypy/objspace/std/marshal_impl.py
+++ b/pypy/objspace/std/marshal_impl.py
@@ -12,6 +12,7 @@
 from pypy.objspace.std.register_all import register_all
 from rpython.rlib.rarithmetic import LONG_BIT, r_longlong, r_uint, intmask
 from pypy.objspace.std import model
+from pypy.objspace.std.dictmultiobject import W_DictMultiObject
 from pypy.interpreter.special import Ellipsis
 from pypy.interpreter.pycode import PyCode
 from pypy.interpreter import gateway, unicodehelper
@@ -24,7 +25,6 @@
 from pypy.objspace.std.floatobject   import W_FloatObject
 from pypy.objspace.std.tupleobject   import W_TupleObject
 from pypy.objspace.std.listobject    import W_ListObject
-from pypy.objspace.std.dictmultiobject    import W_DictMultiObject
 from pypy.objspace.std.stringobject  import W_StringObject
 from pypy.objspace.std.typeobject    import W_TypeObject
 from pypy.objspace.std.longobject    import W_LongObject, newlong
@@ -309,15 +309,18 @@
     return space.newlist(items_w)
 register(TYPE_LIST, unmarshal_List)
 
-def marshal_w__DictMulti(space, w_dict, m):
+def marshal_w_dict(space, w_dict, m):
+    if not isinstance(w_dict, W_DictMultiObject):
+        raise_exception(space, "unmarshallable object")
     m.start(TYPE_DICT)
     for w_tuple in w_dict.items():
         w_key, w_value = space.fixedview(w_tuple, 2)
         m.put_w_obj(w_key)
         m.put_w_obj(w_value)
     m.atom(TYPE_NULL)
+handled_by_any.append(('dict', marshal_w_dict))
 
-def unmarshal_DictMulti(space, u, tc):
+def unmarshal_dict(space, u, tc):
     # since primitive lists are not optimized and we don't know
     # the dict size in advance, use the dict's setitem instead
     # of building a list of tuples.
@@ -329,7 +332,7 @@
         w_value = u.get_w_obj()
         space.setitem(w_dic, w_key, w_value)
     return w_dic
-register(TYPE_DICT, unmarshal_DictMulti)
+register(TYPE_DICT, unmarshal_dict)
 
 def unmarshal_NULL(self, u, tc):
     return None
diff --git a/pypy/objspace/std/model.py b/pypy/objspace/std/model.py
--- a/pypy/objspace/std/model.py
+++ b/pypy/objspace/std/model.py
@@ -40,7 +40,6 @@
             from pypy.objspace.std.complextype  import complex_typedef
             from pypy.objspace.std.tupletype  import tuple_typedef
             from pypy.objspace.std.listobject   import list_typedef
-            from pypy.objspace.std.dicttype   import dict_typedef
             from pypy.objspace.std.basestringtype import basestring_typedef
             from pypy.objspace.std.stringtype import str_typedef
             from pypy.objspace.std.bytearraytype import bytearray_typedef
@@ -81,6 +80,7 @@
 
         # not-multimethod based types
 
+        self.pythontypes.append(dictmultiobject.W_DictMultiObject.typedef)
         self.pythontypes.append(setobject.W_SetObject.typedef)
         self.pythontypes.append(setobject.W_FrozensetObject.typedef)
 
@@ -92,10 +92,6 @@
             floatobject.W_FloatObject: [],
             tupleobject.W_TupleObject: [],
             listobject.W_ListObject: [],
-            dictmultiobject.W_DictMultiObject: [],
-            dictmultiobject.W_DictMultiIterKeysObject: [],
-            dictmultiobject.W_DictMultiIterValuesObject: [],
-            dictmultiobject.W_DictMultiIterItemsObject: [],
             stringobject.W_StringObject: [],
             bytearrayobject.W_BytearrayObject: [],
             typeobject.W_TypeObject: [],
@@ -108,9 +104,6 @@
             iterobject.W_FastTupleIterObject: [],
             iterobject.W_ReverseSeqIterObject: [],
             unicodeobject.W_UnicodeObject: [],
-            dictmultiobject.W_DictViewKeysObject: [],
-            dictmultiobject.W_DictViewItemsObject: [],
-            dictmultiobject.W_DictViewValuesObject: [],
             pypy.interpreter.pycode.PyCode: [],
             pypy.interpreter.special.Ellipsis: [],
             }
@@ -333,9 +326,6 @@
             s += ' instance of %s' % self.w__class__
         return '<%s>' % s
 
-    def unwrap(self, space):
-        raise UnwrapError('cannot unwrap %r' % self)
-
 
 class UnwrapError(Exception):
     pass
diff --git a/pypy/objspace/std/objspace.py b/pypy/objspace/std/objspace.py
--- a/pypy/objspace/std/objspace.py
+++ b/pypy/objspace/std/objspace.py
@@ -253,10 +253,9 @@
 
     def unwrap(self, w_obj):
         """NOT_RPYTHON"""
-        if isinstance(w_obj, model.W_Object):
+        # _____ this code is here to support testing only _____
+        if isinstance(w_obj, W_Root):
             return w_obj.unwrap(self)
-        if isinstance(w_obj, W_Root):
-            return w_obj
         raise model.UnwrapError("cannot unwrap: %r" % w_obj)
 
     def newint(self, intval):
diff --git a/pypy/objspace/std/test/test_dictmultiobject.py b/pypy/objspace/std/test/test_dictmultiobject.py
--- a/pypy/objspace/std/test/test_dictmultiobject.py
+++ b/pypy/objspace/std/test/test_dictmultiobject.py
@@ -2,8 +2,7 @@
 import py
 
 from pypy.objspace.std.dictmultiobject import (W_DictMultiObject,
-    setitem__DictMulti_ANY_ANY, getitem__DictMulti_ANY, StringDictStrategy,
-    ObjectDictStrategy)
+    StringDictStrategy, ObjectDictStrategy)
 
 
 class TestW_DictObject(object):
@@ -409,6 +408,24 @@
         assert {'a': 1 } < { 'b': 1}
         assert {'a': 1, 'x': 2 } < { 'b': 1, 'x': 2}
 
+    def test_other_rich_cmp(self):
+        d1 = {1: 2, 3: 4}
+        d2 = {1: 2, 3: 4}
+        d3 = {1: 2, 3: 5}
+        d4 = {1: 2}
+
+        assert d1 <= d2
+        assert d1 <= d3
+        assert not d1 <= d4
+
+        assert not d1 > d2
+        assert not d1 > d3
+        assert d1 > d4
+
+        assert d1 >= d2
+        assert not d1 >= d3
+        assert d1 >= d4
+
     def test_str_repr(self):
         assert '{}' == str({})
         assert '{1: 2}' == str({1: 2})
@@ -604,6 +621,9 @@
         assert d.values() == []
         assert d.keys() == []
 
+    def test_cmp_with_noncmp(self):
+        assert not {} > object()
+
 class AppTest_DictMultiObject(AppTest_DictObject):
 
     def test_emptydict_unhashable(self):
@@ -971,10 +991,10 @@
         pydict = {}
         for i in range(N):
             x = randint(-N, N)
-            setitem__DictMulti_ANY_ANY(self.space, d, x, i)
+            d.descr_setitem(self.space, x, i)
             pydict[x] = i
         for key, value in pydict.iteritems():
-            assert value == getitem__DictMulti_ANY(self.space, d, key)
+            assert value == d.descr_getitem(self.space, key)
 
 class BaseTestRDictImplementation:
 
diff --git a/rpython/memory/gctransform/asmgcroot.py b/rpython/memory/gctransform/asmgcroot.py
--- a/rpython/memory/gctransform/asmgcroot.py
+++ b/rpython/memory/gctransform/asmgcroot.py
@@ -331,6 +331,11 @@
                                            [annmodel.SomeInteger(),
                                             annmodel.SomeAddress()],
                                            annmodel.s_None)
+        #
+        # check that the order of the need_*() is correct for us: if we
+        # need both threads and stacklets, need_thread_support() must be
+        # called first, to initialize self.belongs_to_current_thread.
+        assert not hasattr(self, 'gc_detach_callback_pieces_ptr')
 
     def walk_stack_roots(self, collect_stack_root):
         gcdata = self.gcdata
diff --git a/rpython/memory/gctransform/framework.py b/rpython/memory/gctransform/framework.py
--- a/rpython/memory/gctransform/framework.py
+++ b/rpython/memory/gctransform/framework.py
@@ -236,9 +236,10 @@
         # thread support
         if translator.config.translation.continuation:
             root_walker.stacklet_support = True
-            root_walker.need_stacklet_support(self, getfn)
         if translator.config.translation.thread:
             root_walker.need_thread_support(self, getfn)
+        if root_walker.stacklet_support:
+            root_walker.need_stacklet_support(self, getfn)
 
         self.layoutbuilder.encode_type_shapes_now()
 
diff --git a/rpython/rlib/entrypoint.py b/rpython/rlib/entrypoint.py
--- a/rpython/rlib/entrypoint.py
+++ b/rpython/rlib/entrypoint.py
@@ -57,7 +57,8 @@
 # This thing is imported by any target which has any API, so it'll get
 # registered
 
-RPython_StartupCode = rffi.llexternal('RPython_StartupCode', [], lltype.Void)
+RPython_StartupCode = rffi.llexternal('RPython_StartupCode', [], lltype.Void,
+                                      _nowrapper=True)
 
 @entrypoint('main', [], c_name='rpython_startup_code')
 def rpython_startup_code():
diff --git a/rpython/rtyper/rpbc.py b/rpython/rtyper/rpbc.py
--- a/rpython/rtyper/rpbc.py
+++ b/rpython/rtyper/rpbc.py
@@ -529,7 +529,7 @@
 
         im_selves = []
         for desc in s_pbc.descriptions:
-            assert desc.funcdesc is self.funcdesc
+            assert desc.funcdesc is self.funcdesc, "You can't mix a set of methods on a frozen PBC in RPython that are different underlaying functions"
             im_selves.append(desc.frozendesc)
 
         self.s_im_self = annmodel.SomePBC(im_selves)


More information about the pypy-commit mailing list