[pypy-commit] pypy default: merge heads

bivab noreply at buildbot.pypy.org
Sun May 19 11:11:47 CEST 2013


Author: David Schneider <david.schneider at picle.org>
Branch: 
Changeset: r64308:2708b1ed0639
Date: 2013-05-19 11:10 +0200
http://bitbucket.org/pypy/pypy/changeset/2708b1ed0639/

Log:	merge heads

diff too long, truncating to 2000 out of 2290 lines

diff --git a/pypy/doc/coding-guide.rst b/pypy/doc/coding-guide.rst
--- a/pypy/doc/coding-guide.rst
+++ b/pypy/doc/coding-guide.rst
@@ -339,8 +339,9 @@
 
 + methods and other class attributes do not change after startup
 + single inheritance is fully supported
-+ simple mixins work too, but the mixed in class needs a ``_mixin_ = True``
-  class attribute
++ simple mixins somewhat work too, but the mixed in class needs a
+  ``_mixin_ = True`` class attribute. isinstance checks against the
+  mixin type will fail when translated.
 
 + classes are first-class objects too
 
diff --git a/pypy/doc/how-to-contribute.rst b/pypy/doc/how-to-contribute.rst
--- a/pypy/doc/how-to-contribute.rst
+++ b/pypy/doc/how-to-contribute.rst
@@ -28,7 +28,8 @@
 Layers
 ------
 
-PyPy has layers. Those layers help us keep the respective parts separated enough
+PyPy has layers. Just like Ogres or onions.
+Those layers help us keep the respective parts separated enough
 to be worked on independently and make the complexity manageable. This is,
 again, just a sanity requirement for such a complex project. For example writing
 a new optimization for the JIT usually does **not** involve touching a Python
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
@@ -19,3 +19,6 @@
 
 .. branch: numpy-subarrays
 Implement subarrays for numpy
+
+.. branch: remove-dict-smm
+Remove multi-methods on dict
diff --git a/pypy/goal/targetpypystandalone.py b/pypy/goal/targetpypystandalone.py
--- a/pypy/goal/targetpypystandalone.py
+++ b/pypy/goal/targetpypystandalone.py
@@ -10,6 +10,8 @@
 from rpython.config.config import ConflictConfigError
 from pypy.tool.option import make_objspace
 from pypy.conftest import pypydir
+from rpython.rlib import rthread
+from pypy.module.thread import os_thread
 
 thisdir = py.path.local(__file__).dirpath()
 
@@ -120,6 +122,15 @@
         source = rffi.charp2str(ll_source)
         return _pypy_execute_source(source)
 
+    @entrypoint('main', [], c_name='pypy_init_threads')
+    def pypy_init_threads():
+        os_thread.setup_threads(space)
+        rffi.aroundstate.before()
+
+    @entrypoint('main', [], c_name='pypy_thread_attach')
+    def pypy_thread_attach():
+        rthread.gc_thread_start()
+
     w_globals = space.newdict()
     space.setitem(w_globals, space.wrap('__builtins__'),
                   space.builtin_modules['__builtin__'])
@@ -137,6 +148,8 @@
         return 0
 
     return entry_point, {'pypy_execute_source': pypy_execute_source,
+                         'pypy_init_threads': pypy_init_threads,
+                         'pypy_thread_attach': pypy_thread_attach,
                          'pypy_setup_home': pypy_setup_home}
 
 def call_finish(space):
diff --git a/pypy/interpreter/astcompiler/codegen.py b/pypy/interpreter/astcompiler/codegen.py
--- a/pypy/interpreter/astcompiler/codegen.py
+++ b/pypy/interpreter/astcompiler/codegen.py
@@ -853,9 +853,10 @@
             self.emit_jump(ops.JUMP_IF_FALSE_OR_POP, cleanup, True)
             if i < (ops_count - 1):
                 comp.comparators[i].walkabout(self)
-        comp.comparators[-1].walkabout(self)
-        last_kind = compare_operations(comp.ops[-1])
-        self.emit_op_arg(ops.COMPARE_OP, last_kind)
+        last_op, last_comparator = comp.ops[-1], comp.comparators[-1]
+        if not self._optimize_comparator(last_op, last_comparator):
+            last_comparator.walkabout(self)
+        self.emit_op_arg(ops.COMPARE_OP, compare_operations(last_op))
         if ops_count > 1:
             end = self.new_block()
             self.emit_jump(ops.JUMP_FORWARD, end)
@@ -864,6 +865,37 @@
             self.emit_op(ops.POP_TOP)
             self.use_next_block(end)
 
+    def _optimize_comparator(self, op, node):
+        """Fold lists/sets of constants in the context of "in"/"not in".
+
+        lists are folded into tuples, sets into frozensets, otherwise
+        returns False
+        """
+        if op in (ast.In, ast.NotIn):
+            is_list = isinstance(node, ast.List)
+            if is_list or isinstance(node, ast.Set):
+                w_const = self._tuple_of_consts(node.elts)
+                if w_const is not None:
+                    if not is_list:
+                        from pypy.objspace.std.setobject import (
+                            W_FrozensetObject)
+                        w_const = W_FrozensetObject(self.space, w_const)
+                    self.load_const(w_const)
+                    return True
+        return False
+
+    def _tuple_of_consts(self, elts):
+        """Return a tuple of consts from elts if possible, or None"""
+        count = len(elts) if elts is not None else 0
+        consts_w = [None] * count
+        for i in range(count):
+            w_value = elts[i].as_constant()
+            if w_value is None:
+                # Not all constants
+                return None
+            consts_w[i] = w_value
+        return self.space.newtuple(consts_w)
+
     def visit_IfExp(self, ifexp):
         self.update_position(ifexp.lineno)
         end = self.new_block()
diff --git a/pypy/interpreter/astcompiler/test/test_compiler.py b/pypy/interpreter/astcompiler/test/test_compiler.py
--- a/pypy/interpreter/astcompiler/test/test_compiler.py
+++ b/pypy/interpreter/astcompiler/test/test_compiler.py
@@ -973,3 +973,30 @@
         counts = self.count_instructions(source3)
         assert counts[ops.BUILD_LIST] == 1
         assert ops.BUILD_LIST_FROM_ARG not in counts
+
+    def test_folding_of_list_constants(self):
+        for source in (
+            # in/not in constants with BUILD_LIST should be folded to a tuple:
+            'a in [1,2,3]',
+            'a not in ["a","b","c"]',
+            'a in [None, 1, None]',
+            'a not in [(1, 2), 3, 4]',
+            ):
+            source = 'def f(): %s' % source
+            counts = self.count_instructions(source)
+            assert ops.BUILD_LIST not in counts
+            assert ops.LOAD_CONST in counts
+
+    def test_folding_of_set_constants(self):
+        for source in (
+            # in/not in constants with BUILD_SET should be folded to a frozenset:
+            'a in {1,2,3}',
+            'a not in {"a","b","c"}',
+            'a in {None, 1, None}',
+            'a not in {(1, 2), 3, 4}',
+            'a in {1, 2, 3, 3, 2, 1}',
+            ):
+            source = 'def f(): %s' % source
+            counts = self.count_instructions(source)
+            assert ops.BUILD_SET not in counts
+            assert ops.LOAD_CONST in counts
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_compiler.py b/pypy/interpreter/test/test_compiler.py
--- a/pypy/interpreter/test/test_compiler.py
+++ b/pypy/interpreter/test/test_compiler.py
@@ -936,6 +936,21 @@
         output = s.getvalue()
         assert "LOAD_GLOBAL" not in output
 
+    def test_folding_of_list_constants(self):
+        source = 'a in [1, 2, 3]'
+        co = compile(source, '', 'exec')
+        i = co.co_consts.index((1, 2, 3))
+        assert i > -1
+        assert isinstance(co.co_consts[i], tuple)
+
+    def test_folding_of_set_constants(self):
+        source = 'a in {1, 2, 3}'
+        co = compile(source, '', 'exec')
+        i = co.co_consts.index(set([1, 2, 3]))
+        assert i > -1
+        assert isinstance(co.co_consts[i], frozenset)
+
+
 class AppTestCallMethod(object):
     spaceconfig = {'objspace.opcodes.CALL_METHOD': 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,24 +1,25 @@
-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.baseobjspace import W_Root
 from pypy.interpreter.error import OperationError, operationerrfmt
+from pypy.interpreter.gateway import (
+    WrappedDefault, applevel, interp2app, unwrap_spec)
+from pypy.interpreter.mixedmodule import MixedModule
 from pypy.interpreter.signature import Signature
+from pypy.objspace.std.stdtypedef import StdTypeDef
 
-from rpython.rlib.objectmodel import r_dict, specialize, newlist_hint
+from rpython.rlib import jit, rerased
 from rpython.rlib.debug import mark_dict_non_null
-from rpython.tool.sourcetools import func_with_new_name
+from rpython.rlib.objectmodel import newlist_hint, r_dict, specialize
+from rpython.tool.sourcetools import func_renamer, 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)
 
 def _never_equal_to_string(space, w_lookup_type):
-    """ Handles the case of a non string key lookup.
+    """Handles the case of a non string key lookup.
     Types that have a sane hash/eq function should allow us to return True
     directly to signal that the key is not in the dict in any case.
     XXX The types should provide such a flag. """
@@ -32,7 +33,7 @@
 
 @specialize.call_location()
 def w_dict_unrolling_heuristic(w_dct):
-    """ In which cases iterating over dict items can be unrolled.
+    """In which cases iterating over dict items can be unrolled.
     Note that w_dct is an instance of W_DictMultiObject, not necesarilly
     an actual dict
     """
@@ -40,13 +41,24 @@
                                     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):
-
+                                   instance=False, strdict=False,
+                                   kwargs=False):
         if space.config.objspace.std.withcelldict and module:
             from pypy.objspace.std.celldict import ModuleDictStrategy
             assert w_type is None
@@ -56,11 +68,9 @@
         elif space.config.objspace.std.withmapdict and instance:
             from pypy.objspace.std.mapdict import MapDictStrategy
             strategy = space.fromcache(MapDictStrategy)
-
         elif instance or strdict or module:
             assert w_type is None
             strategy = space.fromcache(StringDictStrategy)
-
         elif kwargs:
             assert w_type is None
             from pypy.objspace.std.kwargsdict import EmptyKwargsDictStrategy
@@ -81,7 +91,7 @@
         self.dstorage = storage
 
     def __repr__(w_self):
-        """ representation for debugging purposes """
+        """representation for debugging purposes"""
         return "%s(%s)" % (w_self.__class__.__name__, w_self.strategy)
 
     def unwrap(w_dict, space):
@@ -94,12 +104,10 @@
 
     def missing_method(w_dict, space, w_key):
         if not space.is_w(space.type(w_dict), space.w_dict):
-            w_missing = space.lookup(w_dict, "__missing__")
-            if w_missing is None:
-                return None
-            return space.get_and_call_function(w_missing, w_dict, w_key)
-        else:
-            return None
+            w_missing = space.lookup(w_dict, '__missing__')
+            if w_missing is not None:
+                return space.get_and_call_function(w_missing, w_dict, w_key)
+        return None
 
     def initialize_content(w_self, list_pairs_w):
         for w_k, w_v in list_pairs_w:
@@ -108,6 +116,228 @@
     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 True:
+            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()
+
+    @unwrap_spec(w_default=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)
+        return w_value if w_value is not None else w_default
+
+    @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])
+
+    @unwrap_spec(w_default=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 +358,87 @@
 
 _add_indirections()
 
+
+app = 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__ = interp2app(W_DictMultiObject.descr_new),
+    fromkeys = interp2app(W_DictMultiObject.descr_fromkeys,
+                          as_classmethod=True),
+    __hash__ = None,
+    __repr__ = interp2app(W_DictMultiObject.descr_repr),
+    __init__ = interp2app(W_DictMultiObject.descr_init),
+
+    __eq__ = interp2app(W_DictMultiObject.descr_eq),
+    __ne__ = interp2app(W_DictMultiObject.descr_ne),
+    __lt__ = interp2app(W_DictMultiObject.descr_lt),
+    __le__ = interp2app(W_DictMultiObject.descr_le),
+    __gt__ = interp2app(W_DictMultiObject.descr_gt),
+    __ge__ = interp2app(W_DictMultiObject.descr_ge),
+
+    __len__ = interp2app(W_DictMultiObject.descr_len),
+    __iter__ = interp2app(W_DictMultiObject.descr_iter),
+    __contains__ = interp2app(W_DictMultiObject.descr_contains),
+
+    __getitem__ = interp2app(W_DictMultiObject.descr_getitem),
+    __setitem__ = interp2app(W_DictMultiObject.descr_setitem),
+    __delitem__ = interp2app(W_DictMultiObject.descr_delitem),
+
+    __reversed__ = interp2app(W_DictMultiObject.descr_reversed),
+    copy = interp2app(W_DictMultiObject.descr_copy),
+    items = interp2app(W_DictMultiObject.descr_items),
+    keys = interp2app(W_DictMultiObject.descr_keys),
+    values = interp2app(W_DictMultiObject.descr_values),
+    iteritems = interp2app(W_DictMultiObject.descr_iteritems),
+    iterkeys = interp2app(W_DictMultiObject.descr_iterkeys),
+    itervalues = interp2app(W_DictMultiObject.descr_itervalues),
+    viewkeys = interp2app(W_DictMultiObject.descr_viewkeys),
+    viewitems = interp2app(W_DictMultiObject.descr_viewitems),
+    viewvalues = interp2app(W_DictMultiObject.descr_viewvalues),
+    has_key = interp2app(W_DictMultiObject.descr_has_key),
+    clear = interp2app(W_DictMultiObject.descr_clear),
+    get = interp2app(W_DictMultiObject.descr_get),
+    pop = interp2app(W_DictMultiObject.descr_pop),
+    popitem = interp2app(W_DictMultiObject.descr_popitem),
+    setdefault = interp2app(W_DictMultiObject.descr_setdefault),
+    update = interp2app(W_DictMultiObject.descr_update),
+    )
+
+
 class DictStrategy(object):
-
     def __init__(self, space):
         self.space = space
 
@@ -139,7 +448,7 @@
     def w_keys(self, w_dict):
         iterator = self.iterkeys(w_dict)
         result = newlist_hint(self.length(w_dict))
-        while 1:
+        while True:
             w_key = iterator.next_key()
             if w_key is not None:
                 result.append(w_key)
@@ -149,7 +458,7 @@
     def values(self, w_dict):
         iterator = self.itervalues(w_dict)
         result = newlist_hint(self.length(w_dict))
-        while 1:
+        while True:
             w_value = iterator.next_value()
             if w_value is not None:
                 result.append(w_value)
@@ -159,7 +468,7 @@
     def items(self, w_dict):
         iterator = self.iteritems(w_dict)
         result = newlist_hint(self.length(w_dict))
-        while 1:
+        while True:
             w_key, w_value = iterator.next_item()
             if w_key is not None:
                 result.append(self.space.newtuple([w_key, w_value]))
@@ -171,7 +480,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,14 +503,14 @@
     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)
 
     def get_empty_storage(self):
-       return self.erase(None)
+        return self.erase(None)
 
     def switch_to_correct_strategy(self, w_dict, w_key):
         withidentitydict = self.space.config.objspace.std.withidentitydict
@@ -301,21 +609,24 @@
     def getiteritems(self, w_dict):
         return iter([(None, None)])
 
+
 # Iterator Implementation base classes
 
 def _new_next(TP):
-    if TP == 'key' or TP == 'value':
+    if TP in ('key', 'value'):
         EMPTY = None
     else:
         EMPTY = None, None
-    
+
     def next(self):
         if self.dictimplementation is None:
             return EMPTY
+        space = self.space
         if self.len != self.dictimplementation.length():
             self.len = -1   # Make this error state sticky
-            raise OperationError(self.space.w_RuntimeError,
-                     self.space.wrap("dictionary changed size during iteration"))
+            msg = "dictionary changed size during iteration"
+            raise OperationError(space.w_RuntimeError, space.wrap(msg))
+
         # look for the next entry
         if self.pos < self.len:
             result = getattr(self, 'next_' + TP + '_entry')()
@@ -333,8 +644,8 @@
                 w_value = self.dictimplementation.getitem(w_key)
                 if w_value is None:
                     self.len = -1   # Make this error state sticky
-                    raise OperationError(self.space.w_RuntimeError,
-                        self.space.wrap("dictionary changed during iteration"))
+                    msg = "dictionary changed during iteration"
+                    raise OperationError(space.w_RuntimeError, space.wrap(msg))
                 return (w_key, w_value)
         # no more entries
         self.dictimplementation = None
@@ -372,7 +683,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 +735,6 @@
 
 create_iterator_classes(EmptyDictStrategy)
 
-registerimplementation(W_DictMultiObject)
-
-# DictImplementation lattice
-# XXX fix me
-
 
 # concrete subclasses of the above
 
@@ -472,7 +778,8 @@
 
     def setdefault(self, w_dict, w_key, w_default):
         if self.is_correct_type(w_key):
-            return self.unerase(w_dict.dstorage).setdefault(self.unwrap(w_key), w_default)
+            return self.unerase(w_dict.dstorage).setdefault(self.unwrap(w_key),
+                                                            w_default)
         else:
             self.switch_to_object_strategy(w_dict)
             return w_dict.setdefault(w_key, w_default)
@@ -512,7 +819,7 @@
         space = self.space
         dict_w = self.unerase(w_dict.dstorage)
         return [space.newtuple([self.wrap(key), w_value])
-                    for (key, w_value) in dict_w.iteritems()]
+                for (key, w_value) in dict_w.iteritems()]
 
     def popitem(self, w_dict):
         key, value = self.unerase(w_dict.dstorage).popitem()
@@ -543,7 +850,6 @@
 
 
 class ObjectDictStrategy(AbstractTypedStrategy, DictStrategy):
-
     erase, unerase = rerased.new_erasing_pair("object")
     erase = staticmethod(erase)
     unerase = staticmethod(unerase)
@@ -558,9 +864,9 @@
         return True
 
     def get_empty_storage(self):
-       new_dict = r_dict(self.space.eq_w, self.space.hash_w,
-                         force_non_null=True)
-       return self.erase(new_dict)
+        new_dict = r_dict(self.space.eq_w, self.space.hash_w,
+                          force_non_null=True)
+        return self.erase(new_dict)
 
     def _never_equal_to(self, w_lookup_type):
         return False
@@ -576,8 +882,8 @@
 
 create_iterator_classes(ObjectDictStrategy)
 
+
 class StringDictStrategy(AbstractTypedStrategy, DictStrategy):
-
     erase, unerase = rerased.new_erasing_pair("string")
     erase = staticmethod(erase)
     unerase = staticmethod(unerase)
@@ -642,7 +948,6 @@
 
 
 class UnicodeDictStrategy(AbstractTypedStrategy, DictStrategy):
-
     erase, unerase = rerased.new_erasing_pair("unicode")
     erase = staticmethod(erase)
     unerase = staticmethod(unerase)
@@ -744,9 +1049,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:
@@ -764,7 +1066,7 @@
                      w_dict_unrolling_heuristic(w_data))
 def update1_dict_dict(space, w_dict, w_data):
     iterator = w_data.iteritems()
-    while 1:
+    while True:
         w_key, w_value = iterator.next_item()
         if w_key is None:
             break
@@ -788,6 +1090,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,72 +1103,19 @@
     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:
+def characterize(space, w_a, w_b):
+    """(similar to CPython)
+    returns the smallest key in acontent for which b's value is
+    different or absent and this value"""
+    w_smallest_diff_a_key = None
+    w_its_value = None
+    iteratorimplementation = w_a.iteritems()
+    while True:
         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 """
-    w_smallest_diff_a_key = None
-    w_its_value = None
-    iteratorimplementation = w_a.iteritems()
-    while 1:
-        w_key, w_val = iteratorimplementation.next_item()
-        if w_key is None:
-            break
-        if w_smallest_diff_a_key is None or space.is_true(space.lt(w_key, w_smallest_diff_a_key)):
+        if w_smallest_diff_a_key is None or space.is_true(space.lt(
+                w_key, w_smallest_diff_a_key)):
             w_bvalue = w_b.getitem(w_key)
             if w_bvalue is None:
                 w_its_value = w_val
@@ -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,265 @@
         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.type(self)
+
+        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_DictMultiIterKeysObject):
+            w_clone = space.allocate_instance(W_DictMultiIterKeysObject,
+                                              w_typeobj)
+        elif isinstance(self, W_DictMultiIterValuesObject):
+            w_clone = space.allocate_instance(W_DictMultiIterValuesObject,
+                                              w_typeobj)
+        elif isinstance(self, W_DictMultiIterItemsObject):
+            w_clone = space.allocate_instance(W_DictMultiIterItemsObject,
+                                              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)
+        w_ret = space.newtuple([new_inst, space.newtuple([w_res])])
+        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__ = interp2app(W_DictMultiIterItemsObject.descr_iter),
+    next = interp2app(W_DictMultiIterItemsObject.descr_next),
+    __length_hint__ = interp2app(W_BaseDictMultiIterObject.descr_length_hint),
+    __reduce__ = interp2app(W_BaseDictMultiIterObject.descr_reduce),
+    )
 
-def iter__DictMultiIterKeysObject(space, w_dictiter):
-    return w_dictiter
+W_DictMultiIterKeysObject.typedef = StdTypeDef(
+    "dict_iterkeys",
+    __iter__ = interp2app(W_DictMultiIterKeysObject.descr_iter),
+    next = interp2app(W_DictMultiIterKeysObject.descr_next),
+    __length_hint__ = interp2app(W_BaseDictMultiIterObject.descr_length_hint),
+    __reduce__ = interp2app(W_BaseDictMultiIterObject.descr_reduce),
+    )
 
-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__ = interp2app(W_DictMultiIterValuesObject.descr_iter),
+    next = interp2app(W_DictMultiIterValuesObject.descr_next),
+    __length_hint__ = interp2app(W_BaseDictMultiIterObject.descr_length_hint),
+    __reduce__ = interp2app(W_BaseDictMultiIterObject.descr_reduce),
+    )
 
-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)))
 
-class W_DictViewItemsObject(W_DictViewObject):
-    from pypy.objspace.std.dicttype import dict_items_typedef as typedef
-registerimplementation(W_DictViewItemsObject)
+    def descr_len(self, space):
+        return space.len(self.w_dict)
+
+def _all_contained_in(space, w_dictview, w_other):
+    w_iter = space.iter(w_dictview)
+    for w_item in space.iteriterable(w_iter):
+        if not space.is_true(space.contains(w_other, w_item)):
+            return space.w_False
+    return space.w_True
+
+def _is_set_like(w_other):
+    from pypy.objspace.std.setobject import W_BaseSetObject
+    return (isinstance(w_other, W_BaseSetObject) or
+            isinstance(w_other, W_DictViewKeysObject) or
+            isinstance(w_other, W_DictViewItemsObject))
+
+class SetLikeDictView(object):
+    _mixin_ = True
+
+    def descr_eq(self, space, w_other):
+        if not _is_set_like(w_other):
+            return space.w_NotImplemented
+        if space.len_w(self) == space.len_w(w_other):
+            return _all_contained_in(space, self, w_other)
+        return space.w_False
+
+    def descr_ne(self, space, w_other):
+        if not _is_set_like(w_other):
+            return space.w_NotImplemented
+        return space.not_(space.eq(self, w_other))
+
+    def descr_lt(self, space, w_other):
+        if not _is_set_like(w_other):
+            return space.w_NotImplemented
+        if space.len_w(self) < space.len_w(w_other):
+            return _all_contained_in(space, self, w_other)
+        return space.w_False
+
+    def descr_le(self, space, w_other):
+        if not _is_set_like(w_other):
+            return space.w_NotImplemented
+        if space.len_w(self) <= space.len_w(w_other):
+            return _all_contained_in(space, self, w_other)
+        return space.w_False
+
+    def descr_gt(self, space, w_other):
+        if not _is_set_like(w_other):
+            return space.w_NotImplemented
+        if space.len_w(self) > space.len_w(w_other):
+            return _all_contained_in(space, w_other, self)
+        return space.w_False
+
+    def descr_ge(self, space, w_other):
+        if not _is_set_like(w_other):
+            return space.w_NotImplemented
+        if space.len_w(self) >= space.len_w(w_other):
+            return _all_contained_in(space, w_other, self)
+        return space.w_False
+
+    def _as_set_op(name, methname):
+        @func_renamer('descr_' + name)
+        def op(self, space, w_other):
+            w_set = space.call_function(space.w_set, self)
+            space.call_method(w_set, methname, w_other)
+            return w_set
+        @func_renamer('descr_r' + name)
+        def rop(self, space, w_other):
+            w_set = space.call_function(space.w_set, w_other)
+            space.call_method(w_set, methname, self)
+            return w_set
+        return op, rop
+
+    descr_sub, descr_rsub = _as_set_op('sub', 'difference_update')
+    descr_and, descr_rand = _as_set_op('and', 'intersection_update')
+    descr_or, descr_ror = _as_set_op('or', 'update')
+    descr_xor, descr_rxor = _as_set_op('xor', 'symmetric_difference_update')
+
+class W_DictViewItemsObject(W_DictViewObject, SetLikeDictView):
+    def descr_iter(self, space):
+        return W_DictMultiIterItemsObject(space, self.w_dict.iteritems())
+
+class W_DictViewKeysObject(W_DictViewObject, SetLikeDictView):
+    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__ = interp2app(W_DictViewItemsObject.descr_repr),
+    __len__ = interp2app(W_DictViewItemsObject.descr_len),
+    __iter__ = interp2app(W_DictViewItemsObject.descr_iter),
 
-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)
+    __eq__ = interp2app(W_DictViewItemsObject.descr_eq),
+    __ne__ = interp2app(W_DictViewItemsObject.descr_ne),
+    __lt__ = interp2app(W_DictViewItemsObject.descr_lt),
+    __le__ = interp2app(W_DictViewItemsObject.descr_le),
+    __gt__ = interp2app(W_DictViewItemsObject.descr_gt),
+    __ge__ = interp2app(W_DictViewItemsObject.descr_ge),
 
-def all_contained_in(space, w_dictview, w_otherview):
-    w_iter = space.iter(w_dictview)
+    __sub__ = interp2app(W_DictViewItemsObject.descr_sub),
+    __rsub__ = interp2app(W_DictViewItemsObject.descr_rsub),
+    __and__ = interp2app(W_DictViewItemsObject.descr_and),
+    __rand__ = interp2app(W_DictViewItemsObject.descr_rand),
+    __or__ = interp2app(W_DictViewItemsObject.descr_or),
+    __ror__ = interp2app(W_DictViewItemsObject.descr_ror),
+    __xor__ = interp2app(W_DictViewItemsObject.descr_xor),
+    __rxor__ = interp2app(W_DictViewItemsObject.descr_rxor),
+    )
 
-    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
+W_DictViewKeysObject.typedef = StdTypeDef(
+    "dict_keys",
+    __repr__ = interp2app(W_DictViewKeysObject.descr_repr),
+    __len__ = interp2app(W_DictViewKeysObject.descr_len),
+    __iter__ = interp2app(W_DictViewKeysObject.descr_iter),
 
-    return space.w_True
+    __eq__ = interp2app(W_DictViewKeysObject.descr_eq),
+    __ne__ = interp2app(W_DictViewKeysObject.descr_ne),
+    __lt__ = interp2app(W_DictViewKeysObject.descr_lt),
+    __le__ = interp2app(W_DictViewKeysObject.descr_le),
+    __gt__ = interp2app(W_DictViewKeysObject.descr_gt),
+    __ge__ = interp2app(W_DictViewKeysObject.descr_ge),
 
-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
+    __sub__ = interp2app(W_DictViewKeysObject.descr_sub),
+    __rsub__ = interp2app(W_DictViewKeysObject.descr_rsub),
+    __and__ = interp2app(W_DictViewKeysObject.descr_and),
+    __rand__ = interp2app(W_DictViewKeysObject.descr_rand),
+    __or__ = interp2app(W_DictViewKeysObject.descr_or),
+    __ror__ = interp2app(W_DictViewKeysObject.descr_ror),
+    __xor__ = interp2app(W_DictViewKeysObject.descr_xor),
+    __rxor__ = interp2app(W_DictViewKeysObject.descr_rxor),
+    )
 
-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__ = interp2app(W_DictViewValuesObject.descr_repr),
+    __len__ = interp2app(W_DictViewValuesObject.descr_len),
+    __iter__ = interp2app(W_DictViewValuesObject.descr_iter),
+    )
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):
@@ -676,6 +696,7 @@
         assert d.viewkeys() == e.viewkeys()
         del e["a"]
         assert d.viewkeys() != e.viewkeys()
+        assert not d.viewkeys() == 42
 
     def test_dict_items(self):
         d = {1: 10, "a": "ABC"}
@@ -700,6 +721,7 @@
         assert d.viewitems() == e.viewitems()
         e["a"] = "def"
         assert d.viewitems() != e.viewitems()
+        assert not d.viewitems() == 42
 
     def test_dict_mixed_keys_items(self):
         d = {(1, 1): 11, (2, 2): 22}
@@ -712,6 +734,7 @@
         values = d.viewvalues()
         assert set(values) == set([10, "ABC"])
         assert len(values) == 2
+        assert not values == 42
 
     def test_dict_repr(self):
         d = {1: 10, "a": "ABC"}
@@ -754,6 +777,13 @@
         assert d1.viewkeys() ^ set(d2.viewkeys()) == set('ac')
         assert d1.viewkeys() ^ set(d3.viewkeys()) == set('abde')
 
+        assert d1.viewkeys() - d1.viewkeys() == set()
+        assert d1.viewkeys() - d2.viewkeys() == set('a')
+        assert d1.viewkeys() - d3.viewkeys() == set('ab')
+        assert d1.viewkeys() - set(d1.viewkeys()) == set()
+        assert d1.viewkeys() - set(d2.viewkeys()) == set('a')
+        assert d1.viewkeys() - set(d3.viewkeys()) == set('ab')
+
     def test_items_set_operations(self):
         d1 = {'a': 1, 'b': 2}
         d2 = {'a': 2, 'b': 2}
@@ -782,6 +812,113 @@
         assert (d1.viewitems() ^ d3.viewitems() ==
                 set([('a', 1), ('b', 2), ('d', 4), ('e', 5)]))
 
+        assert d1.viewitems() - d1.viewitems() == set()
+        assert d1.viewitems() - d2.viewitems() == set([('a', 1)])
+        assert d1.viewitems() - d3.viewitems() == set([('a', 1), ('b', 2)])
+
+    def test_keys_set_operations_any_type(self):
+        d = {1: u'a', 2: u'b', 3: u'c'}
+        assert d.viewkeys() & set([1]) == set([1])
+        assert d.viewkeys() & {1: u'foo'} == set([1])
+        assert d.viewkeys() & [1, 2] == set([1, 2])
+        #
+        assert set([1]) & d.viewkeys() == set([1])
+        assert {1: u'foo'} & d.viewkeys() == set([1])
+        assert [1, 2] & d.viewkeys() == set([1, 2])
+        #
+        assert d.viewkeys() - set([1]) == set([2, 3])
+        assert set([1, 4]) - d.viewkeys() == set([4])
+        #
+        assert d.viewkeys() == set([1, 2, 3])
+        # XXX: The following 4 commented out are CPython 2.7 bugs
+        #assert set([1, 2, 3]) == d.viewkeys()
+        assert d.viewkeys() == frozenset(set([1, 2, 3]))
+        #assert frozenset(set([1, 2, 3])) == d.viewkeys()
+        assert not d.viewkeys() != set([1, 2, 3])
+        #assert not set([1, 2, 3]) != d.viewkeys()
+        assert not d.viewkeys() != frozenset(set([1, 2, 3]))
+        #assert not frozenset(set([1, 2, 3])) != d.viewkeys()
+
+    def test_items_set_operations_any_type(self):
+        d = {1: u'a', 2: u'b', 3: u'c'}
+        assert d.viewitems() & set([(1, u'a')]) == set([(1, u'a')])
+        assert d.viewitems() & {(1, u'a'): u'foo'} == set([(1, u'a')])
+        assert d.viewitems() & [(1, u'a'), (2, u'b')] == set([(1, u'a'), (2, u'b')])
+        #
+        assert set([(1, u'a')]) & d.viewitems() == set([(1, u'a')])
+        assert {(1, u'a'): u'foo'} & d.viewitems() == set([(1, u'a')])
+        assert [(1, u'a'), (2, u'b')] & d.viewitems() == set([(1, u'a'), (2, u'b')])
+        #
+        assert d.viewitems() - set([(1, u'a')]) == set([(2, u'b'), (3, u'c')])
+        assert set([(1, u'a'), 4]) - d.viewitems() == set([4])
+        #
+        assert d.viewitems() == set([(1, u'a'), (2, u'b'), (3, u'c')])
+        # XXX: The following 4 commented out are CPython 2.7 bugs
+        #assert set([(1, u'a'), (2, u'b'), (3, u'c')]) == d.viewitems()
+        assert d.viewitems() == frozenset(set([(1, u'a'), (2, u'b'), (3, u'c')]))
+        #assert frozenset(set([(1, u'a'), (2, u'b'), (3, u'c')])) == d.viewitems()
+        assert not d.viewitems() != set([(1, u'a'), (2, u'b'), (3, u'c')])
+        #assert not set([(1, u'a'), (2, u'b'), (3, u'c')]) != d.viewitems()
+        assert not d.viewitems() != frozenset(set([(1, u'a'), (2, u'b'), (3, u'c')]))
+        #assert not frozenset(set([(1, u'a'), (2, u'b'), (3, u'c')])) != d.viewitems()
+
+    def test_dictviewset_unhashable_values(self):
+        class C:
+            def __eq__(self, other):
+                return True
+        d = {1: C()}
+        assert d.viewitems() <= d.viewitems()
+
+    def test_compare_keys_and_items(self):
+        d1 = {1: 2}
+        d2 = {(1, 2): 'foo'}
+        assert d1.viewitems() == d2.viewkeys()
+
+    def test_keys_items_contained(self):
+        def helper(fn):
+            empty = fn(dict())
+            empty2 = fn(dict())
+            smaller = fn({1:1, 2:2})
+            larger = fn({1:1, 2:2, 3:3})
+            larger2 = fn({1:1, 2:2, 3:3})
+            larger3 = fn({4:1, 2:2, 3:3})
+
+            assert smaller <  larger
+            assert smaller <= larger
+            assert larger >  smaller
+            assert larger >= smaller
+
+            assert not smaller >= larger
+            assert not smaller >  larger
+            assert not larger  <= smaller
+            assert not larger  <  smaller
+
+            assert not smaller <  larger3
+            assert not smaller <= larger3
+            assert not larger3 >  smaller
+            assert not larger3 >= smaller
+
+            # Inequality strictness
+            assert larger2 >= larger
+            assert larger2 <= larger
+            assert not larger2 > larger
+            assert not larger2 < larger
+
+            assert larger == larger2
+            assert smaller != larger
+
+            # There is an optimization on the zero-element case.
+            assert empty == empty2
+            assert not empty != empty2
+            assert not empty == smaller
+            assert empty != smaller
+
+            # With the same size, an elementwise compare happens
+            assert larger != larger3
+            assert not larger == larger3
+
+        helper(lambda x: x.viewkeys())
+        helper(lambda x: x.viewitems())
 
 class AppTestStrategies(object):
     def setup_class(cls):
@@ -971,10 +1108,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/gc/env.py b/rpython/memory/gc/env.py
--- a/rpython/memory/gc/env.py
+++ b/rpython/memory/gc/env.py
@@ -1,9 +1,10 @@
 """
 Utilities to get environ variables and platform-specific memory-related values.
 """
-import os, sys
+import os, sys, platform
 from rpython.rlib.rarithmetic import r_uint
 from rpython.rlib.debug import debug_print, debug_start, debug_stop
+from rpython.rlib.rstring import assert_str0
 from rpython.rtyper.lltypesystem import lltype, rffi
 from rpython.rtyper.lltypesystem.lloperation import llop
 
@@ -130,7 +131,22 @@
 
 # ---------- Linux2 ----------
 
-def get_L2cache_linux2(filename="/proc/cpuinfo"):
+def get_L2cache_linux2():
+    arch = platform.machine()
+    if arch.endswith('86') or arch == 'x86_64':
+        return get_L2cache_linux2_cpuinfo()
+    if arch in ('alpha', 'ppc', 'ppc64'):
+        return get_L2cache_linux2_cpuinfo(label='L2 cache')
+    if arch == 'ia64':
+        return get_L2cache_linux2_ia64()
+    if arch in ('parisc', 'parisc64'):
+        return get_L2cache_linux2_cpuinfo(label='D-cache')
+    if arch in ('sparc', 'sparc64'):
+        return get_L2cache_linux2_sparc()
+    return -1
+
+
+def get_L2cache_linux2_cpuinfo(filename="/proc/cpuinfo", label='cache size'):
     debug_start("gc-hardware")
     L2cache = sys.maxint
     try:
@@ -149,12 +165,8 @@
     else:
         data = ''.join(data)
         linepos = 0
-        # Currently on ARM-linux we won't find any information about caches in


More information about the pypy-commit mailing list