[pypy-commit] pypy py3k: hg merge default

antocuni noreply at buildbot.pypy.org
Fri Aug 31 10:28:26 CEST 2012


Author: Antonio Cuni <anto.cuni at gmail.com>
Branch: py3k
Changeset: r57048:58ee064bc777
Date: 2012-08-31 10:28 +0200
http://bitbucket.org/pypy/pypy/changeset/58ee064bc777/

Log:	hg merge default

diff --git a/lib_pypy/_ctypes/__init__.py b/lib_pypy/_ctypes/__init__.py
--- a/lib_pypy/_ctypes/__init__.py
+++ b/lib_pypy/_ctypes/__init__.py
@@ -19,6 +19,10 @@
     from _rawffi import FormatError
     from _rawffi import check_HRESULT as _check_HRESULT
 
+    try: from __pypy__ import builtinify
+    except ImportError: builtinify = lambda f: f
+
+    @builtinify
     def CopyComPointer(src, dst):
         from ctypes import c_void_p, cast
         if src:
@@ -28,6 +32,8 @@
         dst[0] = cast(src, c_void_p).value
         return 0
 
+    del builtinify
+
     LoadLibrary = dlopen
 
 from _rawffi import FUNCFLAG_STDCALL, FUNCFLAG_CDECL, FUNCFLAG_PYTHONAPI
diff --git a/lib_pypy/_ctypes/basics.py b/lib_pypy/_ctypes/basics.py
--- a/lib_pypy/_ctypes/basics.py
+++ b/lib_pypy/_ctypes/basics.py
@@ -3,6 +3,9 @@
 import _ffi
 import sys
 
+try: from __pypy__ import builtinify
+except ImportError: builtinify = lambda f: f
+
 keepalive_key = str # XXX fix this when provided with test
 
 def ensure_objects(where):
@@ -145,6 +148,7 @@
     _b_base_ = property(_get_b_base)
     _b_needsfree_ = False
 
+ at builtinify
 def sizeof(tp):
     if not isinstance(tp, _CDataMeta):
         if isinstance(tp, _CData):
@@ -154,6 +158,7 @@
                 type(tp).__name__,))
     return tp._sizeofinstances()
 
+ at builtinify
 def alignment(tp):
     if not isinstance(tp, _CDataMeta):
         if isinstance(tp, _CData):
@@ -163,6 +168,7 @@
                 type(tp).__name__,))
     return tp._alignmentofinstances()
 
+ at builtinify
 def byref(cdata):
     # "pointer" is imported at the end of this module to avoid circular
     # imports
@@ -176,6 +182,7 @@
     instance._buffer = self._ffiarray.fromaddress(address, lgt)
     return instance
 
+ at builtinify
 def addressof(tp):
     return tp._buffer.buffer
 
diff --git a/lib_pypy/_ctypes/dll.py b/lib_pypy/_ctypes/dll.py
--- a/lib_pypy/_ctypes/dll.py
+++ b/lib_pypy/_ctypes/dll.py
@@ -1,5 +1,9 @@
 import _rawffi
 
+try: from __pypy__ import builtinify
+except ImportError: builtinify = lambda f: f
+
+ at builtinify
 def dlopen(name, mode):
     # XXX mode is ignored
     return _rawffi.CDLL(name)
diff --git a/lib_pypy/_ctypes/function.py b/lib_pypy/_ctypes/function.py
--- a/lib_pypy/_ctypes/function.py
+++ b/lib_pypy/_ctypes/function.py
@@ -10,6 +10,8 @@
 import traceback
 import warnings
 
+try: from __pypy__ import builtinify
+except ImportError: builtinify = lambda f: f
 
 # XXX this file needs huge refactoring I fear
 
@@ -34,6 +36,7 @@
     from _ctypes import COMError
     return COMError(errcode, None, None)
 
+ at builtinify
 def call_function(func, args):
     "Only for debugging so far: So that we can call CFunction instances"
     funcptr = CFuncPtr(func)
diff --git a/lib_pypy/_ctypes/pointer.py b/lib_pypy/_ctypes/pointer.py
--- a/lib_pypy/_ctypes/pointer.py
+++ b/lib_pypy/_ctypes/pointer.py
@@ -7,6 +7,9 @@
 from _ctypes.array import Array, array_get_slice_params, array_slice_getitem,\
      array_slice_setitem
 
+try: from __pypy__ import builtinify
+except ImportError: builtinify = lambda f: f
+
 # This cache maps types to pointers to them.
 _pointer_type_cache = {}
 
@@ -154,6 +157,7 @@
 
     return result
 
+ at builtinify
 def POINTER(cls):
     try:
         return _pointer_type_cache[cls]
@@ -173,6 +177,7 @@
         _pointer_type_cache[cls] = klass
     return klass
 
+ at builtinify
 def pointer(inst):
     return POINTER(type(inst))(inst)
 
diff --git a/pypy/annotation/unaryop.py b/pypy/annotation/unaryop.py
--- a/pypy/annotation/unaryop.py
+++ b/pypy/annotation/unaryop.py
@@ -531,7 +531,7 @@
         if not s_enc.is_constant():
             raise TypeError("Non-constant encoding not supported")
         enc = s_enc.const
-        if enc not in ('ascii', 'latin-1'):
+        if enc not in ('ascii', 'latin-1', 'utf-8'):
             raise TypeError("Encoding %s not supported for unicode" % (enc,))
         return SomeString()
     method_encode.can_only_throw = [UnicodeEncodeError]
@@ -554,7 +554,7 @@
         if not s_enc.is_constant():
             raise TypeError("Non-constant encoding not supported")
         enc = s_enc.const
-        if enc not in ('ascii', 'latin-1'):
+        if enc not in ('ascii', 'latin-1', 'utf-8'):
             raise TypeError("Encoding %s not supported for strings" % (enc,))
         return SomeUnicodeString()
     method_decode.can_only_throw = [UnicodeDecodeError]
diff --git a/pypy/conftest.py b/pypy/conftest.py
--- a/pypy/conftest.py
+++ b/pypy/conftest.py
@@ -23,6 +23,17 @@
 #
 option = None
 
+
+def braindead_deindent(self):
+    """monkeypatch that wont end up doing stupid in the python tokenizer"""
+    text = '\n'.join(self.lines)
+    short = py.std.textwrap.dedent(text)
+    newsource = py.code.Source()
+    newsource.lines[:] = short.splitlines()
+    return newsource
+
+py.code.Source.deindent = braindead_deindent
+
 def pytest_report_header():
     return "pytest-%s from %s" % (pytest.__version__, pytest.__file__)
 
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
@@ -23,6 +23,12 @@
 .. branch: improve-rbigint
 Introduce __int128 on systems where it's supported and improve the speed of
 rlib/rbigint.py greatly.
+.. branch: translation-cleanup
+Start to clean up a bit the flow object space.
+.. branch: ffi-backend
+Support CFFI.  http://morepypy.blogspot.ch/2012/08/cffi-release-03.html
+.. branch: speedup-unpackiterable
+
 
 .. "uninteresting" branches that we should just ignore for the whatsnew:
 .. branch: slightly-shorter-c
diff --git a/pypy/interpreter/argument.py b/pypy/interpreter/argument.py
--- a/pypy/interpreter/argument.py
+++ b/pypy/interpreter/argument.py
@@ -314,10 +314,7 @@
         if num_kwds:
             # kwds_mapping maps target indexes in the scope (minus input_argcount)
             # to positions in the keywords_w list
-            cnt = (co_argcount + co_kwonlyargcount - input_argcount)
-            if cnt < 0:
-                cnt = 0
-            kwds_mapping = [0] * cnt
+            kwds_mapping = [0] * (co_argcount + co_kwonlyargcount - input_argcount)
             # initialize manually, for the JIT :-(
             for i in range(len(kwds_mapping)):
                 kwds_mapping[i] = -1
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -20,6 +20,9 @@
 
 UINT_MAX_32_BITS = r_uint(4294967295)
 
+unpackiterable_driver = jit.JitDriver(name = 'unpackiterable',
+                                      greens = ['tp'],
+                                      reds = ['items', 'w_iterator'])
 
 class W_Root(object):
     """This is the abstract root class of all wrapped objects that live
@@ -224,6 +227,23 @@
     def __spacebind__(self, space):
         return self
 
+class W_InterpIterable(W_Root):
+    def __init__(self, space, w_iterable):
+        self.w_iter = space.iter(w_iterable)
+        self.space = space
+
+    def __iter__(self):
+        return self
+
+    def next(self):
+        space = self.space
+        try:
+            return space.next(self.w_iter)
+        except OperationError, e:
+            if not e.match(space, space.w_StopIteration):
+                raise
+            raise StopIteration
+
 class InternalSpaceCache(Cache):
     """A generic cache for an object space.  Arbitrary information can
     be attached to the space by defining a function or class 'f' which
@@ -837,6 +857,9 @@
                                                       expected_length)
             return lst_w[:]     # make the resulting list resizable
 
+    def iteriterable(self, w_iterable):
+        return W_InterpIterable(self, w_iterable)
+
     @jit.dont_look_inside
     def _unpackiterable_unknown_length(self, w_iterator, w_iterable):
         # Unpack a variable-size list of unknown length.
@@ -857,7 +880,11 @@
             except MemoryError:
                 items = [] # it might have lied
         #
+        tp = self.type(w_iterator)
         while True:
+            unpackiterable_driver.jit_merge_point(tp=tp,
+                                                  w_iterator=w_iterator,
+                                                  items=items)
             try:
                 w_item = self.next(w_iterator)
             except OperationError, e:
diff --git a/pypy/jit/backend/llgraph/runner.py b/pypy/jit/backend/llgraph/runner.py
--- a/pypy/jit/backend/llgraph/runner.py
+++ b/pypy/jit/backend/llgraph/runner.py
@@ -365,7 +365,8 @@
         from pypy.jit.backend.llsupport.ffisupport import UnsupportedKind
         arg_types = []
         try:
-            for arg in cif_description.atypes:
+            for itp in range(cif_description.nargs):
+                arg = cif_description.atypes[itp]
                 kind = get_ffi_type_kind(self, arg)
                 if kind != history.VOID:
                     arg_types.append(kind)
diff --git a/pypy/jit/backend/test/calling_convention_test.py b/pypy/jit/backend/test/calling_convention_test.py
--- a/pypy/jit/backend/test/calling_convention_test.py
+++ b/pypy/jit/backend/test/calling_convention_test.py
@@ -310,9 +310,9 @@
         F = lltype.Float
         S = lltype.SingleFloat
         I = lltype.Signed
-        floats = [random.random() - 0.5 for i in range(8)]
-        singlefloats = [r_singlefloat(random.random() - 0.5) for i in range(8)]
-        ints = [random.randrange(-99, 99) for i in range(8)]
+        floats = [random.random() - 0.5 for i in range(20)]
+        singlefloats = [r_singlefloat(random.random() - 0.5) for i in range(20)]
+        ints = [random.randrange(-99, 99) for i in range(20)]
         for repeat in range(100):
             args = []
             argvalues = []
@@ -320,20 +320,23 @@
             local_floats = list(floats)
             local_singlefloats = list(singlefloats)
             local_ints = list(ints)
-            for i in range(8):
-                case = random.randrange(0, 3)
-                if case == 0:
+            for i in range(random.randrange(4, 20)):
+                case = random.randrange(0, 6)
+                if case & 1: boxme = BoxInt
+                else:        boxme = ConstInt
+                if case < 2:
                     args.append(F)
-                    arg = local_floats.pop()
-                    argslist.append(boxfloat(arg))
-                elif case == 1:
+                    arg = arg1 = local_floats.pop()
+                    if case & 1: boxme = boxfloat
+                    else:        boxme = constfloat
+                elif case < 4:
                     args.append(S)
                     arg = local_singlefloats.pop()
-                    argslist.append(BoxInt(longlong.singlefloat2int(arg)))
+                    arg1 = longlong.singlefloat2int(arg)
                 else:
                     args.append(I)
-                    arg = local_ints.pop()
-                    argslist.append(BoxInt(arg))
+                    arg = arg1 = local_ints.pop()
+                argslist.append(boxme(arg1))
                 argvalues.append(arg)
             FUNC = self.FuncType(args, F)
             FPTR = self.Ptr(FUNC)
diff --git a/pypy/jit/backend/x86/assembler.py b/pypy/jit/backend/x86/assembler.py
--- a/pypy/jit/backend/x86/assembler.py
+++ b/pypy/jit/backend/x86/assembler.py
@@ -1171,11 +1171,13 @@
                     xmm_dst_locs.append(unused_xmm.pop())
                 else:
                     pass_on_stack.append(loc)
-            elif (argtypes is not None and argtypes[i-start] == 'S' and
-                  len(unused_xmm) > 0):
+            elif argtypes is not None and argtypes[i-start] == 'S':
                 # Singlefloat argument
-                if singlefloats is None: singlefloats = []
-                singlefloats.append((loc, unused_xmm.pop()))
+                if len(unused_xmm) > 0:
+                    if singlefloats is None: singlefloats = []
+                    singlefloats.append((loc, unused_xmm.pop()))
+                else:
+                    pass_on_stack.append(loc)
             else:
                 if len(unused_gpr) > 0:
                     src_locs.append(loc)
@@ -1209,6 +1211,9 @@
         # Load the singlefloat arguments from main regs or stack to xmm regs
         if singlefloats is not None:
             for src, dst in singlefloats:
+                if isinstance(src, ImmedLoc):
+                    self.mc.MOV(X86_64_SCRATCH_REG, src)
+                    src = X86_64_SCRATCH_REG
                 self.mc.MOVD(dst, src)
         # Finally remap the arguments in the main regs
         # If x is a register and is in dst_locs, then oups, it needs to
diff --git a/pypy/jit/metainterp/warmspot.py b/pypy/jit/metainterp/warmspot.py
--- a/pypy/jit/metainterp/warmspot.py
+++ b/pypy/jit/metainterp/warmspot.py
@@ -14,6 +14,7 @@
 from pypy.rlib.debug import fatalerror
 from pypy.rlib.rstackovf import StackOverflow
 from pypy.translator.simplify import get_functype
+from pypy.translator.backendopt import removenoops
 from pypy.translator.unsimplify import call_final_function
 
 from pypy.jit.metainterp import history, pyjitpl, gc, memmgr
@@ -260,6 +261,10 @@
         graph = copygraph(graph)
         [jmpp] = find_jit_merge_points([graph])
         graph.startblock = support.split_before_jit_merge_point(*jmpp)
+        # XXX this is incredibly obscure, but this is sometiems necessary
+        #     so we don't explode in checkgraph. for reasons unknown this
+        #     is not contanied within simplify_graph
+        removenoops.remove_same_as(graph)
         # a crash in the following checkgraph() means that you forgot
         # to list some variable in greens=[] or reds=[] in JitDriver,
         # or that a jit_merge_point() takes a constant as an argument.
diff --git a/pypy/module/_cffi_backend/ctypefunc.py b/pypy/module/_cffi_backend/ctypefunc.py
--- a/pypy/module/_cffi_backend/ctypefunc.py
+++ b/pypy/module/_cffi_backend/ctypefunc.py
@@ -229,7 +229,7 @@
 W_CTypePrimitiveFloat._get_ffi_type         = _primfloat_ffi_type
 W_CTypePrimitiveLongDouble._get_ffi_type    = _primlongdouble_ffi_type
 W_CTypePtrBase._get_ffi_type                = _ptr_ffi_type
-W_CTypeVoid._get_ffi_type                   = _void_ffi_type
+#W_CTypeVoid._get_ffi_type                  = _void_ffi_type -- special-cased
 # ----------
 
 
@@ -251,7 +251,9 @@
             return result
 
 
-    def fb_fill_type(self, ctype):
+    def fb_fill_type(self, ctype, is_result_type):
+        if is_result_type and isinstance(ctype, W_CTypeVoid):
+            return clibffi.ffi_type_void
         return ctype._get_ffi_type(self)
 
     def fb_struct_ffi_type(self, ctype):
@@ -262,6 +264,11 @@
         # But on 64-bit UNIX, these two structs are passed by value
         # differently: e.g. on x86-64, "b" ends up in register "rsi" in
         # the first case and "rdi" in the second case.
+        #
+        # Another reason for 'custom_field_pos' would be anonymous
+        # nested structures: we lost the information about having it
+        # here, so better safe (and forbid it) than sorry (and maybe
+        # crash).
         space = self.space
         if ctype.custom_field_pos:
             raise OperationError(space.w_TypeError,
@@ -281,7 +288,7 @@
                 raise OperationError(space.w_NotImplementedError,
                     space.wrap("cannot pass as argument a struct "
                                "with bit fields"))
-            ffi_subtype = self.fb_fill_type(cf.ctype)
+            ffi_subtype = self.fb_fill_type(cf.ctype, False)
             if elements:
                 elements[i] = ffi_subtype
 
@@ -322,11 +329,11 @@
         self.atypes = rffi.cast(FFI_TYPE_PP, atypes)
 
         # next comes the result type data
-        self.rtype = self.fb_fill_type(self.fresult)
+        self.rtype = self.fb_fill_type(self.fresult, True)
 
         # next comes each argument's type data
         for i, farg in enumerate(self.fargs):
-            atype = self.fb_fill_type(farg)
+            atype = self.fb_fill_type(farg, False)
             if self.atypes:
                 self.atypes[i] = atype
 
diff --git a/pypy/module/_cffi_backend/ctypestruct.py b/pypy/module/_cffi_backend/ctypestruct.py
--- a/pypy/module/_cffi_backend/ctypestruct.py
+++ b/pypy/module/_cffi_backend/ctypestruct.py
@@ -162,6 +162,10 @@
     def is_bitfield(self):
         return self.bitshift >= 0
 
+    def make_shifted(self, offset):
+        return W_CField(self.ctype, offset + self.offset,
+                        self.bitshift, self.bitsize)
+
     def read(self, cdata):
         cdata = rffi.ptradd(cdata, self.offset)
         if self.bitshift == self.BS_REGULAR:
diff --git a/pypy/module/_cffi_backend/newtype.py b/pypy/module/_cffi_backend/newtype.py
--- a/pypy/module/_cffi_backend/newtype.py
+++ b/pypy/module/_cffi_backend/newtype.py
@@ -182,9 +182,26 @@
             if not is_union:
                 prev_bit_position += fbitsize
         #
-        fld = ctypestruct.W_CField(ftype, offset, bitshift, fbitsize)
-        fields_list.append(fld)
-        fields_dict[fname] = fld
+        if (len(fname) == 0 and
+            isinstance(ftype, ctypestruct.W_CTypeStructOrUnion)):
+            # a nested anonymous struct or union
+            srcfield2names = {}
+            for name, srcfld in ftype.fields_dict.items():
+                srcfield2names[srcfld] = name
+            for srcfld in ftype.fields_list:
+                fld = srcfld.make_shifted(offset)
+                fields_list.append(fld)
+                try:
+                    fields_dict[srcfield2names[srcfld]] = fld
+                except KeyError:
+                    pass
+            # always forbid such structures from being passed by value
+            custom_field_pos = True
+        else:
+            # a regular field
+            fld = ctypestruct.W_CField(ftype, offset, bitshift, fbitsize)
+            fields_list.append(fld)
+            fields_dict[fname] = fld
         #
         if maxsize < ftype.size:
             maxsize = ftype.size
@@ -194,13 +211,13 @@
     if is_union:
         assert offset == 0
         offset = maxsize
-    else:
-        if offset == 0:
-            offset = 1
-        offset = (offset + alignment - 1) & ~(alignment-1)
+    offset = (offset + alignment - 1) & ~(alignment-1)
 
+    # Like C, if the size of this structure would be zero, we compute it
+    # as 1 instead.  But for ctypes support, we allow the manually-
+    # specified totalsize to be zero in this case.
     if totalsize < 0:
-        totalsize = offset
+        totalsize = offset or 1
     elif totalsize < offset:
         raise operationerrfmt(space.w_TypeError,
                      "%s cannot be of size %d: there are fields at least "
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
@@ -8,6 +8,11 @@
     readbuf = str
     bufchar = lambda x: x
     bytechr = chr
+    class U(object):
+        def __add__(self, other):
+            return eval('u'+repr(other).replace(r'\\u', r'\u')
+                                       .replace(r'\\U', r'\U'))
+    u = U()
 else:
     type_or_class = "class"
     long = int
@@ -18,6 +23,7 @@
     readbuf = lambda buf: buf.tobytes()
     bufchar = ord
     bytechr = lambda n: bytes([n])
+    u = ""
 
 def size_of_int():
     BInt = new_primitive_type("int")
@@ -92,7 +98,7 @@
         py.test.raises(TypeError, cast, p, None)
         assert long(cast(p, min - 1)) == max
         assert int(cast(p, b'\x08')) == 8
-        assert int(cast(p, u'\x08')) == 8
+        assert int(cast(p, u+'\x08')) == 8
     for name in ['char', 'short', 'int', 'long', 'long long']:
         p = new_primitive_type('unsigned ' + name)
         size = sizeof(p)
@@ -103,7 +109,7 @@
         assert int(cast(p, max + 1)) == 0
         assert long(cast(p, -1)) == max
         assert int(cast(p, b'\xFE')) == 254
-        assert int(cast(p, u'\xFE')) == 254
+        assert int(cast(p, u+'\xFE')) == 254
 
 def test_no_float_on_int_types():
     p = new_primitive_type('long')
@@ -136,7 +142,7 @@
         assert cast(p, -1.1) != cast(p, -1.1)
         assert repr(float(cast(p, -0.0))) == '-0.0'
         assert float(cast(p, b'\x09')) == 9.0
-        assert float(cast(p, u'\x09')) == 9.0
+        assert float(cast(p, u+'\x09')) == 9.0
         assert float(cast(p, True)) == 1.0
         py.test.raises(TypeError, cast, p, None)
 
@@ -286,12 +292,12 @@
     assert p[0] == b'A'
     py.test.raises(TypeError, newp, BPtr, 65)
     py.test.raises(TypeError, newp, BPtr, b"foo")
-    py.test.raises(TypeError, newp, BPtr, u"foo")
+    py.test.raises(TypeError, newp, BPtr, u+"foo")
     c = cast(BChar, b'A')
     assert str(c) == repr(c)
     assert int(c) == ord(b'A')
     py.test.raises(TypeError, cast, BChar, b'foo')
-    py.test.raises(TypeError, cast, BChar, u'foo')
+    py.test.raises(TypeError, cast, BChar, u+'foo')
 
 def test_reading_pointer_to_pointer():
     BVoidP = new_pointer_type(new_void_type())
@@ -763,6 +769,11 @@
     BFunc = new_function_type((BInt, BInt), BVoid, False)
     assert repr(BFunc) == "<ctype 'void(*)(int, int)'>"
 
+def test_function_void_arg():
+    BVoid = new_void_type()
+    BInt = new_primitive_type("int")
+    py.test.raises(TypeError, new_function_type, (BVoid,), BInt, False)
+
 def test_call_function_0():
     BSignedChar = new_primitive_type("signed char")
     BFunc0 = new_function_type((BSignedChar, BSignedChar), BSignedChar, False)
@@ -846,7 +857,7 @@
     #
     py.test.raises(TypeError, f, 123456)
     py.test.raises(TypeError, f, "foo")
-    py.test.raises(TypeError, f, u"bar")
+    py.test.raises(TypeError, f, u+"bar")
 
 def test_call_function_7():
     BChar = new_primitive_type("char")
@@ -871,8 +882,8 @@
     BStructPtr = new_pointer_type(BStruct)
     complete_struct_or_union(BStruct, [('a1', BChar, -1),
                                        ('a2', BShort, -1)])
-    BFunc18 = new_function_type((BStructPtr,), BShort, False)
-    f = cast(BFunc18, _testfunc(20))
+    BFunc20 = new_function_type((BStructPtr,), BShort, False)
+    f = cast(BFunc20, _testfunc(20))
     x = newp(BStructPtr, {'a1': b'A', 'a2': -4042})
     # test the exception that allows us to pass a 'struct foo' where the
     # function really expects a 'struct foo *'.
@@ -880,6 +891,25 @@
     assert res == -4042 + ord(b'A')
     assert res == f(x)
 
+def test_call_function_21():
+    BInt = new_primitive_type("int")
+    BStruct = new_struct_type("foo")
+    complete_struct_or_union(BStruct, [('a', BInt, -1),
+                                       ('b', BInt, -1),
+                                       ('c', BInt, -1),
+                                       ('d', BInt, -1),
+                                       ('e', BInt, -1),
+                                       ('f', BInt, -1),
+                                       ('g', BInt, -1),
+                                       ('h', BInt, -1),
+                                       ('i', BInt, -1),
+                                       ('j', BInt, -1)])
+    BFunc21 = new_function_type((BStruct,), BInt, False)
+    f = cast(BFunc21, _testfunc(21))
+    res = f(range(13, 3, -1))
+    lst = [(n << i) for (i, n) in enumerate(range(13, 3, -1))]
+    assert res == sum(lst)
+
 def test_call_function_9():
     BInt = new_primitive_type("int")
     BFunc9 = new_function_type((BInt,), BInt, True)    # vararg
@@ -1031,6 +1061,31 @@
     assert s.a == -10
     assert s.b == 1E-42
 
+def test_callback_returning_big_struct():
+    BInt = new_primitive_type("int")
+    BStruct = new_struct_type("foo")
+    BStructPtr = new_pointer_type(BStruct)
+    complete_struct_or_union(BStruct, [('a', BInt, -1),
+                                       ('b', BInt, -1),
+                                       ('c', BInt, -1),
+                                       ('d', BInt, -1),
+                                       ('e', BInt, -1),
+                                       ('f', BInt, -1),
+                                       ('g', BInt, -1),
+                                       ('h', BInt, -1),
+                                       ('i', BInt, -1),
+                                       ('j', BInt, -1)])
+    def cb():
+        return newp(BStructPtr, range(13, 3, -1))[0]
+    BFunc = new_function_type((), BStruct)
+    f = callback(BFunc, cb)
+    s = f()
+    assert typeof(s) is BStruct
+    assert repr(s) in ["<cdata 'struct foo' owning 40 bytes>",
+                       "<cdata 'struct foo' owning 80 bytes>"]
+    for i, name in enumerate("abcdefghij"):
+        assert getattr(s, name) == 13 - i
+
 def test_callback_returning_void():
     BVoid = new_void_type()
     BFunc = new_function_type((), BVoid, False)
@@ -1106,7 +1161,7 @@
     assert f(255) == b'\xFF'
 
 def _hacked_pypy_uni4():
-    pyuni4 = {1: True, 2: False}[len(u'\U00012345')]
+    pyuni4 = {1: True, 2: False}[len(u+'\U00012345')]
     return 'PY_DOT_PY' in globals() and not pyuni4
 
 def test_callback_returning_wchar_t():
@@ -1114,7 +1169,7 @@
     BWChar = new_primitive_type("wchar_t")
     def cb(n):
         if n == -1:
-            return u'\U00012345'
+            return u+'\U00012345'
         if n == -2:
             raise ValueError
         return unichr(n)
@@ -1122,10 +1177,10 @@
     f = callback(BFunc, cb)
     assert f(0) == unichr(0)
     assert f(255) == unichr(255)
-    assert f(0x1234) == u'\u1234'
+    assert f(0x1234) == u+'\u1234'
     if sizeof(BWChar) == 4 and not _hacked_pypy_uni4():
-        assert f(-1) == u'\U00012345'
-    assert f(-2) == u'\x00'   # and an exception printed to stderr
+        assert f(-1) == u+'\U00012345'
+    assert f(-2) == u+'\x00'   # and an exception printed to stderr
 
 def test_struct_with_bitfields():
     BLong = new_primitive_type("long")
@@ -1358,14 +1413,14 @@
 
 def test_string_wchar():
     BWChar = new_primitive_type("wchar_t")
-    assert string(cast(BWChar, 42)) == u'*'
-    assert string(cast(BWChar, 0x4253)) == u'\u4253'
-    assert string(cast(BWChar, 0)) == u'\x00'
+    assert string(cast(BWChar, 42)) == u+'*'
+    assert string(cast(BWChar, 0x4253)) == u+'\u4253'
+    assert string(cast(BWChar, 0)) == u+'\x00'
     BArray = new_array_type(new_pointer_type(BWChar), None)
-    a = newp(BArray, [u'A', u'B', u'C'])
-    assert type(string(a)) is unicode and string(a) == u'ABC'
+    a = newp(BArray, [u+'A', u+'B', u+'C'])
+    assert type(string(a)) is unicode and string(a) == u+'ABC'
     if 'PY_DOT_PY' not in globals() and sys.version_info < (3,):
-        assert string(a, 8).startswith(u'ABC') # may contain additional garbage
+        assert string(a, 8).startswith(u+'ABC') # may contain additional garbage
 
 def test_string_typeerror():
     BShort = new_primitive_type("short")
@@ -1516,7 +1571,7 @@
 def test_wchar():
     BWChar = new_primitive_type("wchar_t")
     BInt = new_primitive_type("int")
-    pyuni4 = {1: True, 2: False}[len(u'\U00012345')]
+    pyuni4 = {1: True, 2: False}[len(u+'\U00012345')]
     wchar4 = {2: False, 4: True}[sizeof(BWChar)]
     assert str(cast(BWChar, 0x45)) == "<cdata 'wchar_t' %s'E'>" % (
         mandatory_u_prefix,)
@@ -1537,44 +1592,44 @@
     complete_struct_or_union(BStruct, [('a1', BWChar, -1),
                                        ('a2', BWCharP, -1)])
     s = newp(BStructPtr)
-    s.a1 = u'\x00'
-    assert s.a1 == u'\x00'
+    s.a1 = u+'\x00'
+    assert s.a1 == u+'\x00'
     py.test.raises(TypeError, "s.a1 = b'a'")
     py.test.raises(TypeError, "s.a1 = bytechr(0xFF)")
-    s.a1 = u'\u1234'
-    assert s.a1 == u'\u1234'
+    s.a1 = u+'\u1234'
+    assert s.a1 == u+'\u1234'
     if pyuni4:
         assert wchar4
-        s.a1 = u'\U00012345'
-        assert s.a1 == u'\U00012345'
+        s.a1 = u+'\U00012345'
+        assert s.a1 == u+'\U00012345'
     elif wchar4:
         if not _hacked_pypy_uni4():
             s.a1 = cast(BWChar, 0x12345)
-            assert s.a1 == u'\ud808\udf45'
-            s.a1 = u'\ud807\udf44'
-            assert s.a1 == u'\U00011f44'
+            assert s.a1 == u+'\ud808\udf45'
+            s.a1 = u+'\ud807\udf44'
+            assert s.a1 == u+'\U00011f44'
     else:
-        py.test.raises(TypeError, "s.a1 = u'\U00012345'")
+        py.test.raises(TypeError, "s.a1 = u+'\U00012345'")
     #
     BWCharArray = new_array_type(BWCharP, None)
-    a = newp(BWCharArray, u'hello \u1234 world')
+    a = newp(BWCharArray, u+'hello \u1234 world')
     assert len(a) == 14   # including the final null
-    assert string(a) == u'hello \u1234 world'
-    a[13] = u'!'
-    assert string(a) == u'hello \u1234 world!'
+    assert string(a) == u+'hello \u1234 world'
+    a[13] = u+'!'
+    assert string(a) == u+'hello \u1234 world!'
     assert str(a) == repr(a)
-    assert a[6] == u'\u1234'
-    a[6] = u'-'
-    assert string(a) == u'hello - world!'
+    assert a[6] == u+'\u1234'
+    a[6] = u+'-'
+    assert string(a) == u+'hello - world!'
     assert str(a) == repr(a)
     #
     if wchar4 and not _hacked_pypy_uni4():
-        u = u'\U00012345\U00012346\U00012347'
-        a = newp(BWCharArray, u)
+        u1 = u+'\U00012345\U00012346\U00012347'
+        a = newp(BWCharArray, u1)
         assert len(a) == 4
-        assert string(a) == u
+        assert string(a) == u1
         assert len(list(a)) == 4
-        expected = [u'\U00012345', u'\U00012346', u'\U00012347', unichr(0)]
+        expected = [u+'\U00012345', u+'\U00012346', u+'\U00012347', unichr(0)]
         assert list(a) == expected
         got = [a[i] for i in range(4)]
         assert got == expected
@@ -1583,44 +1638,44 @@
     w = cast(BWChar, 'a')
     assert repr(w) == "<cdata 'wchar_t' %s'a'>" % mandatory_u_prefix
     assert str(w) == repr(w)
-    assert string(w) == u'a'
+    assert string(w) == u+'a'
     assert int(w) == ord('a')
     w = cast(BWChar, 0x1234)
     assert repr(w) == "<cdata 'wchar_t' %s'\u1234'>" % mandatory_u_prefix
     assert str(w) == repr(w)
-    assert string(w) == u'\u1234'
+    assert string(w) == u+'\u1234'
     assert int(w) == 0x1234
-    w = cast(BWChar, u'\u8234')
+    w = cast(BWChar, u+'\u8234')
     assert repr(w) == "<cdata 'wchar_t' %s'\u8234'>" % mandatory_u_prefix
     assert str(w) == repr(w)
-    assert string(w) == u'\u8234'
+    assert string(w) == u+'\u8234'
     assert int(w) == 0x8234
-    w = cast(BInt, u'\u1234')
+    w = cast(BInt, u+'\u1234')
     assert repr(w) == "<cdata 'int' 4660>"
     if wchar4 and not _hacked_pypy_uni4():
-        w = cast(BWChar, u'\U00012345')
+        w = cast(BWChar, u+'\U00012345')
         assert repr(w) == "<cdata 'wchar_t' %s'\U00012345'>" % (
             mandatory_u_prefix,)
         assert str(w) == repr(w)
-        assert string(w) == u'\U00012345'
+        assert string(w) == u+'\U00012345'
         assert int(w) == 0x12345
-        w = cast(BInt, u'\U00012345')
+        w = cast(BInt, u+'\U00012345')
         assert repr(w) == "<cdata 'int' 74565>"
-    py.test.raises(TypeError, cast, BInt, u'')
-    py.test.raises(TypeError, cast, BInt, u'XX')
-    assert int(cast(BInt, u'a')) == ord('a')
+    py.test.raises(TypeError, cast, BInt, u+'')
+    py.test.raises(TypeError, cast, BInt, u+'XX')
+    assert int(cast(BInt, u+'a')) == ord('a')
     #
-    a = newp(BWCharArray, u'hello - world')
+    a = newp(BWCharArray, u+'hello - world')
     p = cast(BWCharP, a)
-    assert string(p) == u'hello - world'
-    p[6] = u'\u2345'
-    assert string(p) == u'hello \u2345 world'
+    assert string(p) == u+'hello - world'
+    p[6] = u+'\u2345'
+    assert string(p) == u+'hello \u2345 world'
     #
-    s = newp(BStructPtr, [u'\u1234', p])
-    assert s.a1 == u'\u1234'
+    s = newp(BStructPtr, [u+'\u1234', p])
+    assert s.a1 == u+'\u1234'
     assert s.a2 == p
     assert str(s.a2) == repr(s.a2)
-    assert string(s.a2) == u'hello \u2345 world'
+    assert string(s.a2) == u+'hello \u2345 world'
     #
     q = cast(BWCharP, 0)
     assert str(q) == repr(q)
@@ -1631,7 +1686,7 @@
         return len(string(p))
     BFunc = new_function_type((BWCharP,), BInt, False)
     f = callback(BFunc, cb, -42)
-    assert f(u'a\u1234b') == 3
+    assert f(u+'a\u1234b') == 3
     #
     if wchar4 and not pyuni4 and not _hacked_pypy_uni4():
         # try out-of-range wchar_t values
@@ -1951,3 +2006,50 @@
             assert repr(p.a1).startswith("<cdata 'long *' 0x")
         else:
             assert repr(p.a1).startswith("<cdata 'long[%d]' 0x" % length)
+
+def test_nested_anonymous_struct():
+    BInt = new_primitive_type("int")
+    BChar = new_primitive_type("char")
+    BStruct = new_struct_type("foo")
+    BInnerStruct = new_struct_type("foo")
+    complete_struct_or_union(BInnerStruct, [('a1', BInt, -1),
+                                            ('a2', BChar, -1)])
+    complete_struct_or_union(BStruct, [('', BInnerStruct, -1),
+                                       ('a3', BChar, -1)])
+    assert sizeof(BInnerStruct) == sizeof(BInt) * 2   # with alignment
+    assert sizeof(BStruct) == sizeof(BInt) * 3        # 'a3' is placed after
+    d = _getfields(BStruct)
+    assert len(d) == 3
+    assert d[0][0] == 'a1'
+    assert d[0][1].type is BInt
+    assert d[0][1].offset == 0
+    assert d[0][1].bitshift == -1
+    assert d[0][1].bitsize == -1
+    assert d[1][0] == 'a2'
+    assert d[1][1].type is BChar
+    assert d[1][1].offset == sizeof(BInt)
+    assert d[1][1].bitshift == -1
+    assert d[1][1].bitsize == -1
+    assert d[2][0] == 'a3'
+    assert d[2][1].type is BChar
+    assert d[2][1].offset == sizeof(BInt) * 2
+    assert d[2][1].bitshift == -1
+    assert d[2][1].bitsize == -1
+
+def test_sizeof_union():
+    # a union has the largest alignment of its members, and a total size
+    # that is the largest of its items *possibly further aligned* if
+    # another smaller item has a larger alignment...
+    BChar = new_primitive_type("char")
+    BShort = new_primitive_type("short")
+    assert sizeof(BShort) == alignof(BShort) == 2
+    BStruct = new_struct_type("foo")
+    complete_struct_or_union(BStruct, [('a1', BChar),
+                                       ('a2', BChar),
+                                       ('a3', BChar)])
+    assert sizeof(BStruct) == 3 and alignof(BStruct) == 1
+    BUnion = new_union_type("u")
+    complete_struct_or_union(BUnion, [('s', BStruct),
+                                      ('i', BShort)])
+    assert sizeof(BUnion) == 4
+    assert alignof(BUnion) == 2
diff --git a/pypy/module/_cffi_backend/test/_test_lib.c b/pypy/module/_cffi_backend/test/_test_lib.c
--- a/pypy/module/_cffi_backend/test/_test_lib.c
+++ b/pypy/module/_cffi_backend/test/_test_lib.c
@@ -146,6 +146,21 @@
     return ptr->a1 + ptr->a2;
 }
 
+struct _testfunc21_s { int a, b, c, d, e, f, g, h, i, j; };
+static int _testfunc21(struct _testfunc21_s inlined)
+{
+    return ((inlined.a << 0) +
+            (inlined.b << 1) +
+            (inlined.c << 2) +
+            (inlined.d << 3) +
+            (inlined.e << 4) +
+            (inlined.f << 5) +
+            (inlined.g << 6) +
+            (inlined.h << 7) +
+            (inlined.i << 8) +
+            (inlined.j << 9));
+}
+
 DLLEXPORT void *gettestfunc(int num)
 {
     void *f;
@@ -171,6 +186,7 @@
     case 18: f = &_testfunc18; break;
     case 19: f = &_testfunc19; break;
     case 20: f = &_testfunc20; break;
+    case 21: f = &_testfunc21; break;
     default:
         return NULL;
     }
diff --git a/pypy/module/_cffi_backend/test/test_c.py b/pypy/module/_cffi_backend/test/test_c.py
--- a/pypy/module/_cffi_backend/test/test_c.py
+++ b/pypy/module/_cffi_backend/test/test_c.py
@@ -1,7 +1,19 @@
 from __future__ import with_statement
 """
 This file is OBSCURE.  Really.  The purpose is to avoid copying and changing
-'test_c.py' from cffi/c/.
+'test_c.py' from cffi/c/ in the original CFFI repository:
+    https://bitbucket.org/cffi/cffi
+
+Adding a test here involves:
+1. add a test to cffi/c/test.py
+   - if you need a C function to call, add it into _cffi_backend.c
+     as a testfuncNN().
+2. have it pass when you run 'py.test test_c.py' in cffi
+3. check in and (if you can) push the changes
+4. copy test_c.py into _backend_test.py here, killing the few lines of header
+   - if you added a C function, it goes into _test_lib.c here
+   - if you could complete step 3, try running 'py.test test_file.py' here
+5. make the test pass in pypy ('py.test test_c.py')
 """
 import py, sys, ctypes
 if sys.version_info < (2, 6):
diff --git a/pypy/module/_io/interp_iobase.py b/pypy/module/_io/interp_iobase.py
--- a/pypy/module/_io/interp_iobase.py
+++ b/pypy/module/_io/interp_iobase.py
@@ -330,13 +330,11 @@
             try:
                 space.call_method(w_iobase, 'flush')
             except OperationError, e:
-                # if it's an IOError or ValueError, ignore it (ValueError is
-                # raised if by chance we are trying to flush a file which has
-                # already been closed)
-                if not (e.match(space, space.w_IOError) or
-                        e.match(space, space.w_ValueError)):
-                    raise
-        
+                # Silencing all errors is bad, but getting randomly
+                # interrupted here is equally as bad, and potentially
+                # more frequent (because of shutdown issues).
+                pass 
+
 
 class AutoFlusher(object):
     
diff --git a/pypy/module/_multiprocessing/test/test_semaphore.py b/pypy/module/_multiprocessing/test/test_semaphore.py
--- a/pypy/module/_multiprocessing/test/test_semaphore.py
+++ b/pypy/module/_multiprocessing/test/test_semaphore.py
@@ -18,6 +18,8 @@
         kind = self.SEMAPHORE
         value = 1
         maxvalue = 1
+        # the following line gets OSError: [Errno 38] Function not implemented
+        # if /dev/shm is not mounted on Linux
         sem = SemLock(kind, value, maxvalue)
         assert sem.kind == kind
         assert sem.maxvalue == maxvalue
@@ -49,6 +51,8 @@
         kind = self.RECURSIVE
         value = 1
         maxvalue = 1
+        # the following line gets OSError: [Errno 38] Function not implemented
+        # if /dev/shm is not mounted on Linux
         sem = SemLock(kind, value, maxvalue)
 
         sem.acquire()
diff --git a/pypy/module/itertools/test/test_itertools.py b/pypy/module/itertools/test/test_itertools.py
--- a/pypy/module/itertools/test/test_itertools.py
+++ b/pypy/module/itertools/test/test_itertools.py
@@ -88,6 +88,13 @@
         list(it)
         assert repr(it) == "repeat('foobar', 0)"
 
+    def test_repeat_len(self):
+        import itertools
+
+        r = itertools.repeat('a', 15)
+        r.next()
+        raises(TypeError, "len(itertools.repeat('xkcd'))")
+
     def test_takewhile(self):
         import itertools
 
diff --git a/pypy/module/micronumpy/strides.py b/pypy/module/micronumpy/strides.py
--- a/pypy/module/micronumpy/strides.py
+++ b/pypy/module/micronumpy/strides.py
@@ -48,9 +48,12 @@
     return rstrides, rbackstrides
 
 def is_single_elem(space, w_elem, is_rec_type):
+    from pypy.module.micronumpy.interp_numarray import BaseArray
     if (is_rec_type and space.isinstance_w(w_elem, space.w_tuple)):
         return True
-    if space.issequence_w(w_elem):
+    if (space.isinstance_w(w_elem, space.w_tuple) or
+        isinstance(w_elem, BaseArray) or    
+        space.isinstance_w(w_elem, space.w_list)):
         return False
     return True
 
diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py
--- a/pypy/module/micronumpy/test/test_numarray.py
+++ b/pypy/module/micronumpy/test/test_numarray.py
@@ -193,6 +193,19 @@
         assert _to_coords(5, 'F') == [1, 2, 0]
         assert _to_coords(13, 'F') == [1, 0, 2]
 
+    def test_find_shape(self):
+        from pypy.module.micronumpy.strides import find_shape_and_elems
+
+        space = self.space
+        shape, elems = find_shape_and_elems(space,
+                                            space.newlist([space.wrap("a"),
+                                                           space.wrap("b")]),
+                                            None)
+        assert shape == [2]
+        assert space.str_w(elems[0]) == "a"
+        assert space.str_w(elems[1]) == "b"
+        
+
 class AppTestNumArray(BaseNumpyAppTest):
     def w_CustomIndexObject(self, index):
         class CustomIndexObject(object):
diff --git a/pypy/module/test_lib_pypy/ctypes_tests/test_pointers.py b/pypy/module/test_lib_pypy/ctypes_tests/test_pointers.py
--- a/pypy/module/test_lib_pypy/ctypes_tests/test_pointers.py
+++ b/pypy/module/test_lib_pypy/ctypes_tests/test_pointers.py
@@ -253,3 +253,8 @@
         TwoOutArgs(a, byref(b), c, byref(d))
         assert b.value == 7
         assert d.value == 11
+
+    def test_byref_cannot_be_bound(self):
+        class A(object):
+            _byref = byref
+        A._byref(c_int(5))
diff --git a/pypy/objspace/flow/operation.py b/pypy/objspace/flow/operation.py
--- a/pypy/objspace/flow/operation.py
+++ b/pypy/objspace/flow/operation.py
@@ -218,7 +218,6 @@
     ('inplace_xor',     inplace_xor),
     ('iter',            iter),
     ('next',            next),
-    ('next',            __builtin__.next),
     ('get',             get),
     ('set',             set),
     ('delete',          delete),
@@ -237,7 +236,9 @@
     ('div_ovf',         div_ovf),
     ('mod_ovf',         mod_ovf),
     ('lshift_ovf',      lshift_ovf),
-    ]
+]
+if hasattr(__builtin__, 'next'):
+    Table.append(('next', __builtin__.next))
 
 def setup():
     # insert all operators
diff --git a/pypy/objspace/std/celldict.py b/pypy/objspace/std/celldict.py
--- a/pypy/objspace/std/celldict.py
+++ b/pypy/objspace/std/celldict.py
@@ -4,7 +4,7 @@
 """
 
 from pypy.interpreter.baseobjspace import W_Root
-from pypy.objspace.std.dictmultiobject import IteratorImplementation
+from pypy.objspace.std.dictmultiobject import create_iterator_classes
 from pypy.objspace.std.dictmultiobject import DictStrategy, _never_equal_to_string
 from pypy.objspace.std.dictmultiobject import ObjectDictStrategy
 from pypy.rlib import jit, rerased
@@ -124,9 +124,6 @@
         w_res = self.getdictvalue_no_unwrapping(w_dict, key)
         return unwrap_cell(w_res)
 
-    def iter(self, w_dict):
-        return ModuleDictIteratorImplementation(self.space, self, w_dict)
-
     def w_keys(self, w_dict):
         space = self.space
         l = self.unerase(w_dict.dstorage).keys()
@@ -161,15 +158,15 @@
         w_dict.strategy = strategy
         w_dict.dstorage = strategy.erase(d_new)
 
-class ModuleDictIteratorImplementation(IteratorImplementation):
-    def __init__(self, space, strategy, dictimplementation):
-        IteratorImplementation.__init__(
-            self, space, strategy, dictimplementation)
-        dict_w = strategy.unerase(dictimplementation.dstorage)
-        self.iterator = dict_w.iteritems()
+    def getiterkeys(self, w_dict):
+        return self.unerase(w_dict.dstorage).iterkeys()
+    def getitervalues(self, w_dict):
+        return self.unerase(w_dict.dstorage).itervalues()
+    def getiteritems(self, w_dict):
+        return self.unerase(w_dict.dstorage).iteritems()
+    def wrapkey(space, key):
+        return space.wrap(key)
+    def wrapvalue(space, value):
+        return unwrap_cell(value)
 
-    def next_entry(self):
-        for key, cell in self.iterator:
-            return (self.space.wrap(key), unwrap_cell(cell))
-        else:
-            return None, None
+create_iterator_classes(ModuleDictStrategy)
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
@@ -7,8 +7,10 @@
 from pypy.interpreter.argument import Signature
 from pypy.interpreter.error import OperationError, operationerrfmt
 
-from pypy.rlib.objectmodel import r_dict, we_are_translated, specialize
+from pypy.rlib.objectmodel import r_dict, we_are_translated, specialize,\
+     newlist_hint
 from pypy.rlib.debug import mark_dict_non_null
+from pypy.tool.sourcetools import func_with_new_name
 
 from pypy.rlib import rerased
 from pypy.rlib import jit
@@ -111,7 +113,7 @@
     dict_methods = "setitem setitem_str getitem \
                     getitem_str delitem length \
                     clear w_keys values \
-                    items iter setdefault \
+                    items iterkeys itervalues iteritems setdefault \
                     popitem listview_str listview_int".split()
 
     def make_method(method):
@@ -120,6 +122,9 @@
         f.func_name = method
         return f
 
+    def view_as_kwargs(self):
+        return self.strategy.view_as_kwargs(self)
+
     for method in dict_methods:
         setattr(W_DictMultiObject, method, make_method(method))
 
@@ -134,30 +139,30 @@
         raise NotImplementedError
 
     def w_keys(self, w_dict):
-        iterator = self.iter(w_dict)
-        result = []
+        iterator = self.iterkeys(w_dict)
+        result = newlist_hint(self.length(w_dict))
         while 1:
-            w_key, w_value = iterator.next()
+            w_key = iterator.next_key()
             if w_key is not None:
                 result.append(w_key)
             else:
                 return self.space.newlist(result)
 
     def values(self, w_dict):
-        iterator = self.iter(w_dict)
-        result = []
+        iterator = self.itervalues(w_dict)
+        result = newlist_hint(self.length(w_dict))
         while 1:
-            w_key, w_value = iterator.next()
+            w_value = iterator.next_value()
             if w_value is not None:
                 result.append(w_value)
             else:
                 return result
 
     def items(self, w_dict):
-        iterator = self.iter(w_dict)
-        result = []
+        iterator = self.iteritems(w_dict)
+        result = newlist_hint(self.length(w_dict))
         while 1:
-            w_key, w_value = iterator.next()
+            w_key, w_value = iterator.next_item()
             if w_key is not None:
                 result.append(self.space.newtuple([w_key, w_value]))
             else:
@@ -169,8 +174,8 @@
         # will take longer and longer.  But all interesting strategies
         # provide a better one.
         space = self.space
-        iterator = self.iter(w_dict)
-        w_key, w_value = iterator.next()
+        iterator = self.iteritems(w_dict)
+        w_key, w_value = iterator.next_item()
         self.delitem(w_dict, w_key)
         return (w_key, w_value)
 
@@ -271,9 +276,6 @@
     def length(self, w_dict):
         return 0
 
-    def iter(self, w_dict):
-        return EmptyIteratorImplementation(self.space, self, w_dict)
-
     def clear(self, w_dict):
         return
 
@@ -283,31 +285,32 @@
     def view_as_kwargs(self, w_dict):
         return ([], [])
 
-registerimplementation(W_DictMultiObject)
+    # ---------- iterator interface ----------------
 
-# DictImplementation lattice
-# XXX fix me
+    def getiterkeys(self, w_dict):
+        return iter([None])
+    getitervalues = getiterkeys
+    def getiteritems(self, w_dict):
+        return iter([(None, None)])
 
 # Iterator Implementation base classes
 
-class IteratorImplementation(object):
-    def __init__(self, space, strategy, implementation):
-        self.space = space
-        self.strategy = strategy
-        self.dictimplementation = implementation
-        self.len = implementation.length()
-        self.pos = 0
-
+def _new_next(TP):
+    if TP == 'key' or TP == 'value':
+        EMPTY = None
+    else:
+        EMPTY = None, None
+    
     def next(self):
         if self.dictimplementation is None:
-            return None, None
+            return EMPTY
         if self.len != self.dictimplementation.length():
             self.len = -1   # Make this error state sticky
             raise OperationError(self.space.w_RuntimeError,
                      self.space.wrap("dictionary changed size during iteration"))
         # look for the next entry
         if self.pos < self.len:
-            result = self.next_entry()
+            result = getattr(self, 'next_' + TP + '_entry')()
             self.pos += 1
             if self.strategy is self.dictimplementation.strategy:
                 return result      # common case
@@ -316,6 +319,8 @@
                 # length of the dict.  The (key, value) pair in 'result'
                 # might be out-of-date.  We try to explicitly look up
                 # the key in the dict.
+                if TP == 'key' or TP == 'value':
+                    return result
                 w_key = result[0]
                 w_value = self.dictimplementation.getitem(w_key)
                 if w_value is None:
@@ -325,22 +330,96 @@
                 return (w_key, w_value)
         # no more entries
         self.dictimplementation = None
-        return None, None
+        return EMPTY
+    return func_with_new_name(next, 'next_' + TP)
 
-    def next_entry(self):
-        """ Purely abstract method
-        """
-        raise NotImplementedError
+class BaseIteratorImplementation(object):
+    def __init__(self, space, strategy, implementation):
+        self.space = space
+        self.strategy = strategy
+        self.dictimplementation = implementation
+        self.len = implementation.length()
+        self.pos = 0
 
     def length(self):
         if self.dictimplementation is not None:
             return self.len - self.pos
         return 0
 
-class EmptyIteratorImplementation(IteratorImplementation):
-    def next(self):
-        return (None, None)
+class BaseKeyIterator(BaseIteratorImplementation):
+    next_key = _new_next('key')
 
+class BaseValueIterator(BaseIteratorImplementation):
+    next_value = _new_next('value')
+
+class BaseItemIterator(BaseIteratorImplementation):
+    next_item = _new_next('item')
+
+def create_iterator_classes(dictimpl, override_next_item=None):
+    if not hasattr(dictimpl, 'wrapkey'):
+        wrapkey = lambda space, key : key
+    else:
+        wrapkey = dictimpl.wrapkey.im_func
+    if not hasattr(dictimpl, 'wrapvalue'):
+        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)
+            BaseIteratorImplementation.__init__(self, space, strategy, impl)
+
+        def next_key_entry(self):
+            for key in self.iterator:
+                return wrapkey(self.space, key)
+            else:
+                return None
+
+    class IterClassValues(BaseValueIterator):
+        def __init__(self, space, strategy, impl):
+            self.iterator = strategy.getitervalues(impl)
+            BaseIteratorImplementation.__init__(self, space, strategy, impl)
+
+        def next_value_entry(self):
+            for value in self.iterator:
+                return wrapvalue(self.space, value)
+            else:
+                return None
+
+    class IterClassItems(BaseItemIterator):
+        def __init__(self, space, strategy, impl):
+            self.iterator = strategy.getiteritems(impl)
+            BaseIteratorImplementation.__init__(self, space, strategy, impl)
+
+        if override_next_item is not None:
+            next_item_entry = override_next_item
+        else:
+            def next_item_entry(self):
+                for key, value in self.iterator:
+                    return (wrapkey(self.space, key),
+                            wrapvalue(self.space, value))
+                else:
+                    return None, None
+
+    def iterkeys(self, w_dict):
+        return IterClassKeys(self.space, self, w_dict)
+
+    def itervalues(self, w_dict):
+        return IterClassValues(self.space, self, w_dict)
+
+    def iteritems(self, w_dict):
+        return IterClassItems(self.space, self, w_dict)
+    dictimpl.iterkeys = iterkeys
+    dictimpl.itervalues = itervalues
+    dictimpl.iteritems = iteritems
+
+create_iterator_classes(EmptyDictStrategy)
+
+registerimplementation(W_DictMultiObject)
+
+# DictImplementation lattice
+# XXX fix me
 
 
 # concrete subclasses of the above
@@ -447,6 +526,15 @@
         w_dict.strategy = strategy
         w_dict.dstorage = strategy.erase(d_new)
 
+    # --------------- iterator interface -----------------
+
+    def getiterkeys(self, w_dict):
+        return self.unerase(w_dict.dstorage).iterkeys()
+    def getitervalues(self, w_dict):
+        return self.unerase(w_dict.dstorage).itervalues()
+    def getiteritems(self, w_dict):
+        return self.unerase(w_dict.dstorage).iteritems()
+
 class ObjectDictStrategy(AbstractTypedStrategy, DictStrategy):
 
     erase, unerase = rerased.new_erasing_pair("object")
@@ -470,12 +558,10 @@
     def _never_equal_to(self, w_lookup_type):
         return False
 
-    def iter(self, w_dict):
-        return ObjectIteratorImplementation(self.space, self, w_dict)
-
     def w_keys(self, w_dict):
         return self.space.newlist(self.unerase(w_dict.dstorage).keys())
 
+create_iterator_classes(ObjectDictStrategy)
 
 class StringDictStrategy(AbstractTypedStrategy, DictStrategy):
 
@@ -520,12 +606,12 @@
     def listview_str(self, w_dict):
         return self.unerase(w_dict.dstorage).keys()
 
-    def iter(self, w_dict):
-        return StrIteratorImplementation(self.space, self, w_dict)
-
     def w_keys(self, w_dict):
         return self.space.newlist_str(self.listview_str(w_dict))
 
+    def wrapkey(space, key):
+        return space.wrap(key)
+
     @jit.look_inside_iff(lambda self, w_dict:
                          w_dict_unrolling_heuristic(w_dict))
     def view_as_kwargs(self, w_dict):
@@ -540,37 +626,8 @@
             i += 1
         return keys, values
 
-class _WrappedIteratorMixin(object):
-    _mixin_ = True
+create_iterator_classes(StringDictStrategy)
 
-    def __init__(self, space, strategy, dictimplementation):
-        IteratorImplementation.__init__(self, space, strategy, dictimplementation)
-        self.iterator = strategy.unerase(dictimplementation.dstorage).iteritems()
-
-    def next_entry(self):
-        # note that this 'for' loop only runs once, at most
-        for key, w_value in self.iterator:
-            return self.space.wrap(key), w_value
-        else:
-            return None, None
-
-class _UnwrappedIteratorMixin:
-    _mixin_ = True
-
-    def __init__(self, space, strategy, dictimplementation):
-        IteratorImplementation.__init__(self, space, strategy, dictimplementation)
-        self.iterator = strategy.unerase(dictimplementation.dstorage).iteritems()
-
-    def next_entry(self):
-        # note that this 'for' loop only runs once, at most
-        for w_key, w_value in self.iterator:
-            return w_key, w_value
-        else:
-            return None, None
-
-
-class StrIteratorImplementation(_WrappedIteratorMixin, IteratorImplementation):
-    pass
 
 class IntDictStrategy(AbstractTypedStrategy, DictStrategy):
     erase, unerase = rerased.new_erasing_pair("int")
@@ -598,19 +655,15 @@
                 space.is_w(w_lookup_type, space.w_unicode)
                 )
 
-    def iter(self, w_dict):
-        return IntIteratorImplementation(self.space, self, w_dict)
-
     def listview_int(self, w_dict):
         return self.unerase(w_dict.dstorage).keys()
 
+    def wrapkey(space, key):
+        return space.wrap(key)
+
     # XXX there is no space.newlist_int yet to implement w_keys more efficiently
 
-class IntIteratorImplementation(_WrappedIteratorMixin, IteratorImplementation):
-    pass
-
-class ObjectIteratorImplementation(_UnwrappedIteratorMixin, IteratorImplementation):
-    pass
+create_iterator_classes(IntDictStrategy)
 
 init_signature = Signature(['seq_or_map'], None, 'kwargs')
 init_defaults = [None]
@@ -636,9 +689,9 @@
                 w_dict.setitem(w_key, w_value)
 
 def update1_dict_dict(space, w_dict, w_data):
-    iterator = w_data.iter()
+    iterator = w_data.iteritems()
     while 1:
-        w_key, w_value = iterator.next()
+        w_key, w_value = iterator.next_item()
         if w_key is None:
             break
         w_dict.setitem(w_key, w_value)
@@ -686,7 +739,7 @@
     return space.newbool(w_dict.getitem(w_key) is not None)
 
 def iter__DictMulti(space, w_dict):
-    return W_DictMultiIterObject(space, w_dict.iter(), KEYSITER)
+    return W_DictMultiIterKeysObject(space, w_dict.iterkeys())
 
 def eq__DictMulti_DictMulti(space, w_left, w_right):
     if space.is_w(w_left, w_right):
@@ -694,9 +747,9 @@
 
     if w_left.length() != w_right.length():
         return space.w_False
-    iteratorimplementation = w_left.iter()
+    iteratorimplementation = w_left.iteritems()
     while 1:
-        w_key, w_val = iteratorimplementation.next()
+        w_key, w_val = iteratorimplementation.next_item()
         if w_key is None:
             break
         w_rightval = w_right.getitem(w_key)
@@ -711,9 +764,9 @@
     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.iter()
+    iteratorimplementation = w_a.iteritems()
     while 1:
-        w_key, w_val = iteratorimplementation.next()
+        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)):
@@ -768,13 +821,13 @@
     return W_DictViewValuesObject(space, w_self)
 
 def dict_iteritems__DictMulti(space, w_self):
-    return W_DictMultiIterObject(space, w_self.iter(), ITEMSITER)
+    return W_DictMultiIterItemsObject(space, w_self.iteritems())
 
 def dict_iterkeys__DictMulti(space, w_self):
-    return W_DictMultiIterObject(space, w_self.iter(), KEYSITER)
+    return W_DictMultiIterKeysObject(space, w_self.iterkeys())
 
 def dict_itervalues__DictMulti(space, w_self):
-    return W_DictMultiIterObject(space, w_self.iter(), VALUESITER)
+    return W_DictMultiIterValuesObject(space, w_self.itervalues())
 
 def dict_clear__DictMulti(space, w_self):
     w_self.clear()
@@ -818,38 +871,73 @@
 # Iteration
 
 
-KEYSITER = 0
-ITEMSITER = 1
-VALUESITER = 2
-
-class W_DictMultiIterObject(W_Object):
+class W_DictMultiIterKeysObject(W_Object):
     from pypy.objspace.std.dicttype import dictiter_typedef as typedef
 
-    _immutable_fields_ = ["iteratorimplementation", "itertype"]
+    _immutable_fields_ = ["iteratorimplementation"]
 
-    def __init__(w_self, space, iteratorimplementation, itertype):
+    ignore_for_isinstance_cache = True
+
+    def __init__(w_self, space, iteratorimplementation):
         w_self.space = space
         w_self.iteratorimplementation = iteratorimplementation
-        w_self.itertype = itertype
 
-registerimplementation(W_DictMultiIterObject)
+registerimplementation(W_DictMultiIterKeysObject)
 
-def iter__DictMultiIterObject(space, w_dictiter):
+class W_DictMultiIterValuesObject(W_Object):
+    from pypy.objspace.std.dicttype import dictiter_typedef as typedef
+
+    _immutable_fields_ = ["iteratorimplementation"]
+
+    ignore_for_isinstance_cache = True
+
+    def __init__(w_self, space, iteratorimplementation):
+        w_self.space = space
+        w_self.iteratorimplementation = iteratorimplementation
+
+registerimplementation(W_DictMultiIterValuesObject)
+
+class W_DictMultiIterItemsObject(W_Object):
+    from pypy.objspace.std.dicttype import dictiter_typedef as typedef
+
+    _immutable_fields_ = ["iteratorimplementation"]
+
+    ignore_for_isinstance_cache = True
+
+    def __init__(w_self, space, iteratorimplementation):
+        w_self.space = space
+        w_self.iteratorimplementation = iteratorimplementation
+
+registerimplementation(W_DictMultiIterItemsObject)
+
+def iter__DictMultiIterKeysObject(space, w_dictiter):
     return w_dictiter
 
-def next__DictMultiIterObject(space, w_dictiter):
+def next__DictMultiIterKeysObject(space, w_dictiter):
     iteratorimplementation = w_dictiter.iteratorimplementation
-    w_key, w_value = iteratorimplementation.next()
+    w_key = iteratorimplementation.next_key()
     if w_key is not None:
-        itertype = w_dictiter.itertype
-        if itertype == KEYSITER:
-            return w_key
-        elif itertype == VALUESITER:
-            return w_value
-        elif itertype == ITEMSITER:
-            return space.newtuple([w_key, w_value])
-        else:
-            assert 0, "should be unreachable"
+        return w_key
+    raise OperationError(space.w_StopIteration, space.w_None)
+
+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)
 
 # ____________________________________________________________
@@ -884,7 +972,6 @@
 
 def all_contained_in(space, w_dictview, w_otherview):
     w_iter = space.iter(w_dictview)
-    assert isinstance(w_iter, W_DictMultiIterObject)
 
     while True:
         try:
diff --git a/pypy/objspace/std/dictproxyobject.py b/pypy/objspace/std/dictproxyobject.py
--- a/pypy/objspace/std/dictproxyobject.py
+++ b/pypy/objspace/std/dictproxyobject.py
@@ -1,6 +1,6 @@
 from pypy.objspace.std.model import registerimplementation, W_Object
 from pypy.objspace.std.register_all import register_all
-from pypy.objspace.std.dictmultiobject import W_DictMultiObject, IteratorImplementation
+from pypy.objspace.std.dictmultiobject import W_DictMultiObject, create_iterator_classes
 from pypy.objspace.std.dictmultiobject import DictStrategy
 from pypy.objspace.std.typeobject import unwrap_cell
 from pypy.interpreter.error import OperationError, operationerrfmt
@@ -71,9 +71,6 @@
     def length(self, w_dict):
         return len(self.unerase(w_dict.dstorage).dict_w)
 
-    def iter(self, w_dict):
-        return DictProxyIteratorImplementation(self.space, self, w_dict)
-
     def keys(self, w_dict):
         space = self.space
         return space.newlist_str(self.unerase(w_dict.dstorage).dict_w.keys())
@@ -96,15 +93,15 @@
         w_type.dict_w.clear()
         w_type.mutated(None)
 
-class DictProxyIteratorImplementation(IteratorImplementation):
-    def __init__(self, space, strategy, dictimplementation):
-        IteratorImplementation.__init__(
-            self, space, strategy, dictimplementation)
-        w_type = strategy.unerase(dictimplementation.dstorage)
-        self.iterator = w_type.dict_w.iteritems()
+    def getiterkeys(self, w_dict):
+        return self.unerase(w_dict.dstorage).dict_w.iterkeys()
+    def getitervalues(self, w_dict):
+        return self.unerase(w_dict.dstorage).dict_w.itervalues()
+    def getiteritems(self, w_dict):
+        return self.unerase(w_dict.dstorage).dict_w.iteritems()
+    def wrapkey(space, key):
+        return space.wrap(key)
+    def wrapvalue(space, value):
+        return unwrap_cell(space, value)
 
-    def next_entry(self):
-        for key, w_value in self.iterator:
-            return (self.space.wrap(key), unwrap_cell(self.space, w_value))
-        else:
-            return (None, None)
+create_iterator_classes(DictProxyStrategy)
diff --git a/pypy/objspace/std/identitydict.py b/pypy/objspace/std/identitydict.py
--- a/pypy/objspace/std/identitydict.py
+++ b/pypy/objspace/std/identitydict.py
@@ -5,8 +5,7 @@
 from pypy.rlib.debug import mark_dict_non_null
 from pypy.objspace.std.dictmultiobject import (AbstractTypedStrategy,
                                                DictStrategy,
-                                               IteratorImplementation,
-                                               _UnwrappedIteratorMixin)
+                                               create_iterator_classes)
 
 
 # this strategy is selected by EmptyDictStrategy.switch_to_correct_strategy
@@ -77,12 +76,7 @@
     def _never_equal_to(self, w_lookup_type):
         return False
 
-    def iter(self, w_dict):
-        return IdentityDictIteratorImplementation(self.space, self, w_dict)
-
     def w_keys(self, w_dict):
         return self.space.newlist(self.unerase(w_dict.dstorage).keys())
 
-
-class IdentityDictIteratorImplementation(_UnwrappedIteratorMixin, IteratorImplementation):
-    pass
+create_iterator_classes(IdentityDictStrategy)
diff --git a/pypy/objspace/std/kwargsdict.py b/pypy/objspace/std/kwargsdict.py
--- a/pypy/objspace/std/kwargsdict.py
+++ b/pypy/objspace/std/kwargsdict.py
@@ -3,8 +3,8 @@
 
 from pypy.rlib import rerased, jit
 from pypy.objspace.std.dictmultiobject import (DictStrategy,
+                                               create_iterator_classes,
                                                EmptyDictStrategy,
-                                               IteratorImplementation,
                                                ObjectDictStrategy,
                                                StringDictStrategy)
 
@@ -39,9 +39,6 @@
     def _never_equal_to(self, w_lookup_type):
         return False
 
-    def iter(self, w_dict):
-        return KwargsDictIterator(self.space, self, w_dict)
-
     def w_keys(self, w_dict):
         return self.space.newlist([self.space.wrap(key) for key in self.unerase(w_dict.dstorage)[0]])
 
@@ -157,19 +154,24 @@
         keys, values_w = self.unerase(w_dict.dstorage)
         return keys[:], values_w[:] # copy to make non-resizable
 
+    def getiterkeys(self, w_dict):
+        return iter(self.unerase(w_dict.dstorage)[0])
+    def getitervalues(self, w_dict):
+        return iter(self.unerase(w_dict.dstorage)[1])
+    def getiteritems(self, w_dict):
+        keys = self.unerase(w_dict.dstorage)[0]
+        return iter(range(len(keys)))
+    def wrapkey(space, key):
+        return space.wrap(key)
 
-class KwargsDictIterator(IteratorImplementation):
-    def __init__(self, space, strategy, dictimplementation):
-        IteratorImplementation.__init__(self, space, strategy, dictimplementation)
-        keys, values_w = strategy.unerase(self.dictimplementation.dstorage)
-        self.iterator = iter(range(len(keys)))
-        # XXX this potentially leaks
-        self.keys = keys
-        self.values_w = values_w
+def next_item(self):
+    strategy = self.strategy
+    assert isinstance(strategy, KwargsDictStrategy)
+    for i in self.iterator:
+        keys, values_w = strategy.unerase(
+            self.dictimplementation.dstorage)
+        return self.space.wrap(keys[i]), values_w[i]
+    else:
+        return None, None
 
-    def next_entry(self):
-        # note that this 'for' loop only runs once, at most
-        for i in self.iterator:
-            return self.space.wrap(self.keys[i]), self.values_w[i]
-        else:
-            return None, None
+create_iterator_classes(KwargsDictStrategy, override_next_item=next_item)
diff --git a/pypy/objspace/std/mapdict.py b/pypy/objspace/std/mapdict.py
--- a/pypy/objspace/std/mapdict.py
+++ b/pypy/objspace/std/mapdict.py
@@ -5,7 +5,7 @@
 
 from pypy.interpreter.baseobjspace import W_Root
 from pypy.objspace.std.dictmultiobject import W_DictMultiObject, DictStrategy, ObjectDictStrategy
-from pypy.objspace.std.dictmultiobject import IteratorImplementation
+from pypy.objspace.std.dictmultiobject import BaseKeyIterator, BaseValueIterator, BaseItemIterator
 from pypy.objspace.std.dictmultiobject import _never_equal_to_string
 from pypy.objspace.std.objectobject import W_ObjectObject
 from pypy.objspace.std.typeobject import TypeCell
@@ -674,9 +674,6 @@
             res += 1
         return res
 
-    def iter(self, w_dict):
-        return MapDictIteratorImplementation(self.space, self, w_dict)
-
     def clear(self, w_dict):
         w_obj = self.unerase(w_dict.dstorage)
         new_obj = w_obj._get_mapdict_map().remove_dict_entries(w_obj)
@@ -694,32 +691,83 @@
 
     # XXX could implement a more efficient w_keys based on space.newlist_str
 
+    def iterkeys(self, w_dict):
+        return MapDictIteratorKeys(self.space, self, w_dict)
+    def itervalues(self, w_dict):
+        return MapDictIteratorValues(self.space, self, w_dict)
+    def iteritems(self, w_dict):
+        return MapDictIteratorItems(self.space, self, w_dict)
+    
+
 def materialize_r_dict(space, obj, dict_w):
     map = obj._get_mapdict_map()
     new_obj = map.materialize_r_dict(space, obj, dict_w)
     _become(obj, new_obj)
 
-class MapDictIteratorImplementation(IteratorImplementation):
-    def __init__(self, space, strategy, dictimplementation):
-        IteratorImplementation.__init__(
-            self, space, strategy, dictimplementation)
-        w_obj = strategy.unerase(dictimplementation.dstorage)
-        self.w_obj = w_obj
-        self.orig_map = self.curr_map = w_obj._get_mapdict_map()
+class MapDictIteratorKeys(BaseKeyIterator):
+     def __init__(self, space, strategy, dictimplementation):
+         BaseKeyIterator.__init__(
+             self, space, strategy, dictimplementation)
+         w_obj = strategy.unerase(dictimplementation.dstorage)
+         self.w_obj = w_obj
+         self.orig_map = self.curr_map = w_obj._get_mapdict_map()
 
-    def next_entry(self):
-        implementation = self.dictimplementation
-        assert isinstance(implementation.strategy, MapDictStrategy)
-        if self.orig_map is not self.w_obj._get_mapdict_map():
-            return None, None
-        if self.curr_map:
-            curr_map = self.curr_map.search(DICT)
-            if curr_map:
-                self.curr_map = curr_map.back
-                attr = curr_map.selector[0]
-                w_attr = self.space.wrap(attr)
-                return w_attr, self.w_obj.getdictvalue(self.space, attr)
-        return None, None
+     def next_key_entry(self):
+         implementation = self.dictimplementation
+         assert isinstance(implementation.strategy, MapDictStrategy)
+         if self.orig_map is not self.w_obj._get_mapdict_map():
+             return None
+         if self.curr_map:
+             curr_map = self.curr_map.search(DICT)
+             if curr_map:
+                 self.curr_map = curr_map.back
+                 attr = curr_map.selector[0]
+                 w_attr = self.space.wrap(attr)
+                 return w_attr
+         return None
+
+class MapDictIteratorValues(BaseValueIterator):
+     def __init__(self, space, strategy, dictimplementation):
+         BaseValueIterator.__init__(
+             self, space, strategy, dictimplementation)
+         w_obj = strategy.unerase(dictimplementation.dstorage)
+         self.w_obj = w_obj
+         self.orig_map = self.curr_map = w_obj._get_mapdict_map()
+
+     def next_value_entry(self):
+         implementation = self.dictimplementation
+         assert isinstance(implementation.strategy, MapDictStrategy)
+         if self.orig_map is not self.w_obj._get_mapdict_map():
+             return None
+         if self.curr_map:
+             curr_map = self.curr_map.search(DICT)
+             if curr_map:
+                 self.curr_map = curr_map.back
+                 attr = curr_map.selector[0]
+                 return self.w_obj.getdictvalue(self.space, attr)
+         return None
+
+class MapDictIteratorItems(BaseItemIterator):
+     def __init__(self, space, strategy, dictimplementation):
+         BaseItemIterator.__init__(
+             self, space, strategy, dictimplementation)
+         w_obj = strategy.unerase(dictimplementation.dstorage)
+         self.w_obj = w_obj
+         self.orig_map = self.curr_map = w_obj._get_mapdict_map()
+
+     def next_item_entry(self):
+         implementation = self.dictimplementation
+         assert isinstance(implementation.strategy, MapDictStrategy)
+         if self.orig_map is not self.w_obj._get_mapdict_map():
+             return None, None
+         if self.curr_map:
+             curr_map = self.curr_map.search(DICT)
+             if curr_map:
+                 self.curr_map = curr_map.back
+                 attr = curr_map.selector[0]
+                 w_attr = self.space.wrap(attr)
+                 return w_attr, self.w_obj.getdictvalue(self.space, attr)
+         return None, None
 
 # ____________________________________________________________
 # Magic caching
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
@@ -101,7 +101,9 @@
             tupleobject.W_TupleObject: [],
             listobject.W_ListObject: [],
             dictmultiobject.W_DictMultiObject: [],
-            dictmultiobject.W_DictMultiIterObject: [],
+            dictmultiobject.W_DictMultiIterKeysObject: [],
+            dictmultiobject.W_DictMultiIterValuesObject: [],
+            dictmultiobject.W_DictMultiIterItemsObject: [],
             stringobject.W_StringObject: [],
             bytearrayobject.W_BytearrayObject: [],
             typeobject.W_TypeObject: [],
@@ -127,7 +129,9 @@
 
         self.imported_but_not_registered = {
             dictmultiobject.W_DictMultiObject: True, # XXXXXX
-            dictmultiobject.W_DictMultiIterObject: True,
+            dictmultiobject.W_DictMultiIterKeysObject: True,
+            dictmultiobject.W_DictMultiIterValuesObject: True,
+            dictmultiobject.W_DictMultiIterItemsObject: True,
             listobject.W_ListObject: True,
             stringobject.W_StringObject: True,
             tupleobject.W_TupleObject: True,
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
@@ -453,6 +453,8 @@
         class E(dict):
             pass
         assert isinstance(D.fromkeys([1, 2]), E)
+        assert dict.fromkeys({"a": 2, "b": 3}) == {"a": None, "b": None}
+        assert dict.fromkeys({"a": 2, 1: 3}) == {"a": None, 1: None}
 
     def test_str_uses_repr(self):
         class D(dict):
@@ -1046,10 +1048,10 @@
 
     def test_iter(self):
         self.fill_impl()
-        iteratorimplementation = self.impl.iter()
+        iteratorimplementation = self.impl.iteritems()
         items = []
         while 1:
-            item = iteratorimplementation.next()
+            item = iteratorimplementation.next_item()
             if item == (None, None):
                 break
             items.append(item)
diff --git a/pypy/objspace/std/test/test_kwargsdict.py b/pypy/objspace/std/test/test_kwargsdict.py
--- a/pypy/objspace/std/test/test_kwargsdict.py
+++ b/pypy/objspace/std/test/test_kwargsdict.py
@@ -142,3 +142,9 @@
         d = f()
         assert "EmptyKwargsDictStrategy" in self.get_strategy(d)
 
+    def test_iterator(self):
+        def f(**args):
+            return args
+
+        assert dict.fromkeys(f(a=2, b=3)) == {"a": None, "b": None}
+        assert sorted(f(a=2, b=3).itervalues()) == [2, 3]
diff --git a/pypy/rlib/runicode.py b/pypy/rlib/runicode.py
--- a/pypy/rlib/runicode.py
+++ b/pypy/rlib/runicode.py
@@ -47,12 +47,10 @@
 
 def raise_unicode_exception_decode(errors, encoding, msg, s,
                                    startingpos, endingpos):
-    assert isinstance(s, str)
     raise UnicodeDecodeError(encoding, s, startingpos, endingpos, msg)
 
 def raise_unicode_exception_encode(errors, encoding, msg, u,
                                    startingpos, endingpos):
-    assert isinstance(u, unicode)
     raise UnicodeEncodeError(encoding, u, startingpos, endingpos, msg)
 
 # ____________________________________________________________
diff --git a/pypy/rlib/test/test_objectmodel.py b/pypy/rlib/test/test_objectmodel.py
--- a/pypy/rlib/test/test_objectmodel.py
+++ b/pypy/rlib/test/test_objectmodel.py
@@ -427,7 +427,7 @@
     assert f.foo == 'foo'
     assert f(1, 'hello', 42) == (1, 'hello', 42)
     exc = py.test.raises(TypeError, "f(1, 2, 3)")
-    assert exc.value.message == "f argument number 2 must be of type <type 'str'>"
+    assert exc.value.message == "f argument 'b' must be of type <type 'str'>"
     py.test.raises(TypeError, "f('hello', 'world', 3)")
     
 
diff --git a/pypy/rpython/lltypesystem/rbuilder.py b/pypy/rpython/lltypesystem/rbuilder.py
--- a/pypy/rpython/lltypesystem/rbuilder.py
+++ b/pypy/rpython/lltypesystem/rbuilder.py
@@ -59,7 +59,7 @@
 
     @classmethod
     def ll_new(cls, init_size):
-        if init_size < 0 or init_size > MAX:
+        if init_size < 0:
             init_size = MAX
         ll_builder = lltype.malloc(cls.lowleveltype.TO)
         ll_builder.allocated = init_size
diff --git a/pypy/rpython/lltypesystem/rstr.py b/pypy/rpython/lltypesystem/rstr.py
--- a/pypy/rpython/lltypesystem/rstr.py
+++ b/pypy/rpython/lltypesystem/rstr.py
@@ -143,6 +143,13 @@
             s.chars[i] = cast_primitive(UniChar, value.chars[i])
         return s
 
+    def ll_decode_utf8(self, llvalue):
+        from pypy.rpython.annlowlevel import hlstr, llunicode
+        from pypy.rlib.runicode import str_decode_utf_8
+        value = hlstr(llvalue)
+        univalue, _ = str_decode_utf_8(value, len(value), 'strict')
+        return llunicode(univalue)
+
 class UnicodeRepr(BaseLLStringRepr, AbstractUnicodeRepr):
     lowleveltype = Ptr(UNICODE)
     basetype = basestring
@@ -187,6 +194,14 @@
             result.chars[i] = cast_primitive(Char, c)
         return result
 
+    @jit.elidable
+    def ll_encode_utf8(self, ll_s):
+        from pypy.rpython.annlowlevel import hlunicode, llstr
+        from pypy.rlib.runicode import unicode_encode_utf_8
+        s = hlunicode(ll_s)
+        bytes = unicode_encode_utf_8(s, len(s), 'strict')
+        return llstr(bytes)
+
 class CharRepr(AbstractCharRepr, StringRepr):
     lowleveltype = Char
 
diff --git a/pypy/rpython/ootypesystem/rstr.py b/pypy/rpython/ootypesystem/rstr.py
--- a/pypy/rpython/ootypesystem/rstr.py
+++ b/pypy/rpython/ootypesystem/rstr.py
@@ -60,6 +60,13 @@
             sb.ll_append_char(cast_primitive(UniChar, c))
         return sb.ll_build()
 
+    def ll_decode_utf8(self, llvalue):
+        from pypy.rpython.annlowlevel import hlstr, oounicode
+        from pypy.rlib.runicode import str_decode_utf_8
+        value = hlstr(llvalue)
+        univalue, _ = str_decode_utf_8(value, len(value), 'strict')
+        return oounicode(univalue)
+
 
 class UnicodeRepr(BaseOOStringRepr, AbstractUnicodeRepr):
     lowleveltype = ootype.Unicode
@@ -98,6 +105,13 @@
             sb.ll_append_char(cast_primitive(Char, c))
         return sb.ll_build()
 
+    def ll_encode_utf8(self, ll_s):
+        from pypy.rpython.annlowlevel import hlunicode, oostr
+        from pypy.rlib.runicode import unicode_encode_utf_8
+        s = hlunicode(ll_s)
+        bytes = unicode_encode_utf_8(s, len(s), 'strict')
+        return oostr(bytes)
+
 class CharRepr(AbstractCharRepr, StringRepr):
     lowleveltype = Char
 
diff --git a/pypy/rpython/rstr.py b/pypy/rpython/rstr.py
--- a/pypy/rpython/rstr.py
+++ b/pypy/rpython/rstr.py
@@ -309,6 +309,8 @@
             return hop.gendirectcall(self.ll.ll_str2unicode, v_self)
         elif encoding == 'latin-1':
             return hop.gendirectcall(self.ll_decode_latin1, v_self)
+        elif encoding == 'utf-8':
+            return hop.gendirectcall(self.ll_decode_utf8, v_self)
         else:
             raise TyperError("encoding %s not implemented" % (encoding, ))
 
@@ -340,6 +342,8 @@
             return hop.gendirectcall(self.ll_str, v_self)
         elif encoding == "latin-1":
             return hop.gendirectcall(self.ll_encode_latin1, v_self)
+        elif encoding == 'utf-8':
+            return hop.gendirectcall(self.ll_encode_utf8, v_self)
         else:
             raise TyperError("encoding %s not implemented" % (encoding, ))
 
diff --git a/pypy/rpython/test/test_runicode.py b/pypy/rpython/test/test_runicode.py
--- a/pypy/rpython/test/test_runicode.py
+++ b/pypy/rpython/test/test_runicode.py
@@ -98,9 +98,11 @@
         self.interpret_raises(UnicodeEncodeError, f, [1234])
 
     def test_unicode_encode(self):
-        def f(x):
-            y = u'xxx'
-            return (y + unichr(x)).encode('ascii') + y.encode('latin-1')
+        def f(n):
+            x = u'xxx' + unichr(n)
+            y = u'&#224;&#232;&#236;' + unichr(n)
+            z = u'&#32654;' + unichr(n)
+            return x.encode('ascii') + y.encode('latin-1') + z.encode('utf-8')
 
         assert self.ll_to_string(self.interpret(f, [38])) == f(38)
 
@@ -128,11 +130,14 @@
         assert self.interpret(f, [300, False]) == f(300, False)
 
     def test_unicode_decode(self):
-        def f(x):
-            y = 'xxx'
-            return (y + chr(x)).decode('ascii') + chr(x).decode("latin-1") 
+        strings = ['xxx', u'&#224;&#232;&#236;'.encode('latin-1'), u'&#32654;'.encode('utf-8')]
+        def f(n):
+            x = strings[n]
+            y = strings[n+1]
+            z = strings[n+2]
+            return x.decode('ascii') + y.decode('latin-1') + z.decode('utf-8')
 
-        assert self.ll_to_string(self.interpret(f, [38])) == f(38)
+        assert self.ll_to_string(self.interpret(f, [0])) == f(0)
 
     def test_unicode_decode_error(self):
         def f(x):
diff --git a/pypy/translator/sandbox/test/test_sandlib.py b/pypy/translator/sandbox/test/test_sandlib.py
--- a/pypy/translator/sandbox/test/test_sandlib.py
+++ b/pypy/translator/sandbox/test/test_sandlib.py
@@ -106,7 +106,7 @@
             pass
     
     def entry_point(argv):
-        fd = os.open("tcp://codespeak.net:80", os.O_RDONLY, 0777)
+        fd = os.open("tcp://pypy.org:80", os.O_RDONLY, 0777)
         os.write(fd, 'GET /\n')
         print os.read(fd, 30)
         return 0


More information about the pypy-commit mailing list