[pypy-commit] pypy reflex-support: merge default into branch

wlav noreply at buildbot.pypy.org
Wed Aug 29 00:01:28 CEST 2012


Author: Wim Lavrijsen <WLavrijsen at lbl.gov>
Branch: reflex-support
Changeset: r56914:a1be9c7e2489
Date: 2012-08-28 15:01 -0700
http://bitbucket.org/pypy/pypy/changeset/a1be9c7e2489/

Log:	merge default into branch

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/test/test_annrpython.py b/pypy/annotation/test/test_annrpython.py
--- a/pypy/annotation/test/test_annrpython.py
+++ b/pypy/annotation/test/test_annrpython.py
@@ -3829,7 +3829,7 @@
 
             def next(self):
                 return 1
-        
+
         def fn():
             s = 0
             for x in A():
@@ -3841,6 +3841,16 @@
         assert len(a.translator.graphs) == 3 # fn, __iter__, next
         assert isinstance(s, annmodel.SomeInteger)
 
+    def test_next_function(self):
+        def fn(n):
+            x = [0, 1, n]
+            i = iter(x)
+            return next(i) + next(i)
+
+        a = self.RPythonAnnotator()
+        s = a.build_types(fn, [int])
+        assert isinstance(s, annmodel.SomeInteger)
+
     def test_no_attr_on_common_exception_classes(self):
         for cls in [ValueError, Exception]:
             def fn():
diff --git a/pypy/conftest.py b/pypy/conftest.py
--- a/pypy/conftest.py
+++ b/pypy/conftest.py
@@ -19,6 +19,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/doc/windows.rst b/pypy/doc/windows.rst
--- a/pypy/doc/windows.rst
+++ b/pypy/doc/windows.rst
@@ -135,6 +135,10 @@
 the name of a valid gcc-derivative compiler, i.e. x86_64-w64-mingw32-gcc for the 64 bit
 compiler creating a 64 bit target.
 
+You probably want to set the CPATH, LIBRARY_PATH, and PATH environment variable to
+the header files, lib or dlls, and dlls respectively of the locally installed packages 
+if they are not in the mingw directory heirarchy. 
+
 libffi for the mingw compiler
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -175,7 +179,7 @@
 Since hacking on Pypy means running tests, you will need a way to specify
 the mingw compiler when hacking (as opposed to translating). As of
 March 2012, --cc is not a valid option for pytest.py. However if you set an
-environment variable CC it will allow you to choose a compiler.
+environment variable CC to the compliter exe, testing will use it.
 
 .. _'mingw32 build': http://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win32/Automated%20Builds
 .. _`mingw64 build`: http://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win64/Automated%20Builds
diff --git a/pypy/interpreter/argument.py b/pypy/interpreter/argument.py
--- a/pypy/interpreter/argument.py
+++ b/pypy/interpreter/argument.py
@@ -301,10 +301,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 - input_argcount)
-            if cnt < 0:
-                cnt = 0
-            kwds_mapping = [0] * cnt
+            kwds_mapping = [0] * (co_argcount - 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
@@ -831,6 +851,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.
@@ -851,7 +874,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/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
@@ -2,6 +2,12 @@
 #include <stdarg.h>
 #include <errno.h>
 
+#ifdef _WIN32
+#define DLLEXPORT __declspec(dllexport)
+#else
+#define DLLEXPORT
+#endif
+
 static char _testfunc0(char a, char b)
 {
     return a + b;
@@ -140,7 +146,22 @@
     return ptr->a1 + ptr->a2;
 }
 
-void *gettestfunc(int num)
+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;
     switch (num) {
@@ -165,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
@@ -326,13 +326,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/descroperation.py b/pypy/objspace/descroperation.py
--- a/pypy/objspace/descroperation.py
+++ b/pypy/objspace/descroperation.py
@@ -229,13 +229,15 @@
         return space.get_and_call_function(w_descr, w_obj, w_name)
 
     def is_true(space, w_obj):
-        method = "__nonzero__"
-        w_descr = space.lookup(w_obj, method)
+        w_descr = space.lookup(w_obj, "__nonzero__")
         if w_descr is None:
-            method = "__len__"
-            w_descr = space.lookup(w_obj, method)
+            w_descr = space.lookup(w_obj, "__len__")
             if w_descr is None:
                 return True
+            # call __len__
+            w_res = space.get_and_call_function(w_descr, w_obj)
+            return space._check_len_result(w_res) != 0
+        # call __nonzero__
         w_res = space.get_and_call_function(w_descr, w_obj)
         # more shortcuts for common cases
         if space.is_w(w_res, space.w_False):
@@ -245,11 +247,10 @@
         w_restype = space.type(w_res)
         # Note there is no check for bool here because the only possible
         # instances of bool are w_False and w_True, which are checked above.
-        if (space.is_w(w_restype, space.w_int) or
-            space.is_w(w_restype, space.w_long)):
+        if space.is_w(w_restype, space.w_int):
             return space.int_w(w_res) != 0
         else:
-            msg = "%s should return bool or integer" % (method,)
+            msg = "__nonzero__ should return bool or integer"
             raise OperationError(space.w_TypeError, space.wrap(msg))
 
     def nonzero(space, w_obj):
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
@@ -228,7 +228,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
@@ -110,7 +112,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):
@@ -119,6 +121,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))
 
@@ -133,30 +138,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:
@@ -168,8 +173,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)
 
@@ -268,9 +273,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
 
@@ -280,31 +282,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
@@ -313,6 +316,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:
@@ -322,22 +327,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
@@ -444,6 +523,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")
@@ -467,12 +555,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):
 
@@ -517,12 +603,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):
@@ -536,37 +622,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")
@@ -594,19 +651,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]
@@ -632,9 +685,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)
@@ -684,7 +737,7 @@
 dict_has_key__DictMulti_ANY = contains__DictMulti_ANY
 
 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):
@@ -692,9 +745,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)
@@ -709,9 +762,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)):
@@ -762,13 +815,13 @@
     return space.newlist(w_self.values())
 
 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_viewitems__DictMulti(space, w_self):
     return W_DictViewItemsObject(space, w_self)
@@ -821,38 +874,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)
 
 # ____________________________________________________________
@@ -887,7 +975,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
@@ -81,9 +81,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())
@@ -106,15 +103,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/listobject.py b/pypy/objspace/std/listobject.py
--- a/pypy/objspace/std/listobject.py
+++ b/pypy/objspace/std/listobject.py
@@ -512,10 +512,9 @@
         if is_W_IntObject(w_obj):
             start, step, length = self.unerase(w_list.lstorage)
             obj = self.unwrap(w_obj)
-            i = start
             if step > 0 and start <= obj <= start + (length - 1) * step and (start - obj) % step == 0:
                 return True
-            elif step < 0 and start + (length -1) * step <= obj <= start and (start - obj) % step == 0:
+            elif step < 0 and start + (length - 1) * step <= obj <= start and (start - obj) % step == 0:
                 return True
             else:
                 return False
@@ -555,7 +554,7 @@
         l = self.unerase(w_list.lstorage)
         start = l[0]
         step = l[1]
-        length  = l[2]
+        length = l[2]
         if wrap_items:
             r = [None] * length
         else:
@@ -581,9 +580,7 @@
 
     def getslice(self, w_list, start, stop, step, length):
         v = self.unerase(w_list.lstorage)
-        old_start = v[0]
         old_step = v[1]
-        old_length = v[2]
 
         new_start = self._getitem_unwrapped(w_list, start)
         new_step = old_step * step
@@ -595,7 +592,7 @@
             step = l[1]
             last_in_range = self._getitem_unwrapped(w_list, -1)
             if self.unwrap(w_item) - step == last_in_range:
-                new = self.erase((l[0],l[1],l[2]+1))
+                new = self.erase((l[0], l[1], l[2] + 1))
                 w_list.lstorage = new
                 return
 
@@ -715,13 +712,15 @@
 
     def contains(self, w_list, w_obj):
         if self.is_correct_type(w_obj):
-            obj = self.unwrap(w_obj)
+            return self._safe_contains(w_list, self.unwrap(w_obj))
+        return ListStrategy.contains(self, w_list, w_obj)
+
+    def _safe_contains(self, w_list, obj):
             l = self.unerase(w_list.lstorage)
             for i in l:
                 if i == obj:
                     return True
             return False
-        return ListStrategy.contains(self, w_list, w_obj)
 
     def length(self, w_list):
         return len(self.unerase(w_list.lstorage))
@@ -840,7 +839,7 @@
                 newsize = oldsize + delta
                 # XXX support this in rlist!
                 items += [self._none_value] * delta
-                lim = start+len2
+                lim = start + len2
                 i = newsize - 1
                 while i >= lim:
                     items[i] = items[i-delta]
@@ -867,7 +866,7 @@
                 # having to make a shallow copy in the case where
                 # the source and destination lists are the same list.
                 i = len2 - 1
-                start += i*step
+                start += i * step
                 while i >= 0:
                     items[start] = other_items[i]
                     start -= step
@@ -884,11 +883,11 @@
 
     def deleteslice(self, w_list, start, step, slicelength):
         items = self.unerase(w_list.lstorage)
-        if slicelength==0:
+        if slicelength == 0:
             return
 
         if step < 0:
-            start = start + step * (slicelength-1)
+            start = start + step * (slicelength - 1)
             step = -step
 
         if step == 1:
@@ -900,13 +899,13 @@
             i = start
 
             for discard in range(1, slicelength):
-                j = i+1
+                j = i + 1
                 i += step
                 while j < i:
                     items[j-discard] = items[j]
                     j += 1
 
-            j = i+1
+            j = i + 1
             while j < n:
                 items[j-slicelength] = items[j]
                 j += 1
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
@@ -676,9 +676,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)
@@ -696,32 +693,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
@@ -102,7 +102,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: [],
@@ -128,7 +130,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
@@ -454,6 +454,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):
@@ -1038,10 +1040,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
@@ -141,3 +141,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/objspace/test/test_descroperation.py b/pypy/objspace/test/test_descroperation.py
--- a/pypy/objspace/test/test_descroperation.py
+++ b/pypy/objspace/test/test_descroperation.py
@@ -658,7 +658,7 @@
         class X(object):
             def __len__(self): return 1L
             __nonzero__ = __len__
-        assert X()
+        raises(TypeError, bool, X())  # must return bool or int, not long
         del X.__nonzero__
         assert X()
 
@@ -668,6 +668,7 @@
             def __len__(self):
                 return sys.maxsize + 1
         raises(OverflowError, len, X())
+        raises(OverflowError, bool, X())
 
     def test_len_underflow(self):
         import sys
@@ -675,10 +676,12 @@
             def __len__(self):
                 return -1
         raises(ValueError, len, X())
+        raises(ValueError, bool, X())
         class Y(object):
             def __len__(self):
                 return -1L
         raises(ValueError, len, Y())
+        raises(ValueError, bool, Y())
 
     def test_len_custom__int__(self):
         class X(object):
@@ -691,8 +694,12 @@
 
         l = len(X(3.0))
         assert l == 3 and type(l) is int
+        assert X(3.0)
+        assert not X(0.0)
         l = len(X(X(2)))
         assert l == 2 and type(l) is int
+        assert X(X(2))
+        assert not X(X(0))
 
     def test_bool___contains__(self):
         class X(object):
diff --git a/pypy/rlib/libffi.py b/pypy/rlib/libffi.py
--- a/pypy/rlib/libffi.py
+++ b/pypy/rlib/libffi.py
@@ -1,3 +1,6 @@
+"""
+This whole file is DEPRECATED.  Use jit_libffi.py instead.
+"""
 from __future__ import with_statement
 
 from pypy.rpython.lltypesystem import rffi, lltype
diff --git a/pypy/rlib/objectmodel.py b/pypy/rlib/objectmodel.py
--- a/pypy/rlib/objectmodel.py
+++ b/pypy/rlib/objectmodel.py
@@ -108,7 +108,7 @@
 
 specialize = _Specialize()
 
-def enforceargs(*types, **kwds):
+def enforceargs(*types_, **kwds):
     """ Decorate a function with forcing of RPython-level types on arguments.
     None means no enforcing.
 
@@ -117,36 +117,64 @@
     typechecking by passing ``typecheck=False`` to @enforceargs.
     """
     typecheck = kwds.pop('typecheck', True)
-    if kwds:
-        raise TypeError, 'got an unexpected keyword argument: %s' % kwds.keys()
+    if types_ and kwds:
+        raise TypeError, 'Cannot mix positional arguments and keywords'
+
     if not typecheck:
         def decorator(f):
-            f._annenforceargs_ = types
+            f._annenforceargs_ = types_
             return f
         return decorator
     #
-    from pypy.annotation.signature import annotationoftype
-    from pypy.annotation.model import SomeObject
     def decorator(f):
         def get_annotation(t):
+            from pypy.annotation.signature import annotation
+            from pypy.annotation.model import SomeObject, SomeStringOrUnicode
             if isinstance(t, SomeObject):
                 return t
-            return annotationoftype(t)
+            s_result = annotation(t)
+            if isinstance(s_result, SomeStringOrUnicode):
+                return s_result.__class__(can_be_None=True)
+            return s_result
+        def get_type_descr_of_argument(arg):
+            # we don't want to check *all* the items in list/dict: we assume
+            # they are already homogeneous, so we only check the first
+            # item. The case of empty list/dict is handled inside typecheck()
+            if isinstance(arg, list):
+                item = arg[0]
+                return [get_type_descr_of_argument(item)]
+            elif isinstance(arg, dict):
+                key, value = next(arg.iteritems())
+                return {get_type_descr_of_argument(key): get_type_descr_of_argument(value)}
+            else:
+                return type(arg)
         def typecheck(*args):
+            from pypy.annotation.model import SomeList, SomeDict
             for i, (expected_type, arg) in enumerate(zip(types, args)):
                 if expected_type is None:
                     continue
                 s_expected = get_annotation(expected_type)
-                s_argtype = get_annotation(type(arg))
+                # special case: if we expect a list or dict and the argument
+                # is an empty list/dict, the typecheck always pass
+                if isinstance(s_expected, SomeList) and arg == []:
+                    continue
+                if isinstance(s_expected, SomeDict) and arg == {}:
+                    continue
+                #
+                s_argtype = get_annotation(get_type_descr_of_argument(arg))
                 if not s_expected.contains(s_argtype):
-                    msg = "%s argument number %d must be of type %s" % (
-                        f.func_name, i+1, expected_type)
+                    msg = "%s argument %r must be of type %s" % (
+                        f.func_name, srcargs[i], expected_type)
                     raise TypeError, msg
         #
         # we cannot simply wrap the function using *args, **kwds, because it's
         # not RPython. Instead, we generate a function with exactly the same
         # argument list
         srcargs, srcvarargs, srckeywords, defaults = inspect.getargspec(f)
+        if kwds:
+            types = tuple([kwds.get(arg) for arg in srcargs])
+        else:
+            types = types_
         assert len(srcargs) == len(types), (
             'not enough types provided: expected %d, got %d' %
             (len(types), len(srcargs)))
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)")
     
 
@@ -437,6 +437,12 @@
         return a+b
     assert f(2) == 42
 
+def test_enforceargs_keywords():
+    @enforceargs(b=int)
+    def f(a, b, c):
+        return a+b
+    assert f._annenforceargs_ == (None, int, None)
+
 def test_enforceargs_int_float_promotion():
     @enforceargs(float)
     def f(x):
@@ -444,6 +450,25 @@
     # in RPython there is an implicit int->float promotion
     assert f(42) == 42
 
+def test_enforceargs_None_string():
+    @enforceargs(str, unicode)
+    def f(a, b):
+        return a, b
+    assert f(None, None) == (None, None)
+
+def test_enforceargs_complex_types():
+    @enforceargs([int], {str: int})
+    def f(a, b):
+        return a, b
+    x = [0, 1, 2]
+    y = {'a': 1, 'b': 2}
+    assert f(x, y) == (x, y)
+    assert f([], {}) == ([], {})
+    assert f(None, None) == (None, None)
+    py.test.raises(TypeError, "f(['hello'], y)")
+    py.test.raises(TypeError, "f(x, {'a': 'hello'})")
+    py.test.raises(TypeError, "f(x, {0: 42})")
+
 def test_enforceargs_no_typecheck():
     @enforceargs(int, str, None, typecheck=False)
     def f(a, b, c):
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/test/test_rbuiltin.py b/pypy/rpython/test/test_rbuiltin.py
--- a/pypy/rpython/test/test_rbuiltin.py
+++ b/pypy/rpython/test/test_rbuiltin.py
@@ -540,6 +540,26 @@
         res = self.interpret(llfn, [0x12345678])
         assert res == 0x5678
 
+    def test_builtin_next(self):
+        def f(n):
+            x = [1, n, 2]
+            s = iter(x)
+            return next(s) + next(s)
+        res = self.interpret(f, [10])
+        assert res == 11
+
+    def test_builtin_next_stop_iteration(self):
+        def f(n):
+            x = [n]
+            s = iter(x)
+            try:
+                return next(s) + next(s)
+            except StopIteration:
+                return n + 500
+
+        res = self.interpret(f, [12])
+        assert res == 512
+
 
 class TestLLtype(BaseTestRbuiltin, LLRtypeMixin):
 
diff --git a/pypy/translator/c/funcgen.py b/pypy/translator/c/funcgen.py
--- a/pypy/translator/c/funcgen.py
+++ b/pypy/translator/c/funcgen.py
@@ -704,8 +704,9 @@
         value = self.expr(op.args[2])
         TYPE = op.args[2].concretetype
         typename = cdecl(self.db.gettype(TYPE).replace('@', '*@'), '')
-        return ('((%(typename)s) (%(addr)s + %(offset)s))[0] = %(value)s;' %
-                locals())
+        return (
+           '((%(typename)s) (((char *)%(addr)s) + %(offset)s))[0] = %(value)s;'
+           % locals())
 
     def OP_RAW_LOAD(self, op):
         addr = self.expr(op.args[0])
@@ -713,8 +714,9 @@
         result = self.expr(op.result)
         TYPE = op.result.concretetype
         typename = cdecl(self.db.gettype(TYPE).replace('@', '*@'), '')
-        return ("%(result)s = ((%(typename)s) (%(addr)s + %(offset)s))[0];" %
-                locals())
+        return (
+          "%(result)s = ((%(typename)s) (((char *)%(addr)s) + %(offset)s))[0];"
+          % locals())
 
     def OP_CAST_PRIMITIVE(self, op):
         TYPE = self.lltypemap(op.result)
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