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

wlav noreply at buildbot.pypy.org
Thu Sep 8 05:37:32 CEST 2011


Author: Wim Lavrijsen <WLavrijsen at lbl.gov>
Branch: reflex-support
Changeset: r47154:06400362eacb
Date: 2011-09-06 11:39 -0700
http://bitbucket.org/pypy/pypy/changeset/06400362eacb/

Log:	merge default into branch

diff too long, truncating to 10000 out of 10169 lines

diff --git a/lib-python/conftest.py b/lib-python/conftest.py
--- a/lib-python/conftest.py
+++ b/lib-python/conftest.py
@@ -359,7 +359,7 @@
     RegrTest('test_property.py', core=True),
     RegrTest('test_pstats.py'),
     RegrTest('test_pty.py', skip="unsupported extension module"),
-    RegrTest('test_pwd.py', skip=skip_win32),
+    RegrTest('test_pwd.py', usemodules="pwd", skip=skip_win32),
     RegrTest('test_py3kwarn.py'),
     RegrTest('test_pyclbr.py'),
     RegrTest('test_pydoc.py'),
diff --git a/lib-python/modified-2.7/ctypes/util.py b/lib-python/modified-2.7/ctypes/util.py
--- a/lib-python/modified-2.7/ctypes/util.py
+++ b/lib-python/modified-2.7/ctypes/util.py
@@ -72,8 +72,8 @@
         return name
 
 if os.name == "posix" and sys.platform == "darwin":
-    from ctypes.macholib.dyld import dyld_find as _dyld_find
     def find_library(name):
+        from ctypes.macholib.dyld import dyld_find as _dyld_find
         possible = ['lib%s.dylib' % name,
                     '%s.dylib' % name,
                     '%s.framework/%s' % (name, name)]
diff --git a/lib-python/modified-2.7/gzip.py b/lib-python/modified-2.7/gzip.py
new file mode 100644
--- /dev/null
+++ b/lib-python/modified-2.7/gzip.py
@@ -0,0 +1,514 @@
+"""Functions that read and write gzipped files.
+
+The user of the file doesn't have to worry about the compression,
+but random access is not allowed."""
+
+# based on Andrew Kuchling's minigzip.py distributed with the zlib module
+
+import struct, sys, time, os
+import zlib
+import io
+import __builtin__
+
+__all__ = ["GzipFile","open"]
+
+FTEXT, FHCRC, FEXTRA, FNAME, FCOMMENT = 1, 2, 4, 8, 16
+
+READ, WRITE = 1, 2
+
+def write32u(output, value):
+    # The L format writes the bit pattern correctly whether signed
+    # or unsigned.
+    output.write(struct.pack("<L", value))
+
+def read32(input):
+    return struct.unpack("<I", input.read(4))[0]
+
+def open(filename, mode="rb", compresslevel=9):
+    """Shorthand for GzipFile(filename, mode, compresslevel).
+
+    The filename argument is required; mode defaults to 'rb'
+    and compresslevel defaults to 9.
+
+    """
+    return GzipFile(filename, mode, compresslevel)
+
+class GzipFile(io.BufferedIOBase):
+    """The GzipFile class simulates most of the methods of a file object with
+    the exception of the readinto() and truncate() methods.
+
+    """
+
+    myfileobj = None
+    max_read_chunk = 10 * 1024 * 1024   # 10Mb
+
+    def __init__(self, filename=None, mode=None,
+                 compresslevel=9, fileobj=None, mtime=None):
+        """Constructor for the GzipFile class.
+
+        At least one of fileobj and filename must be given a
+        non-trivial value.
+
+        The new class instance is based on fileobj, which can be a regular
+        file, a StringIO object, or any other object which simulates a file.
+        It defaults to None, in which case filename is opened to provide
+        a file object.
+
+        When fileobj is not None, the filename argument is only used to be
+        included in the gzip file header, which may includes the original
+        filename of the uncompressed file.  It defaults to the filename of
+        fileobj, if discernible; otherwise, it defaults to the empty string,
+        and in this case the original filename is not included in the header.
+
+        The mode argument can be any of 'r', 'rb', 'a', 'ab', 'w', or 'wb',
+        depending on whether the file will be read or written.  The default
+        is the mode of fileobj if discernible; otherwise, the default is 'rb'.
+        Be aware that only the 'rb', 'ab', and 'wb' values should be used
+        for cross-platform portability.
+
+        The compresslevel argument is an integer from 1 to 9 controlling the
+        level of compression; 1 is fastest and produces the least compression,
+        and 9 is slowest and produces the most compression.  The default is 9.
+
+        The mtime argument is an optional numeric timestamp to be written
+        to the stream when compressing.  All gzip compressed streams
+        are required to contain a timestamp.  If omitted or None, the
+        current time is used.  This module ignores the timestamp when
+        decompressing; however, some programs, such as gunzip, make use
+        of it.  The format of the timestamp is the same as that of the
+        return value of time.time() and of the st_mtime member of the
+        object returned by os.stat().
+
+        """
+
+        # guarantee the file is opened in binary mode on platforms
+        # that care about that sort of thing
+        if mode and 'b' not in mode:
+            mode += 'b'
+        if fileobj is None:
+            fileobj = self.myfileobj = __builtin__.open(filename, mode or 'rb')
+        if filename is None:
+            if hasattr(fileobj, 'name'): filename = fileobj.name
+            else: filename = ''
+        if mode is None:
+            if hasattr(fileobj, 'mode'): mode = fileobj.mode
+            else: mode = 'rb'
+
+        if mode[0:1] == 'r':
+            self.mode = READ
+            # Set flag indicating start of a new member
+            self._new_member = True
+            # Buffer data read from gzip file. extrastart is offset in
+            # stream where buffer starts. extrasize is number of
+            # bytes remaining in buffer from current stream position.
+            self.extrabuf = ""
+            self.extrasize = 0
+            self.extrastart = 0
+            self.name = filename
+            # Starts small, scales exponentially
+            self.min_readsize = 100
+
+        elif mode[0:1] == 'w' or mode[0:1] == 'a':
+            self.mode = WRITE
+            self._init_write(filename)
+            self.compress = zlib.compressobj(compresslevel,
+                                             zlib.DEFLATED,
+                                             -zlib.MAX_WBITS,
+                                             zlib.DEF_MEM_LEVEL,
+                                             0)
+        else:
+            raise IOError, "Mode " + mode + " not supported"
+
+        self.fileobj = fileobj
+        self.offset = 0
+        self.mtime = mtime
+
+        if self.mode == WRITE:
+            self._write_gzip_header()
+
+    @property
+    def filename(self):
+        import warnings
+        warnings.warn("use the name attribute", DeprecationWarning, 2)
+        if self.mode == WRITE and self.name[-3:] != ".gz":
+            return self.name + ".gz"
+        return self.name
+
+    def __repr__(self):
+        s = repr(self.fileobj)
+        return '<gzip ' + s[1:-1] + ' ' + hex(id(self)) + '>'
+
+    def _check_closed(self):
+        """Raises a ValueError if the underlying file object has been closed.
+
+        """
+        if self.closed:
+            raise ValueError('I/O operation on closed file.')
+
+    def _init_write(self, filename):
+        self.name = filename
+        self.crc = zlib.crc32("") & 0xffffffffL
+        self.size = 0
+        self.writebuf = []
+        self.bufsize = 0
+
+    def _write_gzip_header(self):
+        self.fileobj.write('\037\213')             # magic header
+        self.fileobj.write('\010')                 # compression method
+        fname = os.path.basename(self.name)
+        if fname.endswith(".gz"):
+            fname = fname[:-3]
+        flags = 0
+        if fname:
+            flags = FNAME
+        self.fileobj.write(chr(flags))
+        mtime = self.mtime
+        if mtime is None:
+            mtime = time.time()
+        write32u(self.fileobj, long(mtime))
+        self.fileobj.write('\002')
+        self.fileobj.write('\377')
+        if fname:
+            self.fileobj.write(fname + '\000')
+
+    def _init_read(self):
+        self.crc = zlib.crc32("") & 0xffffffffL
+        self.size = 0
+
+    def _read_gzip_header(self):
+        magic = self.fileobj.read(2)
+        if magic != '\037\213':
+            raise IOError, 'Not a gzipped file'
+        method = ord( self.fileobj.read(1) )
+        if method != 8:
+            raise IOError, 'Unknown compression method'
+        flag = ord( self.fileobj.read(1) )
+        self.mtime = read32(self.fileobj)
+        # extraflag = self.fileobj.read(1)
+        # os = self.fileobj.read(1)
+        self.fileobj.read(2)
+
+        if flag & FEXTRA:
+            # Read & discard the extra field, if present
+            xlen = ord(self.fileobj.read(1))
+            xlen = xlen + 256*ord(self.fileobj.read(1))
+            self.fileobj.read(xlen)
+        if flag & FNAME:
+            # Read and discard a null-terminated string containing the filename
+            while True:
+                s = self.fileobj.read(1)
+                if not s or s=='\000':
+                    break
+        if flag & FCOMMENT:
+            # Read and discard a null-terminated string containing a comment
+            while True:
+                s = self.fileobj.read(1)
+                if not s or s=='\000':
+                    break
+        if flag & FHCRC:
+            self.fileobj.read(2)     # Read & discard the 16-bit header CRC
+
+    def write(self,data):
+        self._check_closed()
+        if self.mode != WRITE:
+            import errno
+            raise IOError(errno.EBADF, "write() on read-only GzipFile object")
+
+        if self.fileobj is None:
+            raise ValueError, "write() on closed GzipFile object"
+
+        # Convert data type if called by io.BufferedWriter.
+        if isinstance(data, memoryview):
+            data = data.tobytes()
+
+        if len(data) > 0:
+            self.size = self.size + len(data)
+            self.crc = zlib.crc32(data, self.crc) & 0xffffffffL
+            self.fileobj.write( self.compress.compress(data) )
+            self.offset += len(data)
+
+        return len(data)
+
+    def read(self, size=-1):
+        self._check_closed()
+        if self.mode != READ:
+            import errno
+            raise IOError(errno.EBADF, "read() on write-only GzipFile object")
+
+        if self.extrasize <= 0 and self.fileobj is None:
+            return ''
+
+        readsize = 1024
+        if size < 0:        # get the whole thing
+            try:
+                while True:
+                    self._read(readsize)
+                    readsize = min(self.max_read_chunk, readsize * 2)
+            except EOFError:
+                size = self.extrasize
+        elif size == 0:
+            return ""
+        else:               # just get some more of it
+            try:
+                while size > self.extrasize:
+                    self._read(readsize)
+                    readsize = min(self.max_read_chunk, readsize * 2)
+            except EOFError:
+                if size > self.extrasize:
+                    size = self.extrasize
+
+        offset = self.offset - self.extrastart
+        chunk = self.extrabuf[offset: offset + size]
+        self.extrasize = self.extrasize - size
+
+        self.offset += size
+        return chunk
+
+    def _unread(self, buf):
+        self.extrasize = len(buf) + self.extrasize
+        self.offset -= len(buf)
+
+    def _read(self, size=1024):
+        if self.fileobj is None:
+            raise EOFError, "Reached EOF"
+
+        if self._new_member:
+            # If the _new_member flag is set, we have to
+            # jump to the next member, if there is one.
+            #
+            # First, check if we're at the end of the file;
+            # if so, it's time to stop; no more members to read.
+            pos = self.fileobj.tell()   # Save current position
+            self.fileobj.seek(0, 2)     # Seek to end of file
+            if pos == self.fileobj.tell():
+                raise EOFError, "Reached EOF"
+            else:
+                self.fileobj.seek( pos ) # Return to original position
+
+            self._init_read()
+            self._read_gzip_header()
+            self.decompress = zlib.decompressobj(-zlib.MAX_WBITS)
+            self._new_member = False
+
+        # Read a chunk of data from the file
+        buf = self.fileobj.read(size)
+
+        # If the EOF has been reached, flush the decompression object
+        # and mark this object as finished.
+
+        if buf == "":
+            uncompress = self.decompress.flush()
+            self._read_eof()
+            self._add_read_data( uncompress )
+            raise EOFError, 'Reached EOF'
+
+        uncompress = self.decompress.decompress(buf)
+        self._add_read_data( uncompress )
+
+        if self.decompress.unused_data != "":
+            # Ending case: we've come to the end of a member in the file,
+            # so seek back to the start of the unused data, finish up
+            # this member, and read a new gzip header.
+            # (The number of bytes to seek back is the length of the unused
+            # data, minus 8 because _read_eof() will rewind a further 8 bytes)
+            self.fileobj.seek( -len(self.decompress.unused_data)+8, 1)
+
+            # Check the CRC and file size, and set the flag so we read
+            # a new member on the next call
+            self._read_eof()
+            self._new_member = True
+
+    def _add_read_data(self, data):
+        self.crc = zlib.crc32(data, self.crc) & 0xffffffffL
+        offset = self.offset - self.extrastart
+        self.extrabuf = self.extrabuf[offset:] + data
+        self.extrasize = self.extrasize + len(data)
+        self.extrastart = self.offset
+        self.size = self.size + len(data)
+
+    def _read_eof(self):
+        # We've read to the end of the file, so we have to rewind in order
+        # to reread the 8 bytes containing the CRC and the file size.
+        # We check the that the computed CRC and size of the
+        # uncompressed data matches the stored values.  Note that the size
+        # stored is the true file size mod 2**32.
+        self.fileobj.seek(-8, 1)
+        crc32 = read32(self.fileobj)
+        isize = read32(self.fileobj)  # may exceed 2GB
+        if crc32 != self.crc:
+            raise IOError("CRC check failed %s != %s" % (hex(crc32),
+                                                         hex(self.crc)))
+        elif isize != (self.size & 0xffffffffL):
+            raise IOError, "Incorrect length of data produced"
+
+        # Gzip files can be padded with zeroes and still have archives.
+        # Consume all zero bytes and set the file position to the first
+        # non-zero byte. See http://www.gzip.org/#faq8
+        c = "\x00"
+        while c == "\x00":
+            c = self.fileobj.read(1)
+        if c:
+            self.fileobj.seek(-1, 1)
+
+    @property
+    def closed(self):
+        return self.fileobj is None
+
+    def close(self):
+        if self.fileobj is None:
+            return
+        if self.mode == WRITE:
+            self.fileobj.write(self.compress.flush())
+            write32u(self.fileobj, self.crc)
+            # self.size may exceed 2GB, or even 4GB
+            write32u(self.fileobj, self.size & 0xffffffffL)
+            self.fileobj = None
+        elif self.mode == READ:
+            self.fileobj = None
+        if self.myfileobj:
+            self.myfileobj.close()
+            self.myfileobj = None
+
+    def flush(self,zlib_mode=zlib.Z_SYNC_FLUSH):
+        self._check_closed()
+        if self.mode == WRITE:
+            # Ensure the compressor's buffer is flushed
+            self.fileobj.write(self.compress.flush(zlib_mode))
+            self.fileobj.flush()
+
+    def fileno(self):
+        """Invoke the underlying file object's fileno() method.
+
+        This will raise AttributeError if the underlying file object
+        doesn't support fileno().
+        """
+        return self.fileobj.fileno()
+
+    def rewind(self):
+        '''Return the uncompressed stream file position indicator to the
+        beginning of the file'''
+        if self.mode != READ:
+            raise IOError("Can't rewind in write mode")
+        self.fileobj.seek(0)
+        self._new_member = True
+        self.extrabuf = ""
+        self.extrasize = 0
+        self.extrastart = 0
+        self.offset = 0
+
+    def readable(self):
+        return self.mode == READ
+
+    def writable(self):
+        return self.mode == WRITE
+
+    def seekable(self):
+        return True
+
+    def seek(self, offset, whence=0):
+        if whence:
+            if whence == 1:
+                offset = self.offset + offset
+            else:
+                raise ValueError('Seek from end not supported')
+        if self.mode == WRITE:
+            if offset < self.offset:
+                raise IOError('Negative seek in write mode')
+            count = offset - self.offset
+            for i in range(count // 1024):
+                self.write(1024 * '\0')
+            self.write((count % 1024) * '\0')
+        elif self.mode == READ:
+            if offset == self.offset:
+                self.read(0) # to make sure that this file is open
+                return self.offset
+            if offset < self.offset:
+                # for negative seek, rewind and do positive seek
+                self.rewind()
+            count = offset - self.offset
+            for i in range(count // 1024):
+                self.read(1024)
+            self.read(count % 1024)
+
+        return self.offset
+
+    def readline(self, size=-1):
+        if size < 0:
+            # Shortcut common case - newline found in buffer.
+            offset = self.offset - self.extrastart
+            i = self.extrabuf.find('\n', offset) + 1
+            if i > 0:
+                self.extrasize -= i - offset
+                self.offset += i - offset
+                return self.extrabuf[offset: i]
+
+            size = sys.maxint
+            readsize = self.min_readsize
+        else:
+            readsize = size
+        bufs = []
+        while size != 0:
+            c = self.read(readsize)
+            i = c.find('\n')
+
+            # We set i=size to break out of the loop under two
+            # conditions: 1) there's no newline, and the chunk is
+            # larger than size, or 2) there is a newline, but the
+            # resulting line would be longer than 'size'.
+            if (size <= i) or (i == -1 and len(c) > size):
+                i = size - 1
+
+            if i >= 0 or c == '':
+                bufs.append(c[:i + 1])    # Add portion of last chunk
+                self._unread(c[i + 1:])   # Push back rest of chunk
+                break
+
+            # Append chunk to list, decrease 'size',
+            bufs.append(c)
+            size = size - len(c)
+            readsize = min(size, readsize * 2)
+        if readsize > self.min_readsize:
+            self.min_readsize = min(readsize, self.min_readsize * 2, 512)
+        return ''.join(bufs) # Return resulting line
+
+
+def _test():
+    # Act like gzip; with -d, act like gunzip.
+    # The input file is not deleted, however, nor are any other gzip
+    # options or features supported.
+    args = sys.argv[1:]
+    decompress = args and args[0] == "-d"
+    if decompress:
+        args = args[1:]
+    if not args:
+        args = ["-"]
+    for arg in args:
+        if decompress:
+            if arg == "-":
+                f = GzipFile(filename="", mode="rb", fileobj=sys.stdin)
+                g = sys.stdout
+            else:
+                if arg[-3:] != ".gz":
+                    print "filename doesn't end in .gz:", repr(arg)
+                    continue
+                f = open(arg, "rb")
+                g = __builtin__.open(arg[:-3], "wb")
+        else:
+            if arg == "-":
+                f = sys.stdin
+                g = GzipFile(filename="", mode="wb", fileobj=sys.stdout)
+            else:
+                f = __builtin__.open(arg, "rb")
+                g = open(arg + ".gz", "wb")
+        while True:
+            chunk = f.read(1024)
+            if not chunk:
+                break
+            g.write(chunk)
+        if g is not sys.stdout:
+            g.close()
+        if f is not sys.stdin:
+            f.close()
+
+if __name__ == '__main__':
+    _test()
diff --git a/lib-python/modified-2.7/sqlite3/test/regression.py b/lib-python/modified-2.7/sqlite3/test/regression.py
--- a/lib-python/modified-2.7/sqlite3/test/regression.py
+++ b/lib-python/modified-2.7/sqlite3/test/regression.py
@@ -274,6 +274,18 @@
         cur.execute("UPDATE foo SET id = 3 WHERE id = 1")
         self.assertEqual(cur.description, None)
 
+    def CheckStatementCache(self):
+        cur = self.con.cursor()
+        cur.execute("CREATE TABLE foo (id INTEGER)")
+        values = [(i,) for i in xrange(5)]
+        cur.executemany("INSERT INTO foo (id) VALUES (?)", values)
+
+        cur.execute("SELECT id FROM foo")
+        self.assertEqual(list(cur), values)
+        self.con.commit()
+        cur.execute("SELECT id FROM foo")
+        self.assertEqual(list(cur), values)
+
 def suite():
     regression_suite = unittest.makeSuite(RegressionTests, "Check")
     return unittest.TestSuite((regression_suite,))
diff --git a/lib-python/modified-2.7/tarfile.py b/lib-python/modified-2.7/tarfile.py
--- a/lib-python/modified-2.7/tarfile.py
+++ b/lib-python/modified-2.7/tarfile.py
@@ -252,8 +252,8 @@
        the high bit set. So we calculate two checksums, unsigned and
        signed.
     """
-    unsigned_chksum = 256 + sum(struct.unpack("148B", buf[:148]) + struct.unpack("356B", buf[156:512]))
-    signed_chksum = 256 + sum(struct.unpack("148b", buf[:148]) + struct.unpack("356b", buf[156:512]))
+    unsigned_chksum = 256 + sum(struct.unpack("148B8x356B", buf[:512]))
+    signed_chksum = 256 + sum(struct.unpack("148b8x356b", buf[:512]))
     return unsigned_chksum, signed_chksum
 
 def copyfileobj(src, dst, length=None):
@@ -265,7 +265,6 @@
     if length is None:
         shutil.copyfileobj(src, dst)
         return
-
     BUFSIZE = 16 * 1024
     blocks, remainder = divmod(length, BUFSIZE)
     for b in xrange(blocks):
@@ -802,19 +801,19 @@
         if self.closed:
             raise ValueError("I/O operation on closed file")
 
-        buf = ""
         if self.buffer:
             if size is None:
-                buf = self.buffer
+                buf = self.buffer + self.fileobj.read()
                 self.buffer = ""
             else:
                 buf = self.buffer[:size]
                 self.buffer = self.buffer[size:]
-
-        if size is None:
-            buf += self.fileobj.read()
+                buf += self.fileobj.read(size - len(buf))
         else:
-            buf += self.fileobj.read(size - len(buf))
+            if size is None:
+                buf = self.fileobj.read()
+            else:
+                buf = self.fileobj.read(size)
 
         self.position += len(buf)
         return buf
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
@@ -54,7 +54,8 @@
     def get_ffi_argtype(self):
         if self._ffiargtype:
             return self._ffiargtype
-        return _shape_to_ffi_type(self._ffiargshape)
+        self._ffiargtype = _shape_to_ffi_type(self._ffiargshape)
+        return self._ffiargtype
 
     def _CData_output(self, resbuffer, base=None, index=-1):
         #assert isinstance(resbuffer, _rawffi.ArrayInstance)
@@ -166,7 +167,8 @@
     return tp._alignmentofinstances()
 
 def byref(cdata):
-    from ctypes import pointer
+    # "pointer" is imported at the end of this module to avoid circular
+    # imports
     return pointer(cdata)
 
 def cdata_from_address(self, address):
@@ -224,5 +226,9 @@
     'Z' : _ffi.types.void_p,
     'X' : _ffi.types.void_p,
     'v' : _ffi.types.sshort,
+    '?' : _ffi.types.ubyte,
     }
 
+
+# used by "byref"
+from _ctypes.pointer import pointer
diff --git a/lib_pypy/_elementtree.py b/lib_pypy/_elementtree.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/_elementtree.py
@@ -0,0 +1,6 @@
+# Just use ElementTree.
+
+from xml.etree import ElementTree
+
+globals().update(ElementTree.__dict__)
+del __all__
diff --git a/lib_pypy/_pypy_interact.py b/lib_pypy/_pypy_interact.py
--- a/lib_pypy/_pypy_interact.py
+++ b/lib_pypy/_pypy_interact.py
@@ -56,6 +56,10 @@
                 prompt = getattr(sys, 'ps1', '>>> ')
             try:
                 line = raw_input(prompt)
+                # Can be None if sys.stdin was redefined
+                encoding = getattr(sys.stdin, 'encoding', None)
+                if encoding and not isinstance(line, unicode):
+                    line = line.decode(encoding)
             except EOFError:
                 console.write("\n")
                 break
diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py
--- a/lib_pypy/_sqlite3.py
+++ b/lib_pypy/_sqlite3.py
@@ -24,6 +24,7 @@
 from ctypes import c_void_p, c_int, c_double, c_int64, c_char_p, cdll
 from ctypes import POINTER, byref, string_at, CFUNCTYPE, cast
 from ctypes import sizeof, c_ssize_t
+from collections import OrderedDict
 import datetime
 import sys
 import time
@@ -274,6 +275,28 @@
 def unicode_text_factory(x):
     return unicode(x, 'utf-8')
 
+
+class StatementCache(object):
+    def __init__(self, connection, maxcount):
+        self.connection = connection
+        self.maxcount = maxcount
+        self.cache = OrderedDict()
+
+    def get(self, sql, cursor, row_factory):
+        try:
+            stat = self.cache[sql]
+        except KeyError:
+            stat = Statement(self.connection, sql)
+            self.cache[sql] = stat
+            if len(self.cache) > self.maxcount:
+                self.cache.popitem(0)
+        #
+        if stat.in_use:
+            stat = Statement(self.connection, sql)
+        stat.set_row_factory(row_factory)
+        return stat
+
+
 class Connection(object):
     def __init__(self, database, timeout=5.0, detect_types=0, isolation_level="",
                  check_same_thread=True, factory=None, cached_statements=100):
@@ -291,6 +314,7 @@
         self.row_factory = None
         self._isolation_level = isolation_level
         self.detect_types = detect_types
+        self.statement_cache = StatementCache(self, cached_statements)
 
         self.cursors = []
 
@@ -399,7 +423,7 @@
         cur = Cursor(self)
         if not isinstance(sql, (str, unicode)):
             raise Warning("SQL is of wrong type. Must be string or unicode.")
-        statement = Statement(cur, sql, self.row_factory)
+        statement = self.statement_cache.get(sql, cur, self.row_factory)
         return statement
 
     def _get_isolation_level(self):
@@ -681,6 +705,8 @@
         from sqlite3.dump import _iterdump
         return _iterdump(self)
 
+DML, DQL, DDL = range(3)
+
 class Cursor(object):
     def __init__(self, con):
         if not isinstance(con, Connection):
@@ -708,12 +734,12 @@
         if type(sql) is unicode:
             sql = sql.encode("utf-8")
         self._check_closed()
-        self.statement = Statement(self, sql, self.row_factory)
+        self.statement = self.connection.statement_cache.get(sql, self, self.row_factory)
 
         if self.connection._isolation_level is not None:
-            if self.statement.kind == "DDL":
+            if self.statement.kind == DDL:
                 self.connection.commit()
-            elif self.statement.kind == "DML":
+            elif self.statement.kind == DML:
                 self.connection._begin()
 
         self.statement.set_params(params)
@@ -724,18 +750,18 @@
             self.statement.reset()
             raise self.connection._get_exception(ret)
 
-        if self.statement.kind == "DQL"and ret == SQLITE_ROW:
+        if self.statement.kind == DQL and ret == SQLITE_ROW:
             self.statement._build_row_cast_map()
-            self.statement._readahead()
+            self.statement._readahead(self)
         else:
             self.statement.item = None
             self.statement.exhausted = True
 
-        if self.statement.kind in ("DML", "DDL"):
+        if self.statement.kind == DML or self.statement.kind == DDL:
             self.statement.reset()
 
         self.rowcount = -1
-        if self.statement.kind == "DML":
+        if self.statement.kind == DML:
             self.rowcount = sqlite.sqlite3_changes(self.connection.db)
 
         return self
@@ -746,8 +772,9 @@
         if type(sql) is unicode:
             sql = sql.encode("utf-8")
         self._check_closed()
-        self.statement = Statement(self, sql, self.row_factory)
-        if self.statement.kind == "DML":
+        self.statement = self.connection.statement_cache.get(sql, self, self.row_factory)
+
+        if self.statement.kind == DML:
             self.connection._begin()
         else:
             raise ProgrammingError, "executemany is only for DML statements"
@@ -799,7 +826,7 @@
         return self
 
     def __iter__(self):
-        return self.statement
+        return iter(self.fetchone, None)
 
     def _check_reset(self):
         if self.reset:
@@ -816,7 +843,7 @@
             return None
 
         try:
-            return self.statement.next()
+            return self.statement.next(self)
         except StopIteration:
             return None
 
@@ -830,7 +857,7 @@
         if size is None:
             size = self.arraysize
         lst = []
-        for row in self.statement:
+        for row in self:
             lst.append(row)
             if len(lst) == size:
                 break
@@ -841,7 +868,7 @@
         self._check_reset()
         if self.statement is None:
             return []
-        return list(self.statement)
+        return list(self)
 
     def _getdescription(self):
         if self._description is None:
@@ -871,22 +898,24 @@
     lastrowid = property(_getlastrowid)
 
 class Statement(object):
-    def __init__(self, cur, sql, row_factory):
+    def __init__(self, connection, sql):
         self.statement = None
         if not isinstance(sql, str):
             raise ValueError, "sql must be a string"
-        self.con = cur.connection
-        self.cur = weakref.ref(cur)
+        self.con = connection
         self.sql = sql # DEBUG ONLY
-        self.row_factory = row_factory
         first_word = self._statement_kind = sql.lstrip().split(" ")[0].upper()
         if first_word in ("INSERT", "UPDATE", "DELETE", "REPLACE"):
-            self.kind = "DML"
+            self.kind = DML
         elif first_word in ("SELECT", "PRAGMA"):
-            self.kind = "DQL"
+            self.kind = DQL
         else:
-            self.kind = "DDL"
+            self.kind = DDL
         self.exhausted = False
+        self.in_use = False
+        #
+        # set by set_row_factory
+        self.row_factory = None
 
         self.statement = c_void_p()
         next_char = c_char_p()
@@ -895,7 +924,7 @@
         if ret == SQLITE_OK and self.statement.value is None:
             # an empty statement, we work around that, as it's the least trouble
             ret = sqlite.sqlite3_prepare_v2(self.con.db, "select 42", -1, byref(self.statement), byref(next_char))
-            self.kind = "DQL"
+            self.kind = DQL
 
         if ret != SQLITE_OK:
             raise self.con._get_exception(ret)
@@ -907,6 +936,9 @@
 
         self._build_row_cast_map()
 
+    def set_row_factory(self, row_factory):
+        self.row_factory = row_factory
+
     def _build_row_cast_map(self):
         self.row_cast_map = []
         for i in xrange(sqlite.sqlite3_column_count(self.statement)):
@@ -976,6 +1008,7 @@
         ret = sqlite.sqlite3_reset(self.statement)
         if ret != SQLITE_OK:
             raise self.con._get_exception(ret)
+        self.mark_dirty()
 
         if params is None:
             if sqlite.sqlite3_bind_parameter_count(self.statement) != 0:
@@ -1006,10 +1039,7 @@
                     raise ProgrammingError("missing parameter '%s'" %param)
                 self.set_param(idx, param)
 
-    def __iter__(self):
-        return self
-
-    def next(self):
+    def next(self, cursor):
         self.con._check_closed()
         self.con._check_thread()
         if self.exhausted:
@@ -1025,10 +1055,10 @@
             sqlite.sqlite3_reset(self.statement)
             raise exc
 
-        self._readahead()
+        self._readahead(cursor)
         return item
 
-    def _readahead(self):
+    def _readahead(self, cursor):
         self.column_count = sqlite.sqlite3_column_count(self.statement)
         row = []
         for i in xrange(self.column_count):
@@ -1063,23 +1093,30 @@
 
         row = tuple(row)
         if self.row_factory is not None:
-            row = self.row_factory(self.cur(), row)
+            row = self.row_factory(cursor, row)
         self.item = row
 
     def reset(self):
         self.row_cast_map = None
-        return sqlite.sqlite3_reset(self.statement)
+        ret = sqlite.sqlite3_reset(self.statement)
+        self.in_use = False
+        self.exhausted = False
+        return ret
 
     def finalize(self):
         sqlite.sqlite3_finalize(self.statement)
         self.statement = None
+        self.in_use = False
+
+    def mark_dirty(self):
+        self.in_use = True
 
     def __del__(self):
         sqlite.sqlite3_finalize(self.statement)
         self.statement = None
 
     def _get_description(self):
-        if self.kind == "DML":
+        if self.kind == DML:
             return None
         desc = []
         for i in xrange(sqlite.sqlite3_column_count(self.statement)):
diff --git a/lib_pypy/distributed/test/test_distributed.py b/lib_pypy/distributed/test/test_distributed.py
--- a/lib_pypy/distributed/test/test_distributed.py
+++ b/lib_pypy/distributed/test/test_distributed.py
@@ -9,7 +9,7 @@
 class AppTestDistributed(object):
     def setup_class(cls):
         cls.space = gettestobjspace(**{"objspace.std.withtproxy": True,
-            "usemodules":("_stackless",)})
+            "usemodules":("_continuation",)})
 
     def test_init(self):
         import distributed
@@ -91,10 +91,8 @@
 
 class AppTestDistributedTasklets(object):
     spaceconfig = {"objspace.std.withtproxy": True,
-                   "objspace.usemodules._stackless": True}
+                   "objspace.usemodules._continuation": True}
     def setup_class(cls):
-        #cls.space = gettestobjspace(**{"objspace.std.withtproxy": True,
-        #    "usemodules":("_stackless",)})
         cls.w_test_env = cls.space.appexec([], """():
         from distributed import test_env
         return test_env
diff --git a/lib_pypy/distributed/test/test_greensock.py b/lib_pypy/distributed/test/test_greensock.py
--- a/lib_pypy/distributed/test/test_greensock.py
+++ b/lib_pypy/distributed/test/test_greensock.py
@@ -10,7 +10,7 @@
         if not option.runappdirect:
             py.test.skip("Cannot run this on top of py.py because of PopenGateway")
         cls.space = gettestobjspace(**{"objspace.std.withtproxy": True,
-                                       "usemodules":("_stackless",)})
+                                       "usemodules":("_continuation",)})
         cls.w_remote_side_code = cls.space.appexec([], """():
         import sys
         sys.path.insert(0, '%s')
diff --git a/lib_pypy/distributed/test/test_socklayer.py b/lib_pypy/distributed/test/test_socklayer.py
--- a/lib_pypy/distributed/test/test_socklayer.py
+++ b/lib_pypy/distributed/test/test_socklayer.py
@@ -9,7 +9,8 @@
 class AppTestSocklayer:
     def setup_class(cls):
         cls.space = gettestobjspace(**{"objspace.std.withtproxy": True,
-                                       "usemodules":("_stackless","_socket", "select")})
+                                       "usemodules":("_continuation",
+                                                     "_socket", "select")})
     
     def test_socklayer(self):
         class X(object):
diff --git a/lib_pypy/greenlet.py b/lib_pypy/greenlet.py
--- a/lib_pypy/greenlet.py
+++ b/lib_pypy/greenlet.py
@@ -59,7 +59,12 @@
         #
         while not target:
             if not target.__started:
-                _continulet.__init__(target, _greenlet_start, *args)
+                if unbound_method != _continulet.throw:
+                    greenlet_func = _greenlet_start
+                else:
+                    greenlet_func = _greenlet_throw
+                _continulet.__init__(target, greenlet_func, *args)
+                unbound_method = _continulet.switch
                 args = ()
                 target.__started = True
                 break
@@ -136,3 +141,11 @@
         if greenlet.parent is not _tls.main:
             _continuation.permute(greenlet, greenlet.parent)
     return (res,)
+
+def _greenlet_throw(greenlet, exc, value, tb):
+    _tls.current = greenlet
+    try:
+        raise exc, value, tb
+    finally:
+        if greenlet.parent is not _tls.main:
+            _continuation.permute(greenlet, greenlet.parent)
diff --git a/lib_pypy/pypy_test/test_coroutine.py b/lib_pypy/pypy_test/test_coroutine.py
--- a/lib_pypy/pypy_test/test_coroutine.py
+++ b/lib_pypy/pypy_test/test_coroutine.py
@@ -2,7 +2,7 @@
 from py.test import skip, raises
 
 try:
-    from lib_pypy.stackless import coroutine, CoroutineExit
+    from stackless import coroutine, CoroutineExit
 except ImportError, e:
     skip('cannot import stackless: %s' % (e,))
 
@@ -20,10 +20,6 @@
         assert not co.is_zombie
 
     def test_is_zombie_del_without_frame(self):
-        try:
-            import _stackless # are we on pypy with a stackless build?
-        except ImportError:
-            skip("only works on pypy-c-stackless")
         import gc
         res = []
         class MyCoroutine(coroutine):
@@ -45,10 +41,6 @@
         assert res[0], "is_zombie was False in __del__"
 
     def test_is_zombie_del_with_frame(self):
-        try:
-            import _stackless # are we on pypy with a stackless build?
-        except ImportError:
-            skip("only works on pypy-c-stackless")
         import gc
         res = []
         class MyCoroutine(coroutine):
diff --git a/lib_pypy/pyrepl/reader.py b/lib_pypy/pyrepl/reader.py
--- a/lib_pypy/pyrepl/reader.py
+++ b/lib_pypy/pyrepl/reader.py
@@ -401,13 +401,19 @@
             return "(arg: %s) "%self.arg
         if "\n" in self.buffer:
             if lineno == 0:
-                return self._ps2
+                res = self.ps2
             elif lineno == self.buffer.count("\n"):
-                return self._ps4
+                res = self.ps4
             else:
-                return self._ps3
+                res = self.ps3
         else:
-            return self._ps1
+            res = self.ps1
+        # Lazily call str() on self.psN, and cache the results using as key
+        # the object on which str() was called.  This ensures that even if the
+        # same object is used e.g. for ps1 and ps2, str() is called only once.
+        if res not in self._pscache:
+            self._pscache[res] = str(res)
+        return self._pscache[res]
 
     def push_input_trans(self, itrans):
         self.input_trans_stack.append(self.input_trans)
@@ -473,8 +479,7 @@
             self.pos = 0
             self.dirty = 1
             self.last_command = None
-            self._ps1, self._ps2, self._ps3, self._ps4 = \
-                           map(str, [self.ps1, self.ps2, self.ps3, self.ps4])
+            self._pscache = {}
         except:
             self.restore()
             raise
@@ -571,7 +576,7 @@
         self.console.push_char(char)
         self.handle1(0)
     
-    def readline(self):
+    def readline(self, returns_unicode=False):
         """Read a line.  The implementation of this method also shows
         how to drive Reader if you want more control over the event
         loop."""
@@ -580,6 +585,8 @@
             self.refresh()
             while not self.finished:
                 self.handle1()
+            if returns_unicode:
+                return self.get_unicode()
             return self.get_buffer()
         finally:
             self.restore()
diff --git a/lib_pypy/pyrepl/readline.py b/lib_pypy/pyrepl/readline.py
--- a/lib_pypy/pyrepl/readline.py
+++ b/lib_pypy/pyrepl/readline.py
@@ -198,7 +198,7 @@
         reader.ps1 = prompt
         return reader.readline()
 
-    def multiline_input(self, more_lines, ps1, ps2):
+    def multiline_input(self, more_lines, ps1, ps2, returns_unicode=False):
         """Read an input on possibly multiple lines, asking for more
         lines as long as 'more_lines(unicodetext)' returns an object whose
         boolean value is true.
@@ -209,7 +209,7 @@
             reader.more_lines = more_lines
             reader.ps1 = reader.ps2 = ps1
             reader.ps3 = reader.ps4 = ps2
-            return reader.readline()
+            return reader.readline(returns_unicode=returns_unicode)
         finally:
             reader.more_lines = saved
 
diff --git a/lib_pypy/pyrepl/simple_interact.py b/lib_pypy/pyrepl/simple_interact.py
--- a/lib_pypy/pyrepl/simple_interact.py
+++ b/lib_pypy/pyrepl/simple_interact.py
@@ -54,7 +54,8 @@
             ps1 = getattr(sys, 'ps1', '>>> ')
             ps2 = getattr(sys, 'ps2', '... ')
             try:
-                statement = multiline_input(more_lines, ps1, ps2)
+                statement = multiline_input(more_lines, ps1, ps2,
+                                            returns_unicode=True)
             except EOFError:
                 break
             more = console.push(statement)
diff --git a/lib_pypy/stackless.py b/lib_pypy/stackless.py
--- a/lib_pypy/stackless.py
+++ b/lib_pypy/stackless.py
@@ -4,121 +4,124 @@
 Please refer to their documentation.
 """
 
-DEBUG = True
-
-def dprint(*args):
-    for arg in args:
-        print arg,
-    print
 
 import traceback
-import sys
+import _continuation
+from functools import partial
+
+class TaskletExit(Exception):
+    pass
+
+CoroutineExit = TaskletExit
+
+class GWrap(_continuation.continulet):
+    """This is just a wrapper around continulet to allow
+       to stick additional attributes to a continulet.
+       To be more concrete, we need a backreference to
+       the coroutine object"""
+
+
+class coroutine(object):
+    "we can't have continulet as a base, because continulets can't be rebound"
+
+    def __init__(self):
+        self._frame = None
+        self.is_zombie = False
+
+    def __getattr__(self, attr):
+        return getattr(self._frame, attr)
+
+    def __del__(self):
+        self.is_zombie = True
+        del self._frame
+        self._frame = None
+
+    def bind(self, func, *argl, **argd):
+        """coro.bind(f, *argl, **argd) -> None.
+           binds function f to coro. f will be called with
+           arguments *argl, **argd
+        """
+        if self._frame is None or not self._frame.is_pending():
+
+            def _func(c, *args, **kwargs):
+                return func(*args, **kwargs)
+            
+            run = partial(_func, *argl, **argd)
+            self._frame = frame = GWrap(run)
+        else:
+            raise ValueError("cannot bind a bound coroutine")
+
+    def switch(self):
+        """coro.switch() -> returnvalue
+           switches to coroutine coro. If the bound function
+           f finishes, the returnvalue is that of f, otherwise
+           None is returned
+        """
+        current = _getcurrent()
+        current._jump_to(self)
+
+    def _jump_to(self, coroutine):
+        _tls.current_coroutine = coroutine
+        self._frame.switch(to=coroutine._frame)
+
+    def kill(self):
+        """coro.kill() : kill coroutine coro"""
+        _tls.current_coroutine = self
+        self._frame.throw(CoroutineExit)
+
+    def _is_alive(self):
+        if self._frame is None:
+            return False
+        return not self._frame.is_pending()
+    is_alive = property(_is_alive)
+    del _is_alive
+
+    def getcurrent():
+        """coroutine.getcurrent() -> the currently running coroutine"""
+        try:
+            return _getcurrent()
+        except AttributeError:
+            return _maincoro
+    getcurrent = staticmethod(getcurrent)
+
+    def __reduce__(self):
+        raise TypeError, 'pickling is not possible based upon continulets'
+
+
+def _getcurrent():
+    "Returns the current coroutine (i.e. the one which called this function)."
+    try:
+        return _tls.current_coroutine
+    except AttributeError:
+        # first call in this thread: current == main
+        _coroutine_create_main()
+        return _tls.current_coroutine
+
 try:
-    # If _stackless can be imported then TaskletExit and CoroutineExit are 
-    # automatically added to the builtins.
-    from _stackless import coroutine, greenlet
-except ImportError: # we are running from CPython
-    from greenlet import greenlet, GreenletExit
-    TaskletExit = CoroutineExit = GreenletExit
-    del GreenletExit
-    try:
-        from functools import partial
-    except ImportError: # we are not running python 2.5
-        class partial(object):
-            # just enough of 'partial' to be usefull
-            def __init__(self, func, *argl, **argd):
-                self.func = func
-                self.argl = argl
-                self.argd = argd
+    from thread import _local
+except ImportError:
+    class _local(object):    # assume no threads
+        pass
 
-            def __call__(self):
-                return self.func(*self.argl, **self.argd)
+_tls = _local()
 
-    class GWrap(greenlet):
-        """This is just a wrapper around greenlets to allow
-           to stick additional attributes to a greenlet.
-           To be more concrete, we need a backreference to
-           the coroutine object"""
+def _coroutine_create_main():
+    # create the main coroutine for this thread
+    _tls.current_coroutine = None
+    main_coroutine = coroutine()
+    main_coroutine.bind(lambda x:x)
+    _tls.main_coroutine = main_coroutine
+    _tls.current_coroutine = main_coroutine
+    return main_coroutine
 
-    class MWrap(object):
-        def __init__(self,something):
-            self.something = something
 
-        def __getattr__(self, attr):
-            return getattr(self.something, attr)
+_maincoro = _coroutine_create_main()
 
-    class coroutine(object):
-        "we can't have greenlet as a base, because greenlets can't be rebound"
-
-        def __init__(self):
-            self._frame = None
-            self.is_zombie = False
-
-        def __getattr__(self, attr):
-            return getattr(self._frame, attr)
-
-        def __del__(self):
-            self.is_zombie = True
-            del self._frame
-            self._frame = None
-
-        def bind(self, func, *argl, **argd):
-            """coro.bind(f, *argl, **argd) -> None.
-               binds function f to coro. f will be called with
-               arguments *argl, **argd
-            """
-            if self._frame is None or self._frame.dead:
-                self._frame = frame = GWrap()
-                frame.coro = self
-            if hasattr(self._frame, 'run') and self._frame.run:
-                raise ValueError("cannot bind a bound coroutine")
-            self._frame.run = partial(func, *argl, **argd)
-
-        def switch(self):
-            """coro.switch() -> returnvalue
-               switches to coroutine coro. If the bound function
-               f finishes, the returnvalue is that of f, otherwise
-               None is returned
-            """
-            try:
-                return greenlet.switch(self._frame)
-            except TypeError, exp: # self._frame is the main coroutine
-                return greenlet.switch(self._frame.something)
-
-        def kill(self):
-            """coro.kill() : kill coroutine coro"""
-            self._frame.throw()
-
-        def _is_alive(self):
-            if self._frame is None:
-                return False
-            return not self._frame.dead
-        is_alive = property(_is_alive)
-        del _is_alive
-
-        def getcurrent():
-            """coroutine.getcurrent() -> the currently running coroutine"""
-            try:
-                return greenlet.getcurrent().coro
-            except AttributeError:
-                return _maincoro
-        getcurrent = staticmethod(getcurrent)
-
-        def __reduce__(self):
-            raise TypeError, 'pickling is not possible based upon greenlets'
-
-    _maincoro = coroutine()
-    maingreenlet = greenlet.getcurrent()
-    _maincoro._frame = frame = MWrap(maingreenlet)
-    frame.coro = _maincoro
-    del frame
-    del maingreenlet
 
 from collections import deque
 
 import operator
-__all__ = 'run getcurrent getmain schedule tasklet channel coroutine \
-                greenlet'.split()
+__all__ = 'run getcurrent getmain schedule tasklet channel coroutine'.split()
 
 _global_task_id = 0
 _squeue = None
@@ -131,7 +134,8 @@
 def _scheduler_remove(value):
     try:
         del _squeue[operator.indexOf(_squeue, value)]
-    except ValueError:pass
+    except ValueError:
+        pass
 
 def _scheduler_append(value, normal=True):
     if normal:
diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py
--- a/pypy/config/pypyoption.py
+++ b/pypy/config/pypyoption.py
@@ -27,7 +27,7 @@
 # --allworkingmodules
 working_modules = default_modules.copy()
 working_modules.update(dict.fromkeys(
-    ["_socket", "unicodedata", "mmap", "fcntl", "_locale",
+    ["_socket", "unicodedata", "mmap", "fcntl", "_locale", "pwd",
      "rctime" , "select", "zipimport", "_lsprof",
      "crypt", "signal", "_rawffi", "termios", "zlib", "bz2",
      "struct", "_hashlib", "_md5", "_sha", "_minimal_curses", "cStringIO",
@@ -58,6 +58,7 @@
     # unix only modules
     del working_modules["crypt"]
     del working_modules["fcntl"]
+    del working_modules["pwd"]
     del working_modules["termios"]
     del working_modules["_minimal_curses"]
 
diff --git a/pypy/config/test/test_config.py b/pypy/config/test/test_config.py
--- a/pypy/config/test/test_config.py
+++ b/pypy/config/test/test_config.py
@@ -281,11 +281,11 @@
 
 def test_underscore_in_option_name():
     descr = OptionDescription("opt", "", [
-        BoolOption("_stackless", "", default=False),
+        BoolOption("_foobar", "", default=False),
     ])
     config = Config(descr)
     parser = to_optparse(config)
-    assert parser.has_option("--_stackless")
+    assert parser.has_option("--_foobar")
 
 def test_none():
     dummy1 = BoolOption('dummy1', 'doc dummy', default=False, cmdline=None)
diff --git a/pypy/doc/config/objspace.usemodules._stackless.txt b/pypy/doc/config/objspace.usemodules._stackless.txt
deleted file mode 100644
--- a/pypy/doc/config/objspace.usemodules._stackless.txt
+++ /dev/null
@@ -1,1 +0,0 @@
-Deprecated.
diff --git a/pypy/doc/config/objspace.usemodules.pwd.txt b/pypy/doc/config/objspace.usemodules.pwd.txt
new file mode 100644
--- /dev/null
+++ b/pypy/doc/config/objspace.usemodules.pwd.txt
@@ -0,0 +1,2 @@
+Use the 'pwd' module. 
+This module is expected to be fully working.
diff --git a/pypy/doc/faq.rst b/pypy/doc/faq.rst
--- a/pypy/doc/faq.rst
+++ b/pypy/doc/faq.rst
@@ -315,6 +315,28 @@
 
 .. _`Andrew Brown's tutorial`: http://morepypy.blogspot.com/2011/04/tutorial-writing-interpreter-with-pypy.html
 
+---------------------------------------------------------
+Can RPython modules for PyPy be translated independently?
+---------------------------------------------------------
+
+No, you have to rebuild the entire interpreter.  This means two things:
+
+* It is imperative to use test-driven development.  You have to test
+  exhaustively your module in pure Python, before even attempting to
+  translate it.  Once you translate it, you should have only a few typing
+  issues left to fix, but otherwise the result should work out of the box.
+
+* Second, and perhaps most important: do you have a really good reason
+  for writing the module in RPython in the first place?  Nowadays you
+  should really look at alternatives, like writing it in pure Python,
+  using ctypes if it needs to call C code.  Other alternatives are being
+  developed too (as of summer 2011), like a Cython binding.
+
+In this context it is not that important to be able to translate
+RPython modules independently of translating the complete interpreter.
+(It could be done given enough efforts, but it's a really serious
+undertaking.  Consider it as quite unlikely for now.)
+
 ----------------------------------------------------------
 Why does PyPy draw a Mandelbrot fractal while translating?
 ----------------------------------------------------------
diff --git a/pypy/doc/jit/pyjitpl5.rst b/pypy/doc/jit/pyjitpl5.rst
--- a/pypy/doc/jit/pyjitpl5.rst
+++ b/pypy/doc/jit/pyjitpl5.rst
@@ -103,7 +103,7 @@
 
 The meta-interpreter starts interpreting the JIT bytecode.  Each operation is
 executed and then recorded in a list of operations, called the trace.
-Operations can have a list of boxes that operate on, arguments.  Some operations
+Operations can have a list of boxes they operate on, arguments.  Some operations
 (like GETFIELD and GETARRAYITEM) also have special objects that describe how
 their arguments are laid out in memory.  All possible operations generated by
 tracing are listed in metainterp/resoperation.py.  When a (interpreter-level)
diff --git a/pypy/doc/stackless.rst b/pypy/doc/stackless.rst
--- a/pypy/doc/stackless.rst
+++ b/pypy/doc/stackless.rst
@@ -199,7 +199,11 @@
 The following features (present in some past Stackless version of PyPy)
 are for the time being not supported any more:
 
-* Tasklets and channels (needs to be rewritten at app-level)
+* Tasklets and channels (currently ``stackless.py`` seems to import,
+  but you have tasklets on top of coroutines on top of greenlets on
+  top of continulets on top of stacklets, and it's probably not too
+  hard to cut two of these levels by adapting ``stackless.py`` to
+  use directly continulets)
 
 * Coroutines (could be rewritten at app-level)
 
@@ -209,6 +213,13 @@
 
 * Automatic unlimited stack (must be emulated__ so far)
 
+* Support for other CPUs than x86 and x86-64
+
+* The app-level ``f_back`` field of frames crossing continulet boundaries
+  is None for now, unlike what I explain in the theoretical overview
+  above.  It mostly means that in a ``pdb.set_trace()`` you cannot go
+  ``up`` past countinulet boundaries.  This could be fixed.
+
 .. __: `recursion depth limit`_
 
 (*) Pickling, as well as changing threads, could be implemented by using
@@ -217,9 +228,8 @@
 "hard" switch (like now) when the C stack contains non-trivial C frames
 to save, and a "soft" switch (like previously) when it contains only
 simple calls from Python to Python.  Soft-switched continulets would
-also consume a bit less RAM, at the possible expense of making the
-switch a bit slower (unsure about that; what is the Stackless Python
-experience?).
+also consume a bit less RAM, and the switch might be a bit faster too
+(unsure about that; what is the Stackless Python experience?).
 
 
 Recursion depth limit
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -626,9 +626,9 @@
             self.default_compiler = compiler
             return compiler
 
-    def createframe(self, code, w_globals, closure=None):
+    def createframe(self, code, w_globals, outer_func=None):
         "Create an empty PyFrame suitable for this code object."
-        return self.FrameClass(self, code, w_globals, closure)
+        return self.FrameClass(self, code, w_globals, outer_func)
 
     def allocate_lock(self):
         """Return an interp-level Lock object if threads are enabled,
diff --git a/pypy/interpreter/function.py b/pypy/interpreter/function.py
--- a/pypy/interpreter/function.py
+++ b/pypy/interpreter/function.py
@@ -30,7 +30,7 @@
     can_change_code = True
     _immutable_fields_ = ['code?',
                           'w_func_globals?',
-                          'closure?',
+                          'closure?[*]',
                           'defs_w?[*]',
                           'name?']
 
@@ -96,7 +96,7 @@
             assert isinstance(code, PyCode)
             if nargs < 5:
                 new_frame = self.space.createframe(code, self.w_func_globals,
-                                                   self.closure)
+                                                   self)
                 for i in funccallunrolling:
                     if i < nargs:
                         new_frame.locals_stack_w[i] = args_w[i]
@@ -156,7 +156,7 @@
     def _flat_pycall(self, code, nargs, frame):
         # code is a PyCode
         new_frame = self.space.createframe(code, self.w_func_globals,
-                                                   self.closure)
+                                                   self)
         for i in xrange(nargs):
             w_arg = frame.peekvalue(nargs-1-i)
             new_frame.locals_stack_w[i] = w_arg
@@ -167,7 +167,7 @@
     def _flat_pycall_defaults(self, code, nargs, frame, defs_to_load):
         # code is a PyCode
         new_frame = self.space.createframe(code, self.w_func_globals,
-                                                   self.closure)
+                                                   self)
         for i in xrange(nargs):
             w_arg = frame.peekvalue(nargs-1-i)
             new_frame.locals_stack_w[i] = w_arg
diff --git a/pypy/interpreter/miscutils.py b/pypy/interpreter/miscutils.py
--- a/pypy/interpreter/miscutils.py
+++ b/pypy/interpreter/miscutils.py
@@ -167,3 +167,7 @@
 
     def getmainthreadvalue(self):
         return self._value
+
+    def getallvalues(self):
+        return {0: self._value}
+
diff --git a/pypy/interpreter/nestedscope.py b/pypy/interpreter/nestedscope.py
--- a/pypy/interpreter/nestedscope.py
+++ b/pypy/interpreter/nestedscope.py
@@ -8,7 +8,7 @@
 
 class Cell(Wrappable):
     "A simple container for a wrapped value."
-    
+
     def __init__(self, w_value=None):
         self.w_value = w_value
 
@@ -90,32 +90,33 @@
     #     variables coming from a parent function in which i'm nested
     # 'closure' is a list of Cell instances: the received free vars.
 
-    cells = None
-
     @jit.unroll_safe
-    def initialize_frame_scopes(self, closure, code):
-        super_initialize_frame_scopes(self, closure, code)
+    def initialize_frame_scopes(self, outer_func, code):
+        super_initialize_frame_scopes(self, outer_func, code)
         ncellvars = len(code.co_cellvars)
         nfreevars = len(code.co_freevars)
         if not nfreevars:
             if not ncellvars:
+                self.cells = []
                 return            # no self.cells needed - fast path
-            if closure is None:
-                closure = []
-        elif closure is None:
+        elif outer_func is None:
             space = self.space
             raise OperationError(space.w_TypeError,
                                  space.wrap("directly executed code object "
                                             "may not contain free variables"))
-        if len(closure) != nfreevars:
+        if outer_func and outer_func.closure:
+            closure_size = len(outer_func.closure)
+        else:
+            closure_size = 0
+        if closure_size != nfreevars:
             raise ValueError("code object received a closure with "
                                  "an unexpected number of free variables")
         self.cells = [None] * (ncellvars + nfreevars)
         for i in range(ncellvars):
             self.cells[i] = Cell()
         for i in range(nfreevars):
-            self.cells[i + ncellvars] = closure[i]
-    
+            self.cells[i + ncellvars] = outer_func.closure[i]
+
     def _getcells(self):
         return self.cells
 
diff --git a/pypy/interpreter/pycode.py b/pypy/interpreter/pycode.py
--- a/pypy/interpreter/pycode.py
+++ b/pypy/interpreter/pycode.py
@@ -198,7 +198,7 @@
 
     def funcrun(self, func, args):
         frame = self.space.createframe(self, func.w_func_globals,
-                                  func.closure)
+                                  func)
         sig = self._signature
         # speed hack
         fresh_frame = jit.hint(frame, access_directly=True,
@@ -211,7 +211,7 @@
 
     def funcrun_obj(self, func, w_obj, args):
         frame = self.space.createframe(self, func.w_func_globals,
-                                  func.closure)
+                                  func)
         sig = self._signature
         # speed hack
         fresh_frame = jit.hint(frame, access_directly=True,
diff --git a/pypy/interpreter/pyframe.py b/pypy/interpreter/pyframe.py
--- a/pypy/interpreter/pyframe.py
+++ b/pypy/interpreter/pyframe.py
@@ -51,7 +51,7 @@
     is_being_profiled        = False
     escaped                  = False  # see mark_as_escaped()
 
-    def __init__(self, space, code, w_globals, closure):
+    def __init__(self, space, code, w_globals, outer_func):
         if not we_are_translated():
             assert type(self) in (space.FrameClass, CPythonFrame), (
                 "use space.FrameClass(), not directly PyFrame()")
@@ -70,7 +70,7 @@
             self.builtin = space.builtin.pick_builtin(w_globals)
         # regular functions always have CO_OPTIMIZED and CO_NEWLOCALS.
         # class bodies only have CO_NEWLOCALS.
-        self.initialize_frame_scopes(closure, code)
+        self.initialize_frame_scopes(outer_func, code)
         self.f_lineno = code.co_firstlineno
 
     def mark_as_escaped(self):
@@ -117,8 +117,8 @@
             return self.builtin
         else:
             return self.space.builtin
-        
-    def initialize_frame_scopes(self, closure, code): 
+
+    def initialize_frame_scopes(self, outer_func, code):
         # regular functions always have CO_OPTIMIZED and CO_NEWLOCALS.
         # class bodies only have CO_NEWLOCALS.
         # CO_NEWLOCALS: make a locals dict unless optimized is also set
@@ -385,7 +385,11 @@
         
         # do not use the instance's __init__ but the base's, because we set
         # everything like cells from here
-        PyFrame.__init__(self, space, pycode, w_globals, closure)
+        # XXX hack
+        from pypy.interpreter.function import Function
+        outer_func = Function(space, None, closure=closure,
+                             forcename="fake")
+        PyFrame.__init__(self, space, pycode, w_globals, outer_func)
         f_back = space.interp_w(PyFrame, w_f_back, can_be_None=True)
         new_frame.f_backref = jit.non_virtual_ref(f_back)
 
diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py
--- a/pypy/interpreter/pyopcode.py
+++ b/pypy/interpreter/pyopcode.py
@@ -1523,10 +1523,8 @@
 
         if not isinstance(prog, codetype):
             filename = '<string>'
-            if not isinstance(prog, str):
-                if isinstance(prog, basestring):
-                    prog = str(prog)
-                elif isinstance(prog, file):
+            if not isinstance(prog, basestring):
+                if isinstance(prog, file):
                     filename = prog.name
                     prog = prog.read()
                 else:
diff --git a/pypy/interpreter/pyparser/future.py b/pypy/interpreter/pyparser/future.py
--- a/pypy/interpreter/pyparser/future.py
+++ b/pypy/interpreter/pyparser/future.py
@@ -109,25 +109,19 @@
             self.getc() == self.getc(+2)):
             self.pos += 3
             while 1: # Deal with a triple quoted docstring
-                if self.getc() == '\\':
-                    self.pos += 2
+                c = self.getc()
+                if c == '\\':
+                    self.pos += 1
+                    self._skip_next_char_from_docstring()
+                elif c != endchar:
+                    self._skip_next_char_from_docstring()
                 else:
-                    c = self.getc()
-                    if c != endchar:
-                        self.pos += 1
-                        if c == '\n':
-                            self.atbol()
-                        elif c == '\r':
-                            if self.getc() == '\n':
-                                self.pos += 1
-                                self.atbol()
-                    else:
-                        self.pos += 1
-                        if (self.getc() == endchar and
-                            self.getc(+1) == endchar):
-                            self.pos += 2
-                            self.consume_empty_line()
-                            break
+                    self.pos += 1
+                    if (self.getc() == endchar and
+                        self.getc(+1) == endchar):
+                        self.pos += 2
+                        self.consume_empty_line()
+                        break
 
         else: # Deal with a single quoted docstring
             self.pos += 1
@@ -138,17 +132,21 @@
                     self.consume_empty_line()
                     return
                 elif c == '\\':
-                    # Deal with linefeeds
-                    if self.getc() != '\r':
-                        self.pos += 1
-                    else:
-                        self.pos += 1
-                        if self.getc() == '\n':
-                            self.pos += 1
+                    self._skip_next_char_from_docstring()
                 elif c in '\r\n':
                     # Syntax error
                     return
 
+    def _skip_next_char_from_docstring(self):
+        c = self.getc()
+        self.pos += 1
+        if c == '\n':
+            self.atbol()
+        elif c == '\r':
+            if self.getc() == '\n':
+                self.pos += 1
+            self.atbol()
+
     def consume_continuation(self):
         c = self.getc()
         if c in '\n\r':
diff --git a/pypy/interpreter/pyparser/test/test_futureautomaton.py b/pypy/interpreter/pyparser/test/test_futureautomaton.py
--- a/pypy/interpreter/pyparser/test/test_futureautomaton.py
+++ b/pypy/interpreter/pyparser/test/test_futureautomaton.py
@@ -221,6 +221,14 @@
     assert f.lineno == 3
     assert f.col_offset == 0
 
+def test_lots_of_continuation_lines():
+    s = "\\\n\\\n\\\n\\\n\\\n\\\n\nfrom __future__ import with_statement\n"
+    f = run(s)
+    assert f.pos == len(s)
+    assert f.flags == fut.CO_FUTURE_WITH_STATEMENT
+    assert f.lineno == 8
+    assert f.col_offset == 0
+
 # This looks like a bug in cpython parser
 # and would require extensive modifications
 # to future.py in order to emulate the same behaviour
@@ -239,3 +247,19 @@
         raise AssertionError('IndentationError not raised')
     assert f.lineno == 2
     assert f.col_offset == 0
+
+def test_continuation_lines_in_docstring_single_quoted():
+    s = '"\\\n\\\n\\\n\\\n\\\n\\\n"\nfrom  __future__ import division\n'
+    f = run(s)
+    assert f.pos == len(s)
+    assert f.flags == fut.CO_FUTURE_DIVISION
+    assert f.lineno == 8
+    assert f.col_offset == 0
+
+def test_continuation_lines_in_docstring_triple_quoted():
+    s = '"""\\\n\\\n\\\n\\\n\\\n\\\n"""\nfrom  __future__ import division\n'
+    f = run(s)
+    assert f.pos == len(s)
+    assert f.flags == fut.CO_FUTURE_DIVISION
+    assert f.lineno == 8
+    assert f.col_offset == 0
diff --git a/pypy/interpreter/test/test_exec.py b/pypy/interpreter/test/test_exec.py
--- a/pypy/interpreter/test/test_exec.py
+++ b/pypy/interpreter/test/test_exec.py
@@ -219,3 +219,30 @@
             raise e
 
         assert res == 1
+
+    def test_exec_unicode(self):
+        # 's' is a string
+        s = "x = u'\xd0\xb9\xd1\x86\xd1\x83\xd0\xba\xd0\xb5\xd0\xbd'"
+        # 'u' is a unicode
+        u = s.decode('utf-8')
+        exec u
+        assert len(x) == 6
+        assert ord(x[0]) == 0x0439
+        assert ord(x[1]) == 0x0446
+        assert ord(x[2]) == 0x0443
+        assert ord(x[3]) == 0x043a
+        assert ord(x[4]) == 0x0435
+        assert ord(x[5]) == 0x043d
+
+    def test_eval_unicode(self):
+        u = "u'%s'" % unichr(0x1234)
+        v = eval(u)
+        assert v == unichr(0x1234)
+
+    def test_compile_unicode(self):
+        s = "x = u'\xd0\xb9\xd1\x86\xd1\x83\xd0\xba\xd0\xb5\xd0\xbd'"
+        u = s.decode('utf-8')
+        c = compile(u, '<input>', 'exec')
+        exec c
+        assert len(x) == 6
+        assert ord(x[0]) == 0x0439
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
@@ -25,13 +25,14 @@
 class Descr(history.AbstractDescr):
 
     def __init__(self, ofs, typeinfo, extrainfo=None, name=None,
-                 arg_types=None, count_fields_if_immut=-1):
+                 arg_types=None, count_fields_if_immut=-1, ffi_flags=0):
         self.ofs = ofs
         self.typeinfo = typeinfo
         self.extrainfo = extrainfo
         self.name = name
         self.arg_types = arg_types
         self.count_fields_if_immut = count_fields_if_immut
+        self.ffi_flags = ffi_flags
 
     def get_arg_types(self):
         return self.arg_types
@@ -67,6 +68,9 @@
     def count_fields_if_immutable(self):
         return self.count_fields_if_immut
 
+    def get_ffi_flags(self):
+        return self.ffi_flags
+
     def __lt__(self, other):
         raise TypeError("cannot use comparison on Descrs")
     def __le__(self, other):
@@ -114,14 +118,14 @@
         return False
 
     def getdescr(self, ofs, typeinfo='?', extrainfo=None, name=None,
-                 arg_types=None, count_fields_if_immut=-1):
+                 arg_types=None, count_fields_if_immut=-1, ffi_flags=0):
         key = (ofs, typeinfo, extrainfo, name, arg_types,
-               count_fields_if_immut)
+               count_fields_if_immut, ffi_flags)
         try:
             return self._descrs[key]
         except KeyError:
             descr = Descr(ofs, typeinfo, extrainfo, name, arg_types,
-                          count_fields_if_immut)
+                          count_fields_if_immut, ffi_flags)
             self._descrs[key] = descr
             return descr
 
@@ -326,7 +330,7 @@
         return self.getdescr(0, token[0], extrainfo=extrainfo,
                              arg_types=''.join(arg_types))
 
-    def calldescrof_dynamic(self, ffi_args, ffi_result, extrainfo):
+    def calldescrof_dynamic(self, ffi_args, ffi_result, extrainfo, ffi_flags):
         from pypy.jit.backend.llsupport.ffisupport import get_ffi_type_kind
         from pypy.jit.backend.llsupport.ffisupport import UnsupportedKind
         arg_types = []
@@ -339,7 +343,8 @@
         except UnsupportedKind:
             return None
         return self.getdescr(0, reskind, extrainfo=extrainfo,
-                             arg_types=''.join(arg_types))
+                             arg_types=''.join(arg_types),
+                             ffi_flags=ffi_flags)
 
 
     def grab_exc_value(self):
diff --git a/pypy/jit/backend/llsupport/descr.py b/pypy/jit/backend/llsupport/descr.py
--- a/pypy/jit/backend/llsupport/descr.py
+++ b/pypy/jit/backend/llsupport/descr.py
@@ -260,10 +260,12 @@
     _clsname = ''
     loop_token = None
     arg_classes = ''     # <-- annotation hack
+    ffi_flags = 0
 
-    def __init__(self, arg_classes, extrainfo=None):
+    def __init__(self, arg_classes, extrainfo=None, ffi_flags=0):
         self.arg_classes = arg_classes    # string of "r" and "i" (ref/int)
         self.extrainfo = extrainfo
+        self.ffi_flags = ffi_flags
 
     def __repr__(self):
         res = '%s(%s)' % (self.__class__.__name__, self.arg_classes)
@@ -284,6 +286,13 @@
     def get_extra_info(self):
         return self.extrainfo
 
+    def get_ffi_flags(self):
+        return self.ffi_flags
+
+    def get_call_conv(self):
+        from pypy.rlib.clibffi import get_call_conv
+        return get_call_conv(self.ffi_flags, True)
+
     def get_arg_types(self):
         return self.arg_classes
 
@@ -391,8 +400,8 @@
     """
     _clsname = 'DynamicIntCallDescr'
 
-    def __init__(self, arg_classes, result_size, result_sign, extrainfo=None):
-        BaseIntCallDescr.__init__(self, arg_classes, extrainfo)
+    def __init__(self, arg_classes, result_size, result_sign, extrainfo=None, ffi_flags=0):
+        BaseIntCallDescr.__init__(self, arg_classes, extrainfo, ffi_flags)
         assert isinstance(result_sign, bool)
         self._result_size = chr(result_size)
         self._result_sign = result_sign
diff --git a/pypy/jit/backend/llsupport/ffisupport.py b/pypy/jit/backend/llsupport/ffisupport.py
--- a/pypy/jit/backend/llsupport/ffisupport.py
+++ b/pypy/jit/backend/llsupport/ffisupport.py
@@ -8,7 +8,7 @@
 class UnsupportedKind(Exception):
     pass
 
-def get_call_descr_dynamic(cpu, ffi_args, ffi_result, extrainfo=None):
+def get_call_descr_dynamic(cpu, ffi_args, ffi_result, extrainfo=None, ffi_flags=0):
     """Get a call descr: the types of result and args are represented by
     rlib.libffi.types.*"""
     try:
@@ -20,18 +20,24 @@
     if reskind == history.INT:
         size = intmask(ffi_result.c_size)
         signed = is_ffi_type_signed(ffi_result)
-        return DynamicIntCallDescr(arg_classes, size, signed, extrainfo)
+        return DynamicIntCallDescr(arg_classes, size, signed, extrainfo,
+                                   ffi_flags=ffi_flags)
     elif reskind == history.REF:
-        return  NonGcPtrCallDescr(arg_classes, extrainfo)
+        return  NonGcPtrCallDescr(arg_classes, extrainfo,
+                                  ffi_flags=ffi_flags)
     elif reskind == history.FLOAT:
-        return FloatCallDescr(arg_classes, extrainfo)
+        return FloatCallDescr(arg_classes, extrainfo,
+                              ffi_flags=ffi_flags)
     elif reskind == history.VOID:
-        return VoidCallDescr(arg_classes, extrainfo)
+        return VoidCallDescr(arg_classes, extrainfo,
+                             ffi_flags=ffi_flags)
     elif reskind == 'L':
-        return LongLongCallDescr(arg_classes, extrainfo)
+        return LongLongCallDescr(arg_classes, extrainfo,
+                                 ffi_flags=ffi_flags)
     elif reskind == 'S':
         SingleFloatCallDescr = getCallDescrClass(rffi.FLOAT)
-        return SingleFloatCallDescr(arg_classes, extrainfo)
+        return SingleFloatCallDescr(arg_classes, extrainfo,
+                                    ffi_flags=ffi_flags)
     assert False
 
 def get_ffi_type_kind(cpu, ffi_type):
diff --git a/pypy/jit/backend/llsupport/llmodel.py b/pypy/jit/backend/llsupport/llmodel.py
--- a/pypy/jit/backend/llsupport/llmodel.py
+++ b/pypy/jit/backend/llsupport/llmodel.py
@@ -257,10 +257,10 @@
     def calldescrof(self, FUNC, ARGS, RESULT, extrainfo):
         return get_call_descr(self.gc_ll_descr, ARGS, RESULT, extrainfo)
 
-    def calldescrof_dynamic(self, ffi_args, ffi_result, extrainfo):
+    def calldescrof_dynamic(self, ffi_args, ffi_result, extrainfo, ffi_flags):
         from pypy.jit.backend.llsupport import ffisupport
         return ffisupport.get_call_descr_dynamic(self, ffi_args, ffi_result,
-                                                 extrainfo)
+                                                 extrainfo, ffi_flags)
 
     def get_overflow_error(self):
         ovf_vtable = self.cast_adr_to_int(self._ovf_error_vtable)
diff --git a/pypy/jit/backend/llsupport/regalloc.py b/pypy/jit/backend/llsupport/regalloc.py
--- a/pypy/jit/backend/llsupport/regalloc.py
+++ b/pypy/jit/backend/llsupport/regalloc.py
@@ -57,11 +57,13 @@
     all_regs              = []
     no_lower_byte_regs    = []
     save_around_call_regs = []
-    
+    frame_reg             = None
+
     def __init__(self, longevity, frame_manager=None, assembler=None):
         self.free_regs = self.all_regs[:]
         self.longevity = longevity
         self.reg_bindings = {}
+        self.bindings_to_frame_reg = {}
         self.position = -1
         self.frame_manager = frame_manager
         self.assembler = assembler
@@ -218,6 +220,10 @@
         self.reg_bindings[v] = loc
         return loc
 
+    def force_allocate_frame_reg(self, v):
+        """ Allocate the new variable v in the frame register."""
+        self.bindings_to_frame_reg[v] = None
+
     def force_spill_var(self, var):
         self._sync_var(var)
         try:
@@ -236,6 +242,8 @@
         try:
             return self.reg_bindings[box]
         except KeyError:
+            if box in self.bindings_to_frame_reg:
+                return self.frame_reg
             return self.frame_manager.loc(box)
 
     def return_constant(self, v, forbidden_vars=[], selected_reg=None):
@@ -264,8 +272,9 @@
         self._check_type(v)
         if isinstance(v, Const):
             return self.return_constant(v, forbidden_vars, selected_reg)
-        
         prev_loc = self.loc(v)
+        if prev_loc is self.frame_reg and selected_reg is None:
+            return prev_loc
         loc = self.force_allocate_reg(v, forbidden_vars, selected_reg,
                                       need_lower_byte=need_lower_byte)
         if prev_loc is not loc:
diff --git a/pypy/jit/backend/llsupport/test/test_ffisupport.py b/pypy/jit/backend/llsupport/test/test_ffisupport.py
--- a/pypy/jit/backend/llsupport/test/test_ffisupport.py
+++ b/pypy/jit/backend/llsupport/test/test_ffisupport.py
@@ -13,17 +13,19 @@
 
 def test_call_descr_dynamic():
     args = [types.sint, types.pointer]
-    descr = get_call_descr_dynamic(FakeCPU(), args, types.sint)
+    descr = get_call_descr_dynamic(FakeCPU(), args, types.sint, ffi_flags=42)
     assert isinstance(descr, DynamicIntCallDescr)
     assert descr.arg_classes == 'ii'
+    assert descr.get_ffi_flags() == 42
 
     args = [types.sint, types.double, types.pointer]
     descr = get_call_descr_dynamic(FakeCPU(), args, types.void)
     assert descr is None    # missing floats
     descr = get_call_descr_dynamic(FakeCPU(supports_floats=True),
-                                   args, types.void)
+                                   args, types.void, ffi_flags=43)
     assert isinstance(descr, VoidCallDescr)
     assert descr.arg_classes == 'ifi'
+    assert descr.get_ffi_flags() == 43
 
     descr = get_call_descr_dynamic(FakeCPU(), [], types.sint8)
     assert isinstance(descr, DynamicIntCallDescr)
@@ -39,14 +41,16 @@
         descr = get_call_descr_dynamic(FakeCPU(), [], types.slonglong)
         assert descr is None   # missing longlongs
         descr = get_call_descr_dynamic(FakeCPU(supports_longlong=True),
-                                       [], types.slonglong)
+                                       [], types.slonglong, ffi_flags=43)
         assert isinstance(descr, LongLongCallDescr)
+        assert descr.get_ffi_flags() == 43
     else:
         assert types.slonglong is types.slong
 
     descr = get_call_descr_dynamic(FakeCPU(), [], types.float)
     assert descr is None   # missing singlefloats
     descr = get_call_descr_dynamic(FakeCPU(supports_singlefloats=True),
-                                   [], types.float)
+                                   [], types.float, ffi_flags=44)
     SingleFloatCallDescr = getCallDescrClass(rffi.FLOAT)
     assert isinstance(descr, SingleFloatCallDescr)
+    assert descr.get_ffi_flags() == 44
diff --git a/pypy/jit/backend/test/runner_test.py b/pypy/jit/backend/test/runner_test.py
--- a/pypy/jit/backend/test/runner_test.py
+++ b/pypy/jit/backend/test/runner_test.py
@@ -468,7 +468,7 @@
             assert longlong.getrealfloat(x) == 3.5 - 42
 
     def test_call(self):
-        from pypy.rlib.libffi import types
+        from pypy.rlib.libffi import types, FUNCFLAG_CDECL
 
         def func_int(a, b):
             return a + b
@@ -497,7 +497,8 @@
             assert res.value == 2 * num
             # then, try it with the dynamic calldescr
             dyn_calldescr = cpu.calldescrof_dynamic([ffi_type, ffi_type], ffi_type,
-                                                    EffectInfo.MOST_GENERAL)
+                                                    EffectInfo.MOST_GENERAL,
+                                                    ffi_flags=FUNCFLAG_CDECL)
             res = self.execute_operation(rop.CALL,
                                          [funcbox, BoxInt(num), BoxInt(num)],
                                          'int', descr=dyn_calldescr)
@@ -1944,7 +1945,7 @@
         assert values == [1, 10]
 
     def test_call_to_c_function(self):
-        from pypy.rlib.libffi import CDLL, types, ArgChain
+        from pypy.rlib.libffi import CDLL, types, ArgChain, FUNCFLAG_CDECL
         from pypy.rpython.lltypesystem.ll2ctypes import libc_name
         libc = CDLL(libc_name)
         c_tolower = libc.getpointer('tolower', [types.uchar], types.sint)
@@ -1955,7 +1956,8 @@
         func_adr = llmemory.cast_ptr_to_adr(c_tolower.funcsym)
         funcbox = ConstInt(heaptracker.adr2int(func_adr))
         calldescr = cpu.calldescrof_dynamic([types.uchar], types.sint,
-                                            EffectInfo.MOST_GENERAL)
+                                            EffectInfo.MOST_GENERAL,
+                                            ffi_flags=FUNCFLAG_CDECL)
         i1 = BoxInt()
         i2 = BoxInt()
         tok = BoxInt()
@@ -2012,7 +2014,8 @@
         calldescr = cpu.calldescrof_dynamic([types.pointer, types_size_t,
                                              types_size_t, types.pointer],
                                             types.void,
-                                            EffectInfo.MOST_GENERAL)
+                                            EffectInfo.MOST_GENERAL,
+                                            ffi_flags=clibffi.FUNCFLAG_CDECL)
         i0 = BoxInt()
         i1 = BoxInt()
         i2 = BoxInt()
@@ -2038,6 +2041,62 @@
         assert len(glob.lst) > 0
         lltype.free(raw, flavor='raw')
 
+    def test_call_to_winapi_function(self):
+        from pypy.rlib.clibffi import _WIN32, FUNCFLAG_STDCALL
+        if not _WIN32:
+            py.test.skip("Windows test only")
+        from pypy.rlib.libffi import CDLL, types, ArgChain
+        from pypy.rlib.rwin32 import DWORD
+        libc = CDLL('KERNEL32')
+        c_GetCurrentDir = libc.getpointer('GetCurrentDirectoryA',
+                                          [types.ulong, types.pointer],
+                                          types.ulong)
+
+        cwd = os.getcwd()
+        buflen = len(cwd) + 10
+        buffer = lltype.malloc(rffi.CCHARP.TO, buflen, flavor='raw')
+        argchain = ArgChain().arg(rffi.cast(DWORD, buflen)).arg(buffer)
+        res = c_GetCurrentDir.call(argchain, DWORD)
+        assert rffi.cast(lltype.Signed, res) == len(cwd)
+        assert rffi.charp2strn(buffer, buflen) == cwd
+        lltype.free(buffer, flavor='raw')
+
+        cpu = self.cpu
+        func_adr = llmemory.cast_ptr_to_adr(c_GetCurrentDir.funcsym)
+        funcbox = ConstInt(heaptracker.adr2int(func_adr))
+        calldescr = cpu.calldescrof_dynamic([types.ulong, types.pointer],
+                                            types.ulong,
+                                            EffectInfo.MOST_GENERAL,
+                                            ffi_flags=FUNCFLAG_STDCALL)
+        i1 = BoxInt()
+        i2 = BoxInt()
+        faildescr = BasicFailDescr(1)
+        # if the stdcall convention is ignored, then ESP is wrong after the
+        # call: 8 bytes too much.  If we repeat the call often enough, crash.
+        ops = []
+        for i in range(50):
+            i3 = BoxInt()
+            ops += [
+                ResOperation(rop.CALL_RELEASE_GIL, [funcbox, i1, i2], i3,
+                             descr=calldescr),
+                ResOperation(rop.GUARD_NOT_FORCED, [], None, descr=faildescr),
+                ]
+            ops[-1].setfailargs([])
+        ops += [
+            ResOperation(rop.FINISH, [i3], None, descr=BasicFailDescr(0))
+        ]
+        looptoken = LoopToken()
+        self.cpu.compile_loop([i1, i2], ops, looptoken)
+
+        buffer = lltype.malloc(rffi.CCHARP.TO, buflen, flavor='raw')
+        self.cpu.set_future_value_int(0, buflen)
+        self.cpu.set_future_value_int(1, rffi.cast(lltype.Signed, buffer))
+        fail = self.cpu.execute_token(looptoken)
+        assert fail.identifier == 0
+        assert self.cpu.get_latest_value_int(0) == len(cwd)
+        assert rffi.charp2strn(buffer, buflen) == cwd
+        lltype.free(buffer, flavor='raw')
+
     def test_guard_not_invalidated(self):
         cpu = self.cpu
         i0 = BoxInt()
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
@@ -34,6 +34,7 @@
 from pypy.rlib.debug import (debug_print, debug_start, debug_stop,
                              have_debug_prints)
 from pypy.rlib import rgc
+from pypy.rlib.clibffi import FFI_DEFAULT_ABI
 from pypy.jit.backend.x86.jump import remap_frame_layout
 from pypy.jit.metainterp.history import ConstInt, BoxInt
 from pypy.jit.codewriter.effectinfo import EffectInfo
@@ -956,6 +957,7 @@
         if (isinstance(from_loc, RegLoc) and from_loc.is_xmm) or (isinstance(to_loc, RegLoc) and to_loc.is_xmm):
             self.mc.MOVSD(to_loc, from_loc)
         else:
+            assert to_loc is not ebp
             self.mc.MOV(to_loc, from_loc)
 
     regalloc_mov = mov # legacy interface
@@ -1120,7 +1122,7 @@
         return genop_cmp_guard_float
 
     def _emit_call(self, force_index, x, arglocs, start=0, tmp=eax,
-                   argtypes=None):
+                   argtypes=None, callconv=FFI_DEFAULT_ABI):
         if IS_X86_64:
             return self._emit_call_64(force_index, x, arglocs, start, argtypes)
 
@@ -1149,6 +1151,16 @@
         # x is a location
         self.mc.CALL(x)
         self.mark_gc_roots(force_index)
+        #
+        if callconv != FFI_DEFAULT_ABI:
+            self._fix_stdcall(callconv, p)
+
+    def _fix_stdcall(self, callconv, p):
+        from pypy.rlib.clibffi import FFI_STDCALL
+        assert callconv == FFI_STDCALL
+        # it's a bit stupid, but we're just going to cancel the fact that
+        # the called function just added 'p' to ESP, by subtracting it again.
+        self.mc.SUB_ri(esp.value, p)
 
     def _emit_call_64(self, force_index, x, arglocs, start, argtypes):
         src_locs = []
@@ -2127,7 +2139,8 @@
             tmp = eax
 
         self._emit_call(force_index, x, arglocs, 3, tmp=tmp,
-                        argtypes=op.getdescr().get_arg_types())
+                        argtypes=op.getdescr().get_arg_types(),
+                        callconv=op.getdescr().get_call_conv())
 
         if IS_X86_32 and isinstance(resloc, StackLoc) and resloc.width == 8:
             # a float or a long long return
@@ -2498,11 +2511,6 @@
 
     genop_discard_cond_call_gc_wb_array = genop_discard_cond_call_gc_wb
 
-    def genop_force_token(self, op, arglocs, resloc):
-        # RegAlloc.consider_force_token ensures this:
-        assert isinstance(resloc, RegLoc)
-        self.mc.LEA_rb(resloc.value, FORCE_INDEX_OFS)
-
     def not_implemented_op_discard(self, op, arglocs):
         not_implemented("not implemented operation: %s" % op.getopname())
 
diff --git a/pypy/jit/backend/x86/regalloc.py b/pypy/jit/backend/x86/regalloc.py
--- a/pypy/jit/backend/x86/regalloc.py
+++ b/pypy/jit/backend/x86/regalloc.py
@@ -29,6 +29,7 @@
     all_regs = [eax, ecx, edx, ebx, esi, edi]
     no_lower_byte_regs = [esi, edi]
     save_around_call_regs = [eax, edx, ecx]
+    frame_reg = ebp
 
     REGLOC_TO_GCROOTMAP_REG_INDEX = {
         ebx: 1,
@@ -312,8 +313,11 @@
                     self.fm.frame_bindings[arg] = loc
             else:
                 if isinstance(loc, RegLoc):
-                    self.rm.reg_bindings[arg] = loc
-                    used[loc] = None
+                    if loc is ebp:
+                        self.rm.bindings_to_frame_reg[arg] = None
+                    else:
+                        self.rm.reg_bindings[arg] = loc
+                        used[loc] = None
                 else:
                     self.fm.frame_bindings[arg] = loc
         self.rm.free_regs = []
@@ -1358,8 +1362,8 @@
                                             self.assembler.datablockwrapper)
 
     def consider_force_token(self, op):
-        loc = self.rm.force_allocate_reg(op.result)
-        self.Perform(op, [], loc)
+        # the FORCE_TOKEN operation returns directly 'ebp'
+        self.rm.force_allocate_frame_reg(op.result)
 
     def not_implemented_op(self, op):
         not_implemented("not implemented operation: %s" % op.getopname())
diff --git a/pypy/jit/backend/x86/runner.py b/pypy/jit/backend/x86/runner.py
--- a/pypy/jit/backend/x86/runner.py
+++ b/pypy/jit/backend/x86/runner.py
@@ -119,7 +119,8 @@
             setitem(index, null)
 
     def get_latest_force_token(self):
-        return self.assembler.fail_ebp + FORCE_INDEX_OFS
+        # the FORCE_TOKEN operation and this helper both return 'ebp'.
+        return self.assembler.fail_ebp
 
     def execute_token(self, executable_token):
         addr = executable_token._x86_bootstrap_code
@@ -153,8 +154,9 @@
                                        flavor='raw', zero=True,
                                        immortal=True)
 
-    def force(self, addr_of_force_index):
+    def force(self, addr_of_force_token):
         TP = rffi.CArrayPtr(lltype.Signed)
+        addr_of_force_index = addr_of_force_token + FORCE_INDEX_OFS
         fail_index = rffi.cast(TP, addr_of_force_index)[0]
         assert fail_index >= 0, "already forced!"
         faildescr = self.get_fail_descr_from_number(fail_index)
@@ -164,7 +166,7 @@
         # start of "no gc operation!" block
         fail_index_2 = self.assembler.grab_frame_values(
             bytecode,
-            addr_of_force_index - FORCE_INDEX_OFS,
+            addr_of_force_token,
             self.all_null_registers)
         self.assembler.leave_jitted_hook()
         # end of "no gc operation!" block
diff --git a/pypy/jit/backend/x86/rx86.py b/pypy/jit/backend/x86/rx86.py
--- a/pypy/jit/backend/x86/rx86.py
+++ b/pypy/jit/backend/x86/rx86.py
@@ -527,6 +527,7 @@
 
     NOP = insn('\x90')
     RET = insn('\xC3')
+    RET16_i = insn('\xC2', immediate(1, 'h'))
 
     PUSH_r = insn(rex_nw, register(1), '\x50')
     PUSH_b = insn(rex_nw, '\xFF', orbyte(6<<3), stack_bp(1))
diff --git a/pypy/jit/backend/x86/test/test_runner.py b/pypy/jit/backend/x86/test/test_runner.py
--- a/pypy/jit/backend/x86/test/test_runner.py
+++ b/pypy/jit/backend/x86/test/test_runner.py
@@ -433,6 +433,88 @@
                 ops_offset[operations[2]] <=
                 ops_offset[None])
 
+    def test_calling_convention(self, monkeypatch):
+        if WORD != 4:
+            py.test.skip("32-bit only test")
+        from pypy.jit.backend.x86.regloc import eax, edx
+        from pypy.jit.backend.x86 import codebuf
+        from pypy.jit.codewriter.effectinfo import EffectInfo
+        from pypy.rlib.libffi import types, clibffi
+        had_stdcall = hasattr(clibffi, 'FFI_STDCALL')
+        if not had_stdcall:    # not running on Windows, but we can still test
+            monkeypatch.setattr(clibffi, 'FFI_STDCALL', 12345, raising=False)
+        #
+        for ffi in [clibffi.FFI_DEFAULT_ABI, clibffi.FFI_STDCALL]:
+            cpu = self.cpu
+            mc = codebuf.MachineCodeBlockWrapper()
+            mc.MOV_rs(eax.value, 4)      # argument 1
+            mc.MOV_rs(edx.value, 40)     # argument 10
+            mc.SUB_rr(eax.value, edx.value)     # return arg1 - arg10
+            if ffi == clibffi.FFI_DEFAULT_ABI:
+                mc.RET()
+            else:
+                mc.RET16_i(40)
+            rawstart = mc.materialize(cpu.asmmemmgr, [])
+            #
+            calldescr = cpu.calldescrof_dynamic([types.slong] * 10,
+                                                types.slong,
+                                                EffectInfo.MOST_GENERAL,
+                                                ffi_flags=-1)
+            calldescr.get_call_conv = lambda: ffi      # <==== hack
+            funcbox = ConstInt(rawstart)
+            i1 = BoxInt()
+            i2 = BoxInt()
+            i3 = BoxInt()
+            i4 = BoxInt()
+            i5 = BoxInt()
+            i6 = BoxInt()
+            c = ConstInt(-1)
+            faildescr = BasicFailDescr(1)
+            # we must call it repeatedly: if the stack pointer gets increased
+            # by 40 bytes by the STDCALL call, and if we don't expect it,
+            # then we are going to get our stack emptied unexpectedly by
+            # several repeated calls
+            ops = [
+            ResOperation(rop.CALL_RELEASE_GIL,
+                         [funcbox, i1, c, c, c, c, c, c, c, c, i2],
+                         i3, descr=calldescr),
+            ResOperation(rop.GUARD_NOT_FORCED, [], None, descr=faildescr),
+
+            ResOperation(rop.CALL_RELEASE_GIL,
+                         [funcbox, i1, c, c, c, c, c, c, c, c, i2],
+                         i4, descr=calldescr),
+            ResOperation(rop.GUARD_NOT_FORCED, [], None, descr=faildescr),
+
+            ResOperation(rop.CALL_RELEASE_GIL,
+                         [funcbox, i1, c, c, c, c, c, c, c, c, i2],
+                         i5, descr=calldescr),
+            ResOperation(rop.GUARD_NOT_FORCED, [], None, descr=faildescr),
+
+            ResOperation(rop.CALL_RELEASE_GIL,
+                         [funcbox, i1, c, c, c, c, c, c, c, c, i2],
+                         i6, descr=calldescr),
+            ResOperation(rop.GUARD_NOT_FORCED, [], None, descr=faildescr),
+
+            ResOperation(rop.FINISH, [i3, i4, i5, i6], None,
+                         descr=BasicFailDescr(0))
+            ]
+            ops[1].setfailargs([])
+            ops[3].setfailargs([])
+            ops[5].setfailargs([])
+            ops[7].setfailargs([])
+            looptoken = LoopToken()
+            self.cpu.compile_loop([i1, i2], ops, looptoken)
+
+            self.cpu.set_future_value_int(0, 123450)
+            self.cpu.set_future_value_int(1, 123408)
+            fail = self.cpu.execute_token(looptoken)
+            assert fail.identifier == 0
+            assert self.cpu.get_latest_value_int(0) == 42
+            assert self.cpu.get_latest_value_int(1) == 42
+            assert self.cpu.get_latest_value_int(2) == 42
+            assert self.cpu.get_latest_value_int(3) == 42
+
+
 class TestDebuggingAssembler(object):
     def setup_method(self, meth):
         self.cpu = CPU(rtyper=None, stats=FakeStats())
diff --git a/pypy/jit/codewriter/support.py b/pypy/jit/codewriter/support.py
--- a/pypy/jit/codewriter/support.py
+++ b/pypy/jit/codewriter/support.py
@@ -91,9 +91,12 @@
     reds_v = op.args[2+numgreens:]
     assert len(reds_v) == numreds
     #
-    def _sort(args_v):
+    def _sort(args_v, is_green):
         from pypy.jit.metainterp.history import getkind
         lst = [v for v in args_v if v.concretetype is not lltype.Void]
+        if is_green:
+            assert len(lst) == len(args_v), (
+                "not supported so far: 'greens' variables contain Void")
         _kind2count = {'int': 1, 'ref': 2, 'float': 3}
         lst2 = sorted(lst, key=lambda v: _kind2count[getkind(v.concretetype)])
         # a crash here means that you have to reorder the variable named in
@@ -102,7 +105,7 @@
         assert lst == lst2
         return lst
     #
-    return (_sort(greens_v), _sort(reds_v))
+    return (_sort(greens_v, True), _sort(reds_v, False))
 
 def maybe_on_top_of_llinterp(rtyper, fnptr):
     # Run a generated graph on top of the llinterp for testing.
diff --git a/pypy/jit/metainterp/optimizeopt/fficall.py b/pypy/jit/metainterp/optimizeopt/fficall.py
--- a/pypy/jit/metainterp/optimizeopt/fficall.py
+++ b/pypy/jit/metainterp/optimizeopt/fficall.py
@@ -18,26 +18,27 @@
     def __init__(self, funcval, cpu, prepare_op):
         self.funcval = funcval
         self.opargs = []
-        argtypes, restype = self._get_signature(funcval)
+        argtypes, restype, flags = self._get_signature(funcval)
         self.descr = cpu.calldescrof_dynamic(argtypes, restype,
-                                             EffectInfo.MOST_GENERAL)
+                                             EffectInfo.MOST_GENERAL,
+                                             ffi_flags=flags)
         # ^^^ may be None if unsupported
         self.prepare_op = prepare_op
         self.delayed_ops = []
 
     def _get_signature(self, funcval):
         """
-        given the funcval, return a tuple (argtypes, restype), where the
-        actuall types are libffi.types.*
+        given the funcval, return a tuple (argtypes, restype, flags), where
+        the actuall types are libffi.types.*
 
         The implementation is tricky because we have three possible cases:
 
         - translated: the easiest case, we can just cast back the pointer to
-          the original Func instance and read .argtypes and .restype
+          the original Func instance and read .argtypes, .restype and .flags
 
         - completely untranslated: this is what we get from test_optimizeopt
           tests. funcval contains a FakeLLObject whose _fake_class is Func,
-          and we can just get .argtypes and .restype
+          and we can just get .argtypes, .restype and .flags
 
         - partially translated: this happens when running metainterp tests:
           funcval contains the low-level equivalent of a Func, and thus we
@@ -49,10 +50,10 @@
         llfunc = funcval.box.getref_base()
         if we_are_translated():
             func = cast_base_ptr_to_instance(Func, llfunc)
-            return func.argtypes, func.restype
+            return func.argtypes, func.restype, func.flags
         elif getattr(llfunc, '_fake_class', None) is Func:
             # untranslated
-            return llfunc.argtypes, llfunc.restype
+            return llfunc.argtypes, llfunc.restype, llfunc.flags
         else:
             # partially translated
             # llfunc contains an opaque pointer to something like the following:
@@ -63,7 +64,7 @@
             # because we don't have the exact TYPE to cast to.  Instead, we
             # just fish it manually :-(
             f = llfunc._obj.container
-            return f.inst_argtypes, f.inst_restype
+            return f.inst_argtypes, f.inst_restype, f.inst_flags
 
 
 class OptFfiCall(Optimization):
diff --git a/pypy/jit/metainterp/optimizeopt/heap.py b/pypy/jit/metainterp/optimizeopt/heap.py
--- a/pypy/jit/metainterp/optimizeopt/heap.py
+++ b/pypy/jit/metainterp/optimizeopt/heap.py
@@ -25,7 +25,7 @@
         #      'cached_fields'.
         #
         self._cached_fields = {}
-        self._cached_fields_getfield_op = {}        
+        self._cached_fields_getfield_op = {}
         self._lazy_setfield = None
         self._lazy_setfield_registered = False
 
@@ -75,7 +75,7 @@
     def remember_field_value(self, structvalue, fieldvalue, getfield_op=None):
         assert self._lazy_setfield is None
         self._cached_fields[structvalue] = fieldvalue
-        self._cached_fields_getfield_op[structvalue] = getfield_op        
+        self._cached_fields_getfield_op[structvalue] = getfield_op
 
     def force_lazy_setfield(self, optheap, can_cache=True):
         op = self._lazy_setfield
@@ -163,7 +163,7 @@
 
     def new(self):
         return OptHeap()
-        
+
     def produce_potential_short_preamble_ops(self, sb):
         descrkeys = self.cached_fields.keys()
         if not we_are_translated():
diff --git a/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py b/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py
--- a/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py
+++ b/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py
@@ -4711,6 +4711,33 @@
         """
         self.optimize_loop(ops, expected)
 
+    def test_forced_virtuals_aliasing(self):
+        ops = """
+        [i0, i1]
+        p0 = new(descr=ssize)
+        p1 = new(descr=ssize)
+        escape(p0)
+        escape(p1)
+        setfield_gc(p0, i0, descr=adescr)
+        setfield_gc(p1, i1, descr=adescr)
+        i2 = getfield_gc(p0, descr=adescr)
+        jump(i2, i2)
+        """
+        expected = """
+        [i0, i1]
+        p0 = new(descr=ssize)
+        escape(p0)
+        p1 = new(descr=ssize)
+        escape(p1)
+        setfield_gc(p0, i0, descr=adescr)
+        setfield_gc(p1, i1, descr=adescr)
+        jump(i0, i0)
+        """
+        py.test.skip("not implemented")
+        # setfields on things that used to be virtual still can't alias each
+        # other
+        self.optimize_loop(ops, expected)
+
 
 class TestLLtype(BaseTestOptimizeBasic, LLtypeMixin):
     pass
diff --git a/pypy/jit/metainterp/optimizeopt/test/test_optimizefficall.py b/pypy/jit/metainterp/optimizeopt/test/test_optimizefficall.py
--- a/pypy/jit/metainterp/optimizeopt/test/test_optimizefficall.py
+++ b/pypy/jit/metainterp/optimizeopt/test/test_optimizefficall.py
@@ -14,12 +14,15 @@
     can check that the signature of a call is really what you want.
     """
 
-    def __init__(self, arg_types, typeinfo):
+    def __init__(self, arg_types, typeinfo, flags):
         self.arg_types = arg_types
         self.typeinfo = typeinfo   # return type
+        self.flags = flags
 
     def __eq__(self, other):
-        return self.arg_types == other.arg_types and self.typeinfo == other.typeinfo
+        return (self.arg_types == other.arg_types and
+                self.typeinfo == other.typeinfo and
+                self.flags == other.get_ffi_flags())
 
 class FakeLLObject(object):
 
@@ -41,14 +44,17 @@
         vable_token_descr = LLtypeMixin.valuedescr
         valuedescr = LLtypeMixin.valuedescr
 
-        int_float__int = MyCallDescr('if', 'i')
+        int_float__int_42 = MyCallDescr('if', 'i', 42)
+        int_float__int_43 = MyCallDescr('if', 'i', 43)
         funcptr = FakeLLObject()
         func = FakeLLObject(_fake_class=Func,
                             argtypes=[types.sint, types.double],
-                            restype=types.sint)
+                            restype=types.sint,
+                            flags=42)
         func2 = FakeLLObject(_fake_class=Func,
                              argtypes=[types.sint, types.double],
-                             restype=types.sint)
+                             restype=types.sint,
+                             flags=43)
         #
         def calldescr(cpu, FUNC, oopspecindex, extraeffect=None):
             if extraeffect == EffectInfo.EF_RANDOM_EFFECTS:
@@ -83,7 +89,7 @@
         """
         expected = """
         [i0, f1]
-        i3 = call_release_gil(12345, i0, f1, descr=int_float__int)
+        i3 = call_release_gil(12345, i0, f1, descr=int_float__int_42)
         guard_not_forced() []
         guard_no_exception() []
         jump(i3, f1)
@@ -123,7 +129,7 @@
         [i0, f1, p2]
         i4 = force_token()
         setfield_gc(p2, i4, descr=vable_token_descr)
-        i3 = call_release_gil(12345, i0, f1, descr=int_float__int)
+        i3 = call_release_gil(12345, i0, f1, descr=int_float__int_42)
         guard_not_forced() [p2]
         guard_no_exception() [p2]
         jump(i3, f1, p2)
@@ -220,7 +226,7 @@
         call(0, ConstPtr(func),                        descr=libffi_prepare)
         #
         # this "nested" call is nicely optimized
-        i4 = call_release_gil(67890, i0, f1, descr=int_float__int)
+        i4 = call_release_gil(67890, i0, f1, descr=int_float__int_43)
         guard_not_forced() []
         guard_no_exception() []
         #
@@ -265,7 +271,7 @@
         expected = """
         [i0, f1, p2]
         setfield_gc(p2, i0, descr=valuedescr)
-        i3 = call_release_gil(12345, i0, f1, descr=int_float__int)
+        i3 = call_release_gil(12345, i0, f1, descr=int_float__int_42)
         guard_not_forced() []
         guard_no_exception() []
         jump(i3, f1, p2)
diff --git a/pypy/jit/metainterp/test/test_warmspot.py b/pypy/jit/metainterp/test/test_warmspot.py
--- a/pypy/jit/metainterp/test/test_warmspot.py
+++ b/pypy/jit/metainterp/test/test_warmspot.py
@@ -252,6 +252,41 @@
         self.check_loops({'int_sub': 1, 'int_gt': 1, 'guard_true': 1,
                           'jump': 1})
 
+    def test_void_red_variable(self):
+        mydriver = JitDriver(greens=[], reds=['a', 'm'])
+        def f1(m):
+            a = None
+            while m > 0:
+                mydriver.jit_merge_point(a=a, m=m)
+                m = m - 1
+                if m == 10:
+                    pass   # other case
+        self.meta_interp(f1, [18])
+
+    def test_bug_constant_rawptrs(self):
+        py.test.skip("crashes because a is a constant")
+        from pypy.rpython.lltypesystem import lltype, rffi
+        mydriver = JitDriver(greens=['a'], reds=['m'])
+        def f1(m):
+            a = lltype.nullptr(rffi.VOIDP.TO)
+            while m > 0:
+                mydriver.jit_merge_point(a=a, m=m)
+                m = m - 1
+        self.meta_interp(f1, [18])
+
+    def test_bug_rawptrs(self):
+        from pypy.rpython.lltypesystem import lltype, rffi
+        mydriver = JitDriver(greens=['a'], reds=['m'])
+        def f1(m):
+            a = lltype.malloc(rffi.VOIDP.TO, 5, flavor='raw')
+            while m > 0:
+                mydriver.jit_merge_point(a=a, m=m)
+                m = m - 1
+                if m == 10:
+                    pass
+            lltype.free(a, flavor='raw')
+        self.meta_interp(f1, [18])
+
 
 class TestLLWarmspot(WarmspotTests, LLJitMixin):
     CPUClass = runner.LLtypeCPU
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
@@ -130,8 +130,15 @@
     results = _find_jit_marker(graphs, 'jit_merge_point')
     if not results:
         raise Exception("no jit_merge_point found!")
+    seen = set([graph for graph, block, pos in results])
+    assert len(seen) == len(results), (
+        "found several jit_merge_points in the same graph")
     return results
 
+def locate_jit_merge_point(graph):
+    [(graph, block, pos)] = find_jit_merge_points([graph])
+    return block, pos, block.operations[pos]
+
 def find_set_param(graphs):
     return _find_jit_marker(graphs, 'set_param')
 
@@ -235,7 +242,7 @@
     def split_graph_and_record_jitdriver(self, graph, block, pos):
         op = block.operations[pos]
         jd = JitDriverStaticData()
-        jd._jit_merge_point_pos = (graph, op)
+        jd._jit_merge_point_in = graph
         args = op.args[2:]
         s_binding = self.translator.annotator.binding
         jd._portal_args_s = [s_binding(v) for v in args]
@@ -245,7 +252,8 @@
         graph.startblock = support.split_before_jit_merge_point(*jmpp)
         graph.startblock.isstartblock = True
         # a crash in the following checkgraph() means that you forgot
-        # to list some variable in greens=[] or reds=[] in JitDriver.
+        # to list some variable in greens=[] or reds=[] in JitDriver,
+        # or that a jit_merge_point() takes a constant as an argument.
         checkgraph(graph)
         for v in graph.getargs():
             assert isinstance(v, Variable)
@@ -503,7 +511,8 @@
             self.make_args_specification(jd)
 
     def make_args_specification(self, jd):
-        graph, op = jd._jit_merge_point_pos
+        graph = jd._jit_merge_point_in
+        _, _, op = locate_jit_merge_point(graph)
         greens_v, reds_v = support.decode_hp_hint_args(op)
         ALLARGS = [v.concretetype for v in (greens_v + reds_v)]
         jd._green_args_spec = [v.concretetype for v in greens_v]
@@ -551,7 +560,7 @@
             assert jitdriver in sublists, \
                    "can_enter_jit with no matching jit_merge_point"
             jd, sublist = sublists[jitdriver]
-            origportalgraph = jd._jit_merge_point_pos[0]
+            origportalgraph = jd._jit_merge_point_in
             if graph is not origportalgraph:
                 sublist.append((graph, block, index))
                 jd.no_loop_header = False
@@ -581,7 +590,7 @@
             can_enter_jits = [(jd.portal_graph, jd.portal_graph.startblock, 0)]
 
         for graph, block, index in can_enter_jits:
-            if graph is jd._jit_merge_point_pos[0]:
+            if graph is jd._jit_merge_point_in:
                 continue
 
             op = block.operations[index]
@@ -639,7 +648,7 @@
         #           while 1:
         #               more stuff
         #
-        origportalgraph = jd._jit_merge_point_pos[0]
+        origportalgraph = jd._jit_merge_point_in
         portalgraph = jd.portal_graph
         PORTALFUNC = jd._PORTAL_FUNCTYPE
 
@@ -655,11 +664,13 @@
         portalfunc_ARGS = []
         nums = {}
         for i, ARG in enumerate(PORTALFUNC.ARGS):
+            kind = history.getkind(ARG)
+            assert kind != 'void'
             if i < len(jd.jitdriver.greens):
                 color = 'green'
             else:
                 color = 'red'
-            attrname = '%s_%s' % (color, history.getkind(ARG))
+            attrname = '%s_%s' % (color, kind)
             count = nums.get(attrname, 0)
             nums[attrname] = count + 1
             portalfunc_ARGS.append((ARG, attrname, count))
@@ -791,14 +802,7 @@
         # ____________________________________________________________
         # Now mutate origportalgraph to end with a call to portal_runner_ptr
         #
-        _, op = jd._jit_merge_point_pos
-        for origblock in origportalgraph.iterblocks():
-            if op in origblock.operations:
-                break
-        else:
-            assert False, "lost the operation %r in the graph %r" % (
-                op, origportalgraph)
-        origindex = origblock.operations.index(op)
+        origblock, origindex, op = locate_jit_merge_point(origportalgraph)
         assert op.opname == 'jit_marker'
         assert op.args[0].value == 'jit_merge_point'
         greens_v, reds_v = support.decode_hp_hint_args(op)
diff --git a/pypy/jit/metainterp/warmstate.py b/pypy/jit/metainterp/warmstate.py
--- a/pypy/jit/metainterp/warmstate.py
+++ b/pypy/jit/metainterp/warmstate.py
@@ -124,7 +124,7 @@
     # Hash of lltype or ootype object.
     # Only supports strings, unicodes and regular instances,
     # as well as primitives that can meaningfully be cast to Signed.
-    if isinstance(TYPE, lltype.Ptr):
+    if isinstance(TYPE, lltype.Ptr) and TYPE.TO._gckind == 'gc':
         if TYPE.TO is rstr.STR or TYPE.TO is rstr.UNICODE:
             return rstr.LLHelpers.ll_strhash(x)    # assumed not null
         else:
@@ -140,7 +140,7 @@
         else:
             return 0
     else:
-        return lltype.cast_primitive(lltype.Signed, x)
+        return rffi.cast(lltype.Signed, x)
 
 @specialize.ll_and_arg(3)
 def set_future_value(cpu, j, value, typecode):
diff --git a/pypy/module/__builtin__/functional.py b/pypy/module/__builtin__/functional.py
--- a/pypy/module/__builtin__/functional.py
+++ b/pypy/module/__builtin__/functional.py
@@ -292,7 +292,7 @@
                 raise
             break
         new_frame = space.createframe(code, w_func.w_func_globals,
-                                      w_func.closure)
+                                      w_func)
         new_frame.locals_stack_w[0] = w_item
         w_res = new_frame.run()
         result_w.append(w_res)
diff --git a/pypy/module/_codecs/interp_codecs.py b/pypy/module/_codecs/interp_codecs.py
--- a/pypy/module/_codecs/interp_codecs.py
+++ b/pypy/module/_codecs/interp_codecs.py
@@ -687,11 +687,15 @@
 # support for the "string escape" codec
 # This is a bytes-to bytes transformation
 
- at unwrap_spec(errors='str_or_None')
-def escape_encode(space, w_string, errors='strict'):
-    w_repr = space.repr(w_string)
-    w_result = space.getslice(w_repr, space.wrap(1), space.wrap(-1))
-    return space.newtuple([w_result, space.len(w_string)])
+ at unwrap_spec(data=str, errors='str_or_None')
+def escape_encode(space, data, errors='strict'):
+    from pypy.objspace.std.stringobject import string_escape_encode
+    result = string_escape_encode(data, quote="'")
+    start = 1
+    end = len(result) - 1
+    assert end >= 0
+    w_result = space.wrap(result[start:end])
+    return space.newtuple([w_result, space.wrap(len(data))])
 
 @unwrap_spec(data=str, errors='str_or_None')
 def escape_decode(space, data, errors='strict'):
diff --git a/pypy/module/_codecs/test/test_codecs.py b/pypy/module/_codecs/test/test_codecs.py
--- a/pypy/module/_codecs/test/test_codecs.py
+++ b/pypy/module/_codecs/test/test_codecs.py
@@ -102,7 +102,6 @@
     
     def test_indexerror(self):
         test =   "\\"     # trailing backslash
-             
         raises (ValueError, test.decode,'string-escape')
 
     def test_charmap_decode(self):
@@ -292,6 +291,10 @@
         assert '\\0f'.decode('string_escape') == chr(0) + 'f'
         assert '\\08'.decode('string_escape') == chr(0) + '8'
 
+    def test_escape_encode(self):
+        assert '"'.encode('string_escape') == '"'
+        assert "'".encode('string_escape') == "\\'"
+
     def test_decode_utf8_different_case(self):
         constant = u"a"
         assert constant.encode("utf-8") == constant.encode("UTF-8")
diff --git a/pypy/module/_continuation/interp_continuation.py b/pypy/module/_continuation/interp_continuation.py
--- a/pypy/module/_continuation/interp_continuation.py
+++ b/pypy/module/_continuation/interp_continuation.py
@@ -43,11 +43,11 @@
     def switch(self, w_to):
         to = self.space.interp_w(W_Continulet, w_to, can_be_None=True)
         if to is not None:
-            if self is to:    # double-switch to myself: no-op
-                return get_result()
             if to.sthread is None:
                 start_state.clear()
                 raise geterror(self.space, "continulet not initialized yet")
+            if self is to:    # double-switch to myself: no-op
+                return get_result()
         if self.sthread is None:
             start_state.clear()
             raise geterror(self.space, "continulet not initialized yet")
diff --git a/pypy/module/_rawffi/test/test__rawffi.py b/pypy/module/_rawffi/test/test__rawffi.py
--- a/pypy/module/_rawffi/test/test__rawffi.py
+++ b/pypy/module/_rawffi/test/test__rawffi.py
@@ -639,33 +639,6 @@
         a1.free()
         cb.free()
 
-    def test_another_callback_in_stackless(self):
-        try:
-            import _stackless
-        except ImportError:
-            skip("only valid in a stackless pypy-c")
-
-        import _rawffi
-        lib = _rawffi.CDLL(self.lib_name)
-        runcallback = lib.ptr('runcallback', ['P'], 'q')
-        def callback():
-            co = _stackless.coroutine()
-            def f():
-                pass
-            try:
-                co.bind(f)
-                co.switch()
-            except RuntimeError:
-                return 1<<42
-            return -5
-
-        cb = _rawffi.CallbackPtr(callback, [], 'q')
-        a1 = cb.byptr()
-        res = runcallback(a1)
-        assert res[0] == 1<<42
-        a1.free()
-        cb.free()
-
     def test_raising_callback(self):
         import _rawffi, sys
         import StringIO
diff --git a/pypy/module/_stackless/__init__.py b/pypy/module/_stackless/__init__.py
deleted file mode 100644
--- a/pypy/module/_stackless/__init__.py
+++ /dev/null
@@ -1,36 +0,0 @@
-# Package initialisation
-from pypy.interpreter.mixedmodule import MixedModule
-
-class Module(MixedModule):
-    """
-    This module implements Stackless for applications.
-    """
-
-    appleveldefs = {
-        'GreenletExit' : 'app_greenlet.GreenletExit',
-        'GreenletError' : 'app_greenlet.GreenletError',
-    }
-
-    interpleveldefs = {
-        'tasklet'    : 'interp_stackless.tasklet',
-        'coroutine'  : 'interp_coroutine.AppCoroutine',
-        'greenlet'   : 'interp_greenlet.AppGreenlet',
-        'usercostate': 'interp_composable_coroutine.W_UserCoState',
-        '_return_main' : 'interp_coroutine.return_main',
-        'get_stack_depth_limit': 'interp_coroutine.get_stack_depth_limit',
-        'set_stack_depth_limit': 'interp_coroutine.set_stack_depth_limit',
-    }
-
-    def setup_after_space_initialization(self):
-        # post-installing classmethods/staticmethods which
-        # are not yet directly supported
-        from pypy.module._stackless.interp_coroutine import post_install as post_install_coro
-        post_install_coro(self)
-        from pypy.module._stackless.interp_greenlet import post_install as post_install_greenlet
-        post_install_greenlet(self)
-
-        if self.space.config.translation.gc == 'marksweep':
-            from pypy.module._stackless.interp_clonable import post_install as post_install_clonable
-            self.extra_interpdef('clonable', 'interp_clonable.AppClonableCoroutine')
-            self.extra_interpdef('fork',     'interp_clonable.fork')
-            post_install_clonable(self)
diff --git a/pypy/module/_stackless/app_greenlet.py b/pypy/module/_stackless/app_greenlet.py
deleted file mode 100644
--- a/pypy/module/_stackless/app_greenlet.py
+++ /dev/null
@@ -1,5 +0,0 @@
-class GreenletExit(Exception):
-    pass
-
-class GreenletError(Exception):
-    pass
diff --git a/pypy/module/_stackless/interp_clonable.py b/pypy/module/_stackless/interp_clonable.py
deleted file mode 100644
--- a/pypy/module/_stackless/interp_clonable.py
+++ /dev/null
@@ -1,106 +0,0 @@
-from pypy.interpreter.error import OperationError
-from pypy.interpreter.typedef import TypeDef
-from pypy.interpreter.gateway import interp2app
-from pypy.module._stackless.interp_coroutine import AppCoroutine, AppCoState
-from pypy.module._stackless.interp_coroutine import makeStaticMethod
-from pypy.module._stackless.rcoroutine import AbstractThunk
-from pypy.module._stackless.rclonable import InterpClonableMixin
-
-
-class AppClonableCoroutine(AppCoroutine, InterpClonableMixin):
-
-    def newsubctx(self):
-        self.hello_local_pool()
-        AppCoroutine.newsubctx(self)
-        self.goodbye_local_pool()
-
-    def hello(self):
-        self.hello_local_pool()
-        AppCoroutine.hello(self)
-
-    def goodbye(self):
-        AppCoroutine.goodbye(self)
-        self.goodbye_local_pool()
-
-    def descr_method__new__(space, w_subtype):
-        co = space.allocate_instance(AppClonableCoroutine, w_subtype)
-        costate = AppClonableCoroutine._get_state(space)
-        AppClonableCoroutine.__init__(co, space, state=costate)
-        return space.wrap(co)
-
-    def _get_state(space):
-        return space.fromcache(AppClonableCoState)
-    _get_state = staticmethod(_get_state)
-
-    def w_getcurrent(space):
-        return space.wrap(AppClonableCoroutine._get_state(space).current)
-    w_getcurrent = staticmethod(w_getcurrent)
-
-    def w_clone(self):
-        space = self.space
-        costate = self.costate
-        if costate.current is self:
-            raise OperationError(space.w_RuntimeError,
-                                 space.wrap("clone() cannot clone the "
-                                            "current coroutine"
-                                            "; use fork() instead"))
-        copy = AppClonableCoroutine(space, state=costate)
-        copy.subctx = self.clone_into(copy, self.subctx)
-        return space.wrap(copy)
-
-    def descr__reduce__(self, space):
-        raise OperationError(space.w_TypeError,
-                             space.wrap("_stackless.clonable instances are "
-                                        "not picklable"))
-
-
-AppClonableCoroutine.typedef = TypeDef("clonable", AppCoroutine.typedef,
-    __new__    = interp2app(AppClonableCoroutine.descr_method__new__.im_func),
-    getcurrent = interp2app(AppClonableCoroutine.w_getcurrent),
-    clone      = interp2app(AppClonableCoroutine.w_clone),
-    __reduce__ = interp2app(AppClonableCoroutine.descr__reduce__),
-)
-
-class AppClonableCoState(AppCoState):
-    def post_install(self):
-        self.current = self.main = AppClonableCoroutine(self.space, state=self)
-        self.main.subctx.clear_framestack()      # wack
-
-def post_install(module):
-    makeStaticMethod(module, 'clonable', 'getcurrent')
-    space = module.space
-    AppClonableCoroutine._get_state(space).post_install()
-
-# ____________________________________________________________
-
-class ForkThunk(AbstractThunk):
-    def __init__(self, coroutine):
-        self.coroutine = coroutine
-        self.newcoroutine = None
-    def call(self):
-        oldcoro = self.coroutine
-        self.coroutine = None
-        newcoro = AppClonableCoroutine(oldcoro.space, state=oldcoro.costate)
-        newcoro.subctx = oldcoro.clone_into(newcoro, oldcoro.subctx)
-        newcoro.parent = oldcoro
-        self.newcoroutine = newcoro
-
-def fork(space):
-    """Fork, as in the Unix fork(): the call returns twice, and the return
-    value of the call is either the new 'child' coroutine object (if returning
-    into the parent), or None (if returning into the child).  This returns
-    into the parent first, which can switch to the child later.
-    """
-    costate = AppClonableCoroutine._get_state(space)
-    current = costate.current
-    if current is costate.main:
-        raise OperationError(space.w_RuntimeError,
-                             space.wrap("cannot fork() in the main "
-                                        "clonable coroutine"))
-    thunk = ForkThunk(current)
-    coro_fork = AppClonableCoroutine(space, state=costate)
-    coro_fork.bind(thunk)
-    coro_fork.switch()
-    # we resume here twice.  The following would need explanations about
-    # why it returns the correct thing in both the parent and the child...
-    return space.wrap(thunk.newcoroutine)
diff --git a/pypy/module/_stackless/interp_composable_coroutine b/pypy/module/_stackless/interp_composable_coroutine
deleted file mode 100644
--- a/pypy/module/_stackless/interp_composable_coroutine
+++ /dev/null
@@ -1,33 +0,0 @@
-from pypy.interpreter.baseobjspace import Wrappable
-from pypy.interpreter.typedef import TypeDef, interp2app
-from pypy.module._stackless.coroutine import AppCoState, AppCoroutine
-
-
-class W_UserCoState(Wrappable):
-    def __init__(self, space):
-        self.costate = AppCoState(space)
-        self.costate.post_install()
-
-    def descr_method__new__(space, w_subtype):
-        costate = space.allocate_instance(W_UserCoState, w_subtype)
-        W_UserCoState.__init__(costate, space)
-        return space.wrap(costate)
-
-    def w_getcurrent(self):
-        space = self.costate.space
-        return space.wrap(self.costate.current)
-
-    def w_spawn(self, w_subtype=None):
-        space = self.costate.space
-        if space.is_w(w_subtype, space.w_None):
-            w_subtype = space.gettypeobject(AppCoroutine.typedef)
-        co = space.allocate_instance(AppCoroutine, w_subtype)
-        AppCoroutine.__init__(co, space, state=self.costate)
-        return space.wrap(co)
-
-W_UserCoState.typedef = TypeDef("usercostate",
-    __new__ = interp2app(W_UserCoState.descr_method__new__.im_func),
-    __module__ = '_stackless',
-    getcurrent = interp2app(W_UserCoState.w_getcurrent),
-    spawn      = interp2app(W_UserCoState.w_spawn),
-)
diff --git a/pypy/module/_stackless/interp_composable_coroutine.py b/pypy/module/_stackless/interp_composable_coroutine.py
deleted file mode 100644
--- a/pypy/module/_stackless/interp_composable_coroutine.py
+++ /dev/null
@@ -1,34 +0,0 @@
-from pypy.interpreter.baseobjspace import Wrappable
-from pypy.interpreter.typedef import TypeDef, interp2app
-from pypy.module._stackless.interp_coroutine import AppCoState, AppCoroutine
-
-
-class W_UserCoState(Wrappable):
-    def __init__(self, space):
-        self.costate = AppCoState(space)
-        self.costate.post_install()
-
-    def descr_method__new__(space, w_subtype):
-        costate = space.allocate_instance(W_UserCoState, w_subtype)
-        W_UserCoState.__init__(costate, space)
-        return space.wrap(costate)
-
-    def w_getcurrent(self):
-        space = self.costate.space
-        return space.wrap(self.costate.current)
-
-    def w_spawn(self, w_subtype=None):
-        space = self.costate.space
-        if space.is_w(w_subtype, space.w_None):
-            w_subtype = space.gettypeobject(AppCoroutine.typedef)
-        co = space.allocate_instance(AppCoroutine, w_subtype)
-        AppCoroutine.__init__(co, space, state=self.costate)
-        return space.wrap(co)
-
-W_UserCoState.typedef = TypeDef("usercostate",
-    __new__ = interp2app(W_UserCoState.descr_method__new__.im_func),
-    __module__ = '_stackless',
-    getcurrent = interp2app(W_UserCoState.w_getcurrent),
-    spawn      = interp2app(W_UserCoState.w_spawn),
-)
-W_UserCoState.acceptable_as_base_class = False
diff --git a/pypy/module/_stackless/interp_coroutine.py b/pypy/module/_stackless/interp_coroutine.py
deleted file mode 100644
--- a/pypy/module/_stackless/interp_coroutine.py
+++ /dev/null
@@ -1,403 +0,0 @@
-"""
-Coroutine implementation for application level on top
-of the internal coroutines.
-This is an extensible concept. Multiple implementations
-of concurrency can exist together, if they follow the
-basic concept of maintaining their own costate.
-
-There is also some diversification possible by using
-multiple costates for the same type. This leads to
-disjoint switchable sets within the same type.
-
-I'm not so sure to what extent the opposite is possible, too.
-I.e., merging the costate of tasklets and greenlets would
-allow them to be parents of each other. Needs a bit more
-experience to decide where to set the limits.
-"""
-
-from pypy.interpreter.argument import Arguments
-from pypy.interpreter.typedef import GetSetProperty, TypeDef
-from pypy.interpreter.gateway import interp2app, unwrap_spec
-from pypy.interpreter.error import OperationError, operationerrfmt
-
-from pypy.module._stackless.stackless_flags import StacklessFlags
-from pypy.module._stackless.rcoroutine import Coroutine, BaseCoState, AbstractThunk, CoroutineExit
-
-from pypy.module.exceptions.interp_exceptions import W_SystemExit, _new_exception
-
-from pypy.rlib import rstack, jit # for resume points
-from pypy.tool import stdlib_opcode as pythonopcode
-
-class _AppThunk(AbstractThunk):
-
-    def __init__(self, space, costate, w_obj, args):
-        self.space = space
-        self.costate = costate
-        if not space.is_true(space.callable(w_obj)):
-            raise operationerrfmt(
-                space.w_TypeError,
-                "'%s' object is not callable",
-                space.type(w_obj).getname(space))
-        self.w_func = w_obj
-        self.args = args
-
-    def call(self):
-        costate = self.costate
-        w_result = self.space.call_args(self.w_func, self.args)
-        costate.w_tempval = w_result
-
-class _ResumeThunk(AbstractThunk):
-    def __init__(self, space, costate, w_frame):
-        self.space = space
-        self.costate = costate
-        self.w_frame = w_frame
-
-    def call(self):
-        w_result = resume_frame(self.space, self.w_frame)
-        # costate.w_tempval = w_result #XXX?
-
-
-W_CoroutineExit = _new_exception('CoroutineExit', W_SystemExit,
-                        """Coroutine killed manually.""")
-
-# Should be moved to interp_stackless.py if it's ever implemented... Currently
-# used by pypy/lib/stackless.py.
-W_TaskletExit = _new_exception('TaskletExit', W_SystemExit,
-            """Tasklet killed manually.""")
-
-class AppCoroutine(Coroutine): # XXX, StacklessFlags):
-
-    def __init__(self, space, state=None):
-        self.space = space
-        if state is None:
-            state = AppCoroutine._get_state(space)
-        Coroutine.__init__(self, state)
-        self.flags = 0
-        self.newsubctx()
-
-    def newsubctx(self):
-        ec = self.space.getexecutioncontext()
-        self.subctx = ec.Subcontext()
-
-    def descr_method__new__(space, w_subtype):
-        co = space.allocate_instance(AppCoroutine, w_subtype)
-        AppCoroutine.__init__(co, space)
-        return space.wrap(co)
-
-    def _get_state(space):
-        return space.fromcache(AppCoState)
-    _get_state = staticmethod(_get_state)
-
-    def w_bind(self, w_func, __args__):
-        space = self.space
-        if self.frame is not None:
-            raise OperationError(space.w_ValueError, space.wrap(
-                "cannot bind a bound Coroutine"))
-        state = self.costate
-        thunk = _AppThunk(space, state, w_func, __args__)
-        self.bind(thunk)
-
-    def w_switch(self):
-        space = self.space
-        if self.frame is None:
-            raise OperationError(space.w_ValueError, space.wrap(
-                "cannot switch to an unbound Coroutine"))
-        state = self.costate
-        self.switch()
-        w_ret, state.w_tempval = state.w_tempval, space.w_None
-        return w_ret
-
-    def switch(self):
-        space = self.space
-        try:
-            Coroutine.switch(self)
-        except CoroutineExit:
-            raise OperationError(self.costate.w_CoroutineExit, space.w_None)
-
-    def w_finished(self, w_excinfo):
-        pass
-
-    def finish(self, operror=None):
-        space = self.space
-        if isinstance(operror, OperationError):
-            w_exctype = operror.w_type
-            w_excvalue = operror.get_w_value(space)
-            w_exctraceback = operror.get_traceback()
-            w_excinfo = space.newtuple([w_exctype, w_excvalue, w_exctraceback])
-
-            if w_exctype is self.costate.w_CoroutineExit:
-                self.coroutine_exit = True
-        else:
-            w_N = space.w_None
-            w_excinfo = space.newtuple([w_N, w_N, w_N])
-
-        return space.call_method(space.wrap(self),'finished', w_excinfo)
-
-    def hello(self):
-        ec = self.space.getexecutioncontext()
-        self.subctx.enter(ec)
-
-    def goodbye(self):
-        ec = self.space.getexecutioncontext()
-        self.subctx.leave(ec)
-
-    def w_kill(self):
-        self.kill()
-
-    def w_throw(self, w_type, w_value=None, w_traceback=None):
-        space = self.space
-
-        operror = OperationError(w_type, w_value)
-        operror.normalize_exception(space)
-
-        if not space.is_w(w_traceback, space.w_None):
-            from pypy.interpreter import pytraceback
-            tb = space.interpclass_w(w_traceback)
-            if tb is None or not space.is_true(space.isinstance(tb,
-                space.gettypeobject(pytraceback.PyTraceback.typedef))):
-                raise OperationError(space.w_TypeError,
-                      space.wrap("throw: arg 3 must be a traceback or None"))
-            operror.set_traceback(tb)
-
-        self._kill(operror)
-
-    def _userdel(self):
-        if self.get_is_zombie():
-            return
-        self.set_is_zombie(True)
-        self.space.userdel(self.space.wrap(self))
-
-    def w_getcurrent(space):
-        return space.wrap(AppCoroutine._get_state(space).current)
-    w_getcurrent = staticmethod(w_getcurrent)
-
-    def w_getmain(space):
-        return space.wrap(AppCoroutine._get_state(space).main)
-    w_getmain = staticmethod(w_getmain)
-
-    # pickling interface
-    def descr__reduce__(self, space):
-        # this is trying to be simplistic at the moment.
-        # we neither allow to pickle main (which can become a mess
-        # since it has some deep anchestor frames)
-        # nor we allow to pickle the current coroutine.
-        # rule: switch before pickling.
-        # you cannot construct the tree that you are climbing.
-        from pypy.interpreter.mixedmodule import MixedModule
-        w_mod    = space.getbuiltinmodule('_stackless')
-        mod      = space.interp_w(MixedModule, w_mod)
-        w_mod2    = space.getbuiltinmodule('_pickle_support')
-        mod2      = space.interp_w(MixedModule, w_mod2)
-        w_new_inst = mod.get('coroutine')
-        w        = space.wrap
-        nt = space.newtuple
-        ec = self.space.getexecutioncontext()
-
-        if self is self.costate.main:
-            return nt([mod.get('_return_main'), nt([])])
-
-        thunk = self.thunk
-        if isinstance(thunk, _AppThunk):
-            w_args, w_kwds = thunk.args.topacked()
-            w_thunk = nt([thunk.w_func, w_args, w_kwds])
-        else:
-            w_thunk = space.w_None
-
-        tup_base = [
-            ]
-        tup_state = [
-            w(self.flags),
-            self.subctx.getstate(space),
-            w_thunk,
-            w(self.parent),
-            ]
-
-        return nt([w_new_inst, nt(tup_base), nt(tup_state)])
-
-    def descr__setstate__(self, space, w_args):
-        w_flags, w_state, w_thunk, w_parent = space.unpackiterable(w_args,
-                                                        expected_length=4)
-        self.flags = space.int_w(w_flags)
-        if space.is_w(w_parent, space.w_None):
-            w_parent = self.w_getmain(space)
-        self.parent = space.interp_w(AppCoroutine, w_parent)
-        ec = self.space.getexecutioncontext()
-        self.subctx.setstate(space, w_state)
-        if space.is_w(w_thunk, space.w_None):
-            if space.is_w(w_state, space.w_None):
-                self.thunk = None
-            else:
-                self.bind(_ResumeThunk(space, self.costate, self.subctx.topframe))
-        else:
-            w_func, w_args, w_kwds = space.unpackiterable(w_thunk,
-                                                          expected_length=3)
-            args = Arguments.frompacked(space, w_args, w_kwds)
-            self.bind(_AppThunk(space, self.costate, w_func, args))
-
-
-# _mixin_ did not work
-for methname in StacklessFlags.__dict__:
-    meth = getattr(StacklessFlags, methname)
-    if hasattr(meth, 'im_func'):
-        setattr(AppCoroutine, meth.__name__, meth.im_func)
-del meth, methname
-
-def w_get_is_zombie(self, space):
-    return space.wrap(self.get_is_zombie())
-AppCoroutine.w_get_is_zombie = w_get_is_zombie
-
-def w_get_is_alive(self, space):
-    return space.wrap(self.is_alive())
-AppCoroutine.w_get_is_alive = w_get_is_alive
-
-def w_descr__framestack(self, space):
-    assert isinstance(self, AppCoroutine)
-    counter = 0
-    f = self.subctx.topframe
-    while f is not None:
-        counter += 1
-        f = f.f_backref()
-    items = [None] * counter
-    f = self.subctx.topframe
-    while f is not None:
-        counter -= 1
-        assert counter >= 0
-        items[counter] = space.wrap(f)
-        f = f.f_backref()
-    assert counter == 0
-    return space.newtuple(items)
-
-def makeStaticMethod(module, classname, funcname):
-    "NOT_RPYTHON"
-    space = module.space
-    w_klass = space.getattr(space.wrap(module), space.wrap(classname))
-    # HACK HACK HACK
-    # make the typeobject mutable for a while
-    from pypy.objspace.std.typeobject import W_TypeObject
-    assert isinstance(w_klass, W_TypeObject)
-    old_flag = w_klass.flag_heaptype
-    w_klass.flag_heaptype = True
-
-    space.appexec([w_klass, space.wrap(funcname)], """
-        (klass, funcname):
-            func = getattr(klass, funcname)
-            setattr(klass, funcname, staticmethod(func.im_func))
-    """)
-    w_klass.flag_heaptype = old_flag
-
-def post_install(module):
-    makeStaticMethod(module, 'coroutine', 'getcurrent')
-    makeStaticMethod(module, 'coroutine', 'getmain')
-    space = module.space
-    AppCoroutine._get_state(space).post_install()
-
-# space.appexec("""() :
-
-# maybe use __spacebind__ for postprocessing
-
-AppCoroutine.typedef = TypeDef("coroutine",
-    __new__ = interp2app(AppCoroutine.descr_method__new__.im_func),
-    bind = interp2app(AppCoroutine.w_bind),
-    switch = interp2app(AppCoroutine.w_switch),
-    kill = interp2app(AppCoroutine.w_kill),
-    throw = interp2app(AppCoroutine.w_throw),
-    finished = interp2app(AppCoroutine.w_finished),
-    is_alive = GetSetProperty(AppCoroutine.w_get_is_alive),
-    is_zombie = GetSetProperty(AppCoroutine.w_get_is_zombie,
-      doc=AppCoroutine.get_is_zombie.__doc__), #--- this flag is a bit obscure
-      # and not useful (it's totally different from Coroutine.is_zombie(), too)
-      # but lib/stackless.py uses it
-    _framestack = GetSetProperty(w_descr__framestack),
-    getcurrent = interp2app(AppCoroutine.w_getcurrent),
-    getmain = interp2app(AppCoroutine.w_getmain),
-    __reduce__   = interp2app(AppCoroutine.descr__reduce__),
-    __setstate__ = interp2app(AppCoroutine.descr__setstate__),
-    __module__ = '_stackless',
-)
-
-class AppCoState(BaseCoState):
-    def __init__(self, space):
-        BaseCoState.__init__(self)
-        self.w_tempval = space.w_None
-        self.space = space
-
-        # XXX Workaround: for now we need to instantiate these classes
-        # explicitly for translation to work
-        W_CoroutineExit(space)
-        W_TaskletExit(space)
-
-        # Exporting new exception to space
-        self.w_CoroutineExit = space.gettypefor(W_CoroutineExit)
-        space.setitem(
-                      space.exceptions_module.w_dict,
-                      space.new_interned_str('CoroutineExit'),
-                      self.w_CoroutineExit)
-        space.setitem(space.builtin.w_dict,
-                      space.new_interned_str('CoroutineExit'),
-                      self.w_CoroutineExit)
-
-        # Should be moved to interp_stackless.py if it's ever implemented...
-        self.w_TaskletExit = space.gettypefor(W_TaskletExit)
-        space.setitem(
-                      space.exceptions_module.w_dict,
-                      space.new_interned_str('TaskletExit'),
-                      self.w_TaskletExit)
-        space.setitem(space.builtin.w_dict,
-                      space.new_interned_str('TaskletExit'),
-                      self.w_TaskletExit)
-
-    def post_install(self):
-        self.current = self.main = AppCoroutine(self.space, state=self)
-        self.main.subctx.clear_framestack()      # wack
-
-def return_main(space):
-    return AppCoroutine._get_state(space).main
-
-def get_stack_depth_limit(space):
-    return space.wrap(rstack.get_stack_depth_limit())
-
- at unwrap_spec(limit=int)
-def set_stack_depth_limit(space, limit):
-    rstack.set_stack_depth_limit(limit)
-
-
-# ___________________________________________________________________
-# unpickling trampoline
-
-def resume_frame(space, w_frame):
-    from pypy.interpreter.pyframe import PyFrame
-    frame = space.interp_w(PyFrame, w_frame, can_be_None=True)
-    w_result = space.w_None
-    operr = None
-    executioncontext = frame.space.getexecutioncontext()
-    while frame is not None:
-        code = frame.pycode.co_code
-        instr = frame.last_instr
-        opcode = ord(code[instr])
-        map = pythonopcode.opmap
-        call_ops = [map['CALL_FUNCTION'], map['CALL_FUNCTION_KW'], map['CALL_FUNCTION_VAR'],
-                    map['CALL_FUNCTION_VAR_KW'], map['CALL_METHOD']]
-        assert opcode in call_ops
-        instr += 1
-        oparg = ord(code[instr]) | ord(code[instr + 1]) << 8
-        nargs = oparg & 0xff
-        nkwds = (oparg >> 8) & 0xff
-        if nkwds == 0:     # only positional arguments
-            # fast paths leaves things on the stack, pop them
-            if space.config.objspace.opcodes.CALL_METHOD and opcode == map['CALL_METHOD']:
-                frame.dropvalues(nargs + 2)
-            elif opcode == map['CALL_FUNCTION']:
-                frame.dropvalues(nargs + 1)
-
-        # small hack: unlink frame out of the execution context, because
-        # execute_frame will add it there again
-        executioncontext.topframeref = jit.non_virtual_ref(frame.f_backref())
-        frame.last_instr = instr + 1 # continue after the call
-        try:
-            w_result = frame.execute_frame(w_result, operr)
-        except OperationError, operr:
-            pass
-        frame = frame.f_backref()
-    if operr:
-        raise operr
-    return w_result
diff --git a/pypy/module/_stackless/interp_greenlet.py b/pypy/module/_stackless/interp_greenlet.py
deleted file mode 100644
--- a/pypy/module/_stackless/interp_greenlet.py
+++ /dev/null
@@ -1,238 +0,0 @@
-from pypy.interpreter.argument import Arguments
-from pypy.interpreter.typedef import GetSetProperty, TypeDef
-from pypy.interpreter.gateway import interp2app
-from pypy.interpreter.gateway import NoneNotWrapped
-from pypy.interpreter.error import OperationError
-
-from pypy.module._stackless.rcoroutine import Coroutine, BaseCoState
-from pypy.module._stackless.rcoroutine import AbstractThunk, syncstate
-from pypy.module._stackless.interp_coroutine import makeStaticMethod
-
-
-class GreenletThunk(AbstractThunk):
-
-    def __init__(self, greenlet):
-        self.greenlet = greenlet
-
-    def call(self):
-        greenlet = self.greenlet
-        greenlet.active = True
-        try:
-            space = greenlet.space
-            args_w = greenlet.costate.args_w
-            __args__ = Arguments(space, args_w)
-            try:
-                w_run = space.getattr(space.wrap(greenlet), space.wrap('run'))
-                greenlet.w_callable = None
-                w_result = space.call_args(w_run, __args__)
-            except OperationError, operror:
-                if not operror.match(space, greenlet.costate.w_GreenletExit):
-                    raise
-                w_result = operror.get_w_value(space)
-        finally:
-            greenlet.active = False
-        greenlet.costate.args_w = [w_result]
-
-class AppGreenletCoState(BaseCoState):
-    def __init__(self, space):
-        BaseCoState.__init__(self)
-        self.args_w = None
-        self.space = space
-        self.w_GreenletExit  = get(space, "GreenletExit")
-        self.w_GreenletError = get(space, "GreenletError")
-
-    def post_install(self):
-        self.current = self.main = AppGreenlet(self.space, is_main=True)
-
-class AppGreenlet(Coroutine):
-    def __init__(self, space, w_callable=None, is_main=False):
-        Coroutine.__init__(self, self._get_state(space))
-        self.space = space
-        self.w_callable = w_callable
-        self.active = is_main
-        self.subctx = space.getexecutioncontext().Subcontext()
-        if is_main:
-            self.subctx.clear_framestack()      # wack
-        else:
-            self.bind(GreenletThunk(self))
-
-    def descr_method__new__(space, w_subtype, __args__):
-        co = space.allocate_instance(AppGreenlet, w_subtype)
-        AppGreenlet.__init__(co, space)
-        return space.wrap(co)
-
-    def descr_method__init__(self, w_run=NoneNotWrapped,
-                                   w_parent=NoneNotWrapped):
-        if w_run is not None:
-            self.set_run(w_run)
-        if w_parent is not None:
-            self.set_parent(w_parent)
-
-    def _get_state(space):
-        return space.fromcache(AppGreenletCoState)
-    _get_state = staticmethod(_get_state)
-
-    def hello(self):
-        ec = self.space.getexecutioncontext()
-        self.subctx.enter(ec)
-
-    def goodbye(self):
-        ec = self.space.getexecutioncontext()
-        self.subctx.leave(ec)
-
-    def w_getcurrent(space):
-        return space.wrap(AppGreenlet._get_state(space).current)
-    w_getcurrent = staticmethod(w_getcurrent)
-
-    def w_switch(self, args_w):
-        # Find the switch target - it might be a parent greenlet
-        space = self.space
-        costate = self.costate
-        target = self
-        while target.isdead():
-            target = target.parent
-            assert isinstance(target, AppGreenlet)
-        # Switch to it
-        costate.args_w = args_w
-        if target is not costate.current:
-            target.switch()
-        else:
-            # case not handled in Coroutine.switch()
-            syncstate._do_things_to_do()
-        result_w = costate.args_w
-        costate.args_w = None
-        # costate.args_w can be set to None above for throw(), but then
-        # switch() should have raised.  At this point cosstate.args_w != None.
-        assert result_w is not None
-        # Return the result of a switch, packaging it in a tuple if
-        # there is more than one value.
-        if len(result_w) == 1:
-            return result_w[0]
-        return space.newtuple(result_w)
-
-    def w_throw(self, w_type=None, w_value=None, w_traceback=None):
-        space = self.space
-        if space.is_w(w_type, space.w_None):
-            w_type = self.costate.w_GreenletExit
-        # Code copied from RAISE_VARARGS but slightly modified.  Not too nice.
-        operror = OperationError(w_type, w_value)
-        operror.normalize_exception(space)
-        if not space.is_w(w_traceback, space.w_None):
-            from pypy.interpreter import pytraceback
-            tb = space.interpclass_w(w_traceback)
-            if tb is None or not space.is_true(space.isinstance(tb, 
-                space.gettypeobject(pytraceback.PyTraceback.typedef))):
-                raise OperationError(space.w_TypeError,
-                      space.wrap("throw: arg 3 must be a traceback or None"))
-            operror.set_traceback(tb)
-        # Dead greenlet: turn GreenletExit into a regular return
-        if self.isdead() and operror.match(space, self.costate.w_GreenletExit):
-            args_w = [operror.get_w_value(space)]
-        else:
-            syncstate.push_exception(operror)
-            args_w = None
-        return self.w_switch(args_w)
-
-    def _userdel(self):
-        self.space.userdel(self.space.wrap(self))
-
-    def isdead(self):
-        return self.thunk is None and not self.active
-
-    def w_get_is_dead(self, space):
-        return space.newbool(self.isdead())
-
-    def descr__nonzero__(self):
-        return self.space.newbool(self.active)
-
-    def w_get_run(self, space):
-        w_run = self.w_callable
-        if w_run is None:
-            raise OperationError(space.w_AttributeError, space.wrap("run"))
-        return w_run
-
-    def set_run(self, w_run):
-        space = self.space
-        if self.thunk is None:
-            raise OperationError(space.w_AttributeError,
-                                 space.wrap("run cannot be set "
-                                            "after the start of the greenlet"))
-        self.w_callable = w_run
-
-    def w_set_run(self, space, w_run):
-        self.set_run(w_run)
-
-    def w_del_run(self, space):
-        if self.w_callable is None:
-            raise OperationError(space.w_AttributeError, space.wrap("run"))
-        self.w_callable = None
-
-    def w_get_parent(self, space):
-        return space.wrap(self.parent)
-
-    def set_parent(self, w_parent):
-        space = self.space
-        newparent = space.interp_w(AppGreenlet, w_parent)
-        if newparent.costate is not self.costate:
-            raise OperationError(self.costate.w_GreenletError,
-                                 space.wrap("invalid foreign parent"))
-        curr = newparent
-        while curr:
-            if curr is self:
-                raise OperationError(space.w_ValueError,
-                                     space.wrap("cyclic parent chain"))
-            curr = curr.parent
-        self.parent = newparent
-
-    def w_set_parent(self, space, w_parent):
-        self.set_parent(w_parent)
-
-    def w_get_frame(self, space):
-        if not self.active or self.costate.current is self:
-            f = None
-        else:
-            f = self.subctx.topframe
-        return space.wrap(f)
-
-def get(space, name):
-    w_module = space.getbuiltinmodule('_stackless')
-    return space.getattr(w_module, space.wrap(name))
-
-def post_install(module):
-    "NOT_RPYTHON"
-    makeStaticMethod(module, 'greenlet', 'getcurrent')
-    space = module.space
-    state = AppGreenlet._get_state(space)
-    state.post_install()
-    w_greenlet = get(space, 'greenlet')
-    # HACK HACK HACK
-    # make the typeobject mutable for a while
-    from pypy.objspace.std.typeobject import W_TypeObject
-    assert isinstance(w_greenlet, W_TypeObject)
-    old_flag = w_greenlet.flag_heaptype
-    w_greenlet.flag_heaptype = True
-    space.appexec([w_greenlet,
-                   state.w_GreenletExit,
-                   state.w_GreenletError], """
-    (greenlet, exit, error):
-        greenlet.GreenletExit = exit
-        greenlet.error = error
-    """)
-    w_greenlet.flag_heaptype = old_flag
-
-AppGreenlet.typedef = TypeDef("greenlet",
-    __new__ = interp2app(AppGreenlet.descr_method__new__.im_func),
-    __init__ = interp2app(AppGreenlet.descr_method__init__),
-    switch = interp2app(AppGreenlet.w_switch),
-    dead = GetSetProperty(AppGreenlet.w_get_is_dead),
-    run = GetSetProperty(AppGreenlet.w_get_run,
-                         AppGreenlet.w_set_run,
-                         AppGreenlet.w_del_run),
-    parent = GetSetProperty(AppGreenlet.w_get_parent,
-                            AppGreenlet.w_set_parent),
-    getcurrent = interp2app(AppGreenlet.w_getcurrent),
-    throw = interp2app(AppGreenlet.w_throw),
-    gr_frame = GetSetProperty(AppGreenlet.w_get_frame),
-    __nonzero__ = interp2app(AppGreenlet.descr__nonzero__),
-    __module__ = '_stackless',
-)
diff --git a/pypy/module/_stackless/interp_stackless.py b/pypy/module/_stackless/interp_stackless.py
deleted file mode 100644
--- a/pypy/module/_stackless/interp_stackless.py
+++ /dev/null
@@ -1,28 +0,0 @@
-from pypy.interpreter.baseobjspace import Wrappable
-from pypy.interpreter.typedef import TypeDef
-from pypy.interpreter.gateway import interp2app
-import os
-
-
-class tasklet(Wrappable):
-
-    def __init__(self, space):
-        self.space = space
-        self.flags = 0
-        self.state = None
-
-    def descr_method__new__(space, w_subtype):
-        t = space.allocate_instance(tasklet, w_subtype)
-        tasklet.__init__(t, space)
-        return space.wrap(t)
-
-    def w_demo(self):
-        output("42")
-
-tasklet.typedef = TypeDef("tasklet",
-    __new__ = interp2app(tasklet.descr_method__new__.im_func),
-    demo = interp2app(tasklet.w_demo),
-)
-
-def output(stuff):
-    os.write(2, stuff + '\n')
diff --git a/pypy/module/_stackless/rclonable.py b/pypy/module/_stackless/rclonable.py
deleted file mode 100644
--- a/pypy/module/_stackless/rclonable.py
+++ /dev/null
@@ -1,87 +0,0 @@
-from pypy.module._stackless.interp_coroutine import AbstractThunk, Coroutine
-from pypy.rlib.rgc import gc_swap_pool, gc_clone
-from pypy.rlib.objectmodel import we_are_translated
-
-
-class InterpClonableMixin:
-    local_pool = None
-    _mixin_ = True
-
-    def hello_local_pool(self):
-        if we_are_translated():
-            self.saved_pool = gc_swap_pool(self.local_pool)
-
-    def goodbye_local_pool(self):
-        if we_are_translated():
-            self.local_pool = gc_swap_pool(self.saved_pool)
-            self.saved_pool = None
-
-    def clone_into(self, copy, extradata=None):
-        if not we_are_translated():
-            raise NotImplementedError
-        # cannot gc_clone() directly self, because it is not in its own
-        # local_pool.  Moreover, it has a __del__, which cloning doesn't
-        # support properly at the moment.
-        copy.parent = self.parent
-        # the hello/goodbye pair has two purposes: it forces
-        # self.local_pool to be computed even if it was None up to now,
-        # and it puts the 'data' tuple in the correct pool to be cloned.
-        self.hello_local_pool()
-        data = (self.frame, extradata)
-        self.goodbye_local_pool()
-        # clone!
-        data, copy.local_pool = gc_clone(data, self.local_pool)
-        copy.frame, extradata = data
-        copy.thunk = self.thunk # in case we haven't switched to self yet
-        return extradata
-
-
-class InterpClonableCoroutine(Coroutine, InterpClonableMixin):
-
-    def hello(self):
-        self.hello_local_pool()
-
-    def goodbye(self):
-        self.goodbye_local_pool()
-
-    def clone(self):
-        # hack, this is overridden in AppClonableCoroutine
-        if self.getcurrent() is self:
-            raise RuntimeError("clone() cannot clone the current coroutine; "
-                               "use fork() instead")
-        copy = InterpClonableCoroutine(self.costate)
-        self.clone_into(copy)
-        return copy
-
-
-class ForkThunk(AbstractThunk):
-    def __init__(self, coroutine):
-        self.coroutine = coroutine
-        self.newcoroutine = None
-    def call(self):
-        oldcoro = self.coroutine
-        self.coroutine = None
-        newcoro = oldcoro.clone()
-        newcoro.parent = oldcoro
-        self.newcoroutine = newcoro
-
-def fork():
-    """Fork, as in the Unix fork(): the call returns twice, and the return
-    value of the call is either the new 'child' coroutine object (if returning
-    into the parent), or None (if returning into the child).  This returns
-    into the parent first, which can switch to the child later.
-    """
-    current = InterpClonableCoroutine.getcurrent()
-    if not isinstance(current, InterpClonableCoroutine):
-        raise RuntimeError("fork() in a non-clonable coroutine")
-    thunk = ForkThunk(current)
-    coro_fork = InterpClonableCoroutine()
-    coro_fork.bind(thunk)
-    coro_fork.switch()
-    # we resume here twice.  The following would need explanations about
-    # why it returns the correct thing in both the parent and the child...
-    return thunk.newcoroutine
-
-##    from pypy.rpython.lltypesystem import lltype, lloperation
-##    lloperation.llop.debug_view(lltype.Void, current, thunk,
-##        lloperation.llop.gc_x_size_header(lltype.Signed))
diff --git a/pypy/module/_stackless/rcoroutine.py b/pypy/module/_stackless/rcoroutine.py
deleted file mode 100644
--- a/pypy/module/_stackless/rcoroutine.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from pypy.rlib.rcoroutine import make_coroutine_classes
-from pypy.interpreter.baseobjspace import Wrappable
-
-d = make_coroutine_classes(Wrappable)
-
-Coroutine = d['Coroutine']
-BaseCoState = d['BaseCoState']
-AbstractThunk = d['AbstractThunk']
-syncstate = d['syncstate']
-CoroutineExit = d['CoroutineExit']
diff --git a/pypy/module/_stackless/stackless_flags.py b/pypy/module/_stackless/stackless_flags.py
deleted file mode 100644
--- a/pypy/module/_stackless/stackless_flags.py
+++ /dev/null
@@ -1,201 +0,0 @@
-"""
-basic definitions for tasklet flags.
-For simplicity and compatibility,
-they are defined the same for coroutines,
-even if they are not used.
-
-taken from tasklet_structs.h
-----------------------------
-
-/***************************************************************************
-
-    Tasklet Flag Definition
-    -----------------------
-
-    blocked:        The tasklet is either waiting in a channel for
-                    writing (1) or reading (-1) or not blocked (0).
-                    Maintained by the channel logic. Do not change.
-
-    atomic:         If true, schedulers will never switch. Driven by
-                    the code object or dynamically, see below.
-
-    ignore_nesting: Allows auto-scheduling, even if nesting_level
-                    is not zero.
-
-    autoschedule:   The tasklet likes to be auto-scheduled. User driven.
-
-    block_trap:     Debugging aid. Whenever the tasklet would be
-                    blocked by a channel, an exception is raised.
-
-    is_zombie:      This tasklet is almost dead, its deallocation has
-                    started. The tasklet *must* die at some time, or the
-                    process can never end.
-
-    pending_irq:    If set, an interrupt was issued during an atomic
-                    operation, and should be handled when possible.
-
-
-    Policy for atomic/autoschedule and switching:
-    ---------------------------------------------
-    A tasklet switch can always be done explicitly by calling schedule().
-    Atomic and schedule are concerned with automatic features.
-
-    atomic  autoschedule
-
-        1       any     Neither a scheduler nor a watchdog will
-                        try to switch this tasklet.
-
-        0       0       The tasklet can be stopped on desire, or it
-                        can be killed by an exception.
-
-        0       1       Like above, plus auto-scheduling is enabled.
-
-    Default settings:
-    -----------------
-    All flags are zero by default.
-
- ***************************************************************************/
-
-typedef struct _tasklet_flags {
-        int blocked: 2;
-        unsigned int atomic: 1;
-        unsigned int ignore_nesting: 1;
-        unsigned int autoschedule: 1;
-        unsigned int block_trap: 1;
-        unsigned int is_zombie: 1;
-        unsigned int pending_irq: 1;
-} PyTaskletFlagStruc;
-"""
-
-from pypy.rlib.rarithmetic import LONG_BIT, intmask
-
-class BitSetDef(object):
-    __slots__ = "_names __dict__ _attrname".split()
-
-    def __init__(self, _attrname):
-        self._names = []
-        self._attrname = _attrname
-        
-    def __setattr__(self, key, value):
-        if key not in self.__slots__:
-            assert key not in self.__dict__
-            self._names.append(key)
-        object.__setattr__(self, key, value)
-
-    def __iter__(self):
-        return self._enum_objects()
-    
-    def _enum_objects(self):
-        for name in self._names:
-            yield name, getattr(self, name)
-
-# negative values are user-writable
-flags = BitSetDef("flags")
-flags.blocked           =   2, """writing (1) or reading (-1) or not blocked (0)"""
-flags.atomic            =  -1, """If true, schedulers will never switch"""
-flags.ignore_nesting    =  -1, """allow auto-scheduling in nested interpreters"""
-flags.autoschedule      =  -1, """enable auto-scheduling"""
-flags.block_trap        =  -1, """raise an exception instead of blocking"""
-flags.is_zombie         =   1, """__del__ is in progress"""
-flags.pending_irq       =   1, """an interrupt occured while being atomic"""
-
-def make_get_bits(name, bits, shift):
-    """ return a bool for single bits, signed int otherwise """
-    signmask = 1 << (bits - 1 + shift)
-    lshift = bits + shift
-    rshift = bits
-    if bits == 1:
-        return "bool(%s & 0x%x)" % (name, signmask)
-    else:
-        return "intmask(%s << (LONG_BIT-%d)) >> (LONG_BIT-%d)" % (name, lshift, rshift)
-
-def make_set_bits(name, bits, shift):
-    datamask = int('1' * bits, 2)
-    clearmask = datamask << shift
-    return "%s & ~0x%x | (value & 0x%x) << %d" % (name, clearmask, datamask, shift)
-
-def gen_code():
-    from cStringIO import StringIO
-    f = StringIO()
-    print >> f, "class StacklessFlags(object):"
-    print >> f, "    _mixin_ = True"
-    shift = 0
-    field = "self.%s" % flags._attrname
-    for name, (bits, doc) in flags:
-        write, bits = bits < 0, abs(bits)
-        print >> f
-        print >> f, '    def get_%s(self):' % name
-        print >> f, '        """%s"""' % doc
-        print >> f, '        return %s' % make_get_bits(field, bits, shift)
-        print >> f, '    def set_%s(self, value):' % name
-        print >> f, '        """%s"""' % doc
-        print >> f, '        %s = %s' % (field, make_set_bits(field, bits, shift))
-        print >> f, '    set_%s._public = %s' % (name, write)
-        shift += bits
-    return f.getvalue()
-
-# BEGIN generated code
-class StacklessFlags(object):
-    _mixin_ = True
-
-    def get_blocked(self):
-        """writing (1) or reading (-1) or not blocked (0)"""
-        return intmask(self.flags << (LONG_BIT-2)) >> (LONG_BIT-2)
-    def set_blocked(self, value):
-        """writing (1) or reading (-1) or not blocked (0)"""
-        self.flags = self.flags & ~0x3 | (value & 0x3) << 0
-    set_blocked._public = False
-
-    def get_atomic(self):
-        """If true, schedulers will never switch"""
-        return bool(self.flags & 0x4)
-    def set_atomic(self, value):
-        """If true, schedulers will never switch"""
-        self.flags = self.flags & ~0x4 | (value & 0x1) << 2
-    set_atomic._public = True
-
-    def get_ignore_nesting(self):
-        """allow auto-scheduling in nested interpreters"""
-        return bool(self.flags & 0x8)
-    def set_ignore_nesting(self, value):
-        """allow auto-scheduling in nested interpreters"""
-        self.flags = self.flags & ~0x8 | (value & 0x1) << 3
-    set_ignore_nesting._public = True
-
-    def get_autoschedule(self):
-        """enable auto-scheduling"""
-        return bool(self.flags & 0x10)
-    def set_autoschedule(self, value):
-        """enable auto-scheduling"""
-        self.flags = self.flags & ~0x10 | (value & 0x1) << 4
-    set_autoschedule._public = True
-
-    def get_block_trap(self):
-        """raise an exception instead of blocking"""
-        return bool(self.flags & 0x20)
-    def set_block_trap(self, value):
-        """raise an exception instead of blocking"""
-        self.flags = self.flags & ~0x20 | (value & 0x1) << 5
-    set_block_trap._public = True
-
-    def get_is_zombie(self):
-        """__del__ is in progress"""
-        return bool(self.flags & 0x40)
-    def set_is_zombie(self, value):
-        """__del__ is in progress"""
-        self.flags = self.flags & ~0x40 | (value & 0x1) << 6
-    set_is_zombie._public = False
-
-    def get_pending_irq(self):
-        """an interrupt occured while being atomic"""
-        return bool(self.flags & 0x80)
-    def set_pending_irq(self, value):
-        """an interrupt occured while being atomic"""
-        self.flags = self.flags & ~0x80 | (value & 0x1) << 7
-    set_pending_irq._public = False
-
-# END generated code
-
-if __name__ == '__main__':
-    # paste this into the file
-    print gen_code()
diff --git a/pypy/module/_stackless/test/__init__.py b/pypy/module/_stackless/test/__init__.py
deleted file mode 100644
--- a/pypy/module/_stackless/test/__init__.py
+++ /dev/null
@@ -1,1 +0,0 @@
-#
\ No newline at end of file
diff --git a/pypy/module/_stackless/test/conftest.py b/pypy/module/_stackless/test/conftest.py
deleted file mode 100644
--- a/pypy/module/_stackless/test/conftest.py
+++ /dev/null
@@ -1,8 +0,0 @@
-import sys
-import py.test
-
-def pytest_runtest_setup(item):
-    py.test.importorskip('greenlet')
-    if sys.platform == 'win32':
-        py.test.skip("stackless tests segfault on Windows")
-
diff --git a/pypy/module/_stackless/test/slp_test_pickle.py b/pypy/module/_stackless/test/slp_test_pickle.py
deleted file mode 100644
--- a/pypy/module/_stackless/test/slp_test_pickle.py
+++ /dev/null
@@ -1,35 +0,0 @@
-from pypy.conftest import gettestobjspace
-
-# app-level testing of coroutine pickling
-
-class AppTest_Pickle:
-
-    def setup_class(cls):
-        space = gettestobjspace(usemodules=('_stackless',))
-        cls.space = space
-
-    def test_simple_ish(self):
-
-        output = []
-        import _stackless
-        def f(coro, n, x):
-            if n == 0:
-                coro.switch()
-                return
-            f(coro, n-1, 2*x)
-            output.append(x)
-
-        def example():
-            main_coro = _stackless.coroutine.getcurrent()
-            sub_coro = _stackless.coroutine()
-            sub_coro.bind(f, main_coro, 5, 1)
-            sub_coro.switch()
-
-            import pickle
-            pckl = pickle.dumps(sub_coro)
-            new_coro = pickle.loads(pckl)
-
-            new_coro.switch()
-
-        example()
-        assert output == [16, 8, 4, 2, 1]
diff --git a/pypy/module/_stackless/test/test_choicepoint.py b/pypy/module/_stackless/test/test_choicepoint.py
deleted file mode 100644
--- a/pypy/module/_stackless/test/test_choicepoint.py
+++ /dev/null
@@ -1,85 +0,0 @@
-import py; py.test.skip("clonable coroutines not really maintained any more")
-
-from pypy.rlib.rcoroutine import AbstractThunk
-from pypy.module._stackless.rclonable import InterpClonableCoroutine as ClonableCoroutine
-
-class ChoicePointHolder(object):
-    def __init__(self):
-        self.choicepoints = []
-        self.clone_me = False
-        self.answer = 0
-        self.solutions_count = 0
-
-    def next_choice(self):
-        return self.choicepoints.pop()
-
-    def add(self, choice, answer=0):
-        self.choicepoints.append((choice, answer))
-
-    def more_choices(self):
-        return bool(self.choicepoints)
-
-    def choice(self):
-        #os.write(1, "choice\n")
-        self.clone_me = True
-        self.g_main.switch()
-        #os.write(1, "answer: %d\n" % (self.answer,))
-        return self.answer
-
-    def fail(self):
-        self.g_main.switch()
-        assert False
-
-choicepoints = ChoicePointHolder()
-
-# ____________________________________________________________
-
-class SearchTask(AbstractThunk):
-    def call(self):
-        path = []
-        for i in range(10):
-            res = choicepoints.choice()
-            assert len(path) == i
-            path.append(res)
-            #os.write(1, "{%x} trying: %s\n" % (id(path), path))
-            if i == 3:
-                import gc; gc.collect()
-        #os.write(1, "{%x} found a solution: %s\n" % (id(path), path))
-        choicepoints.solutions_count += 1
-
-# ____________________________________________________________
-
-
-class SearchAllTask(AbstractThunk):
-    def call(self):
-        search_coro = ClonableCoroutine()
-        search_coro.bind(SearchTask())
-        choicepoints.add(search_coro)
-
-        #os.write(1, "starting\n")
-        while choicepoints.more_choices():
-            searcher, nextvalue = choicepoints.next_choice()
-            choicepoints.clone_me = False
-            choicepoints.answer = nextvalue
-            #os.write(1, '<<< {%x} %d\n' % (id(searcher), nextvalue))
-            searcher.switch()
-            #os.write(1, '>>> %d\n' % (choicepoints.clone_me,))
-            if choicepoints.clone_me:
-                searcher2 = searcher.clone()
-                #os.write(1, 'searcher = {%x}, searcher2 = {%x}\n' % (
-                #    id(searcher), id(searcher2)))
-                choicepoints.add(searcher, 5)
-                choicepoints.add(searcher2, 4)
-
-def entry_point():
-    choicepoints.g_main = ClonableCoroutine()
-    choicepoints.g_main.bind(SearchAllTask())
-    choicepoints.g_main.switch()
-    return choicepoints.solutions_count
-
-def test_choicepoint():
-    from pypy.translator.c.test import test_newgc
-    tester = test_newgc.TestUsingStacklessFramework()
-    fn = tester.getcompiled(entry_point)
-    res = fn()
-    assert res == 2 ** 10
diff --git a/pypy/module/_stackless/test/test_clonable.py b/pypy/module/_stackless/test/test_clonable.py
deleted file mode 100644
--- a/pypy/module/_stackless/test/test_clonable.py
+++ /dev/null
@@ -1,187 +0,0 @@
-import py; py.test.skip("clonable coroutines not really maintained any more")
-
-from pypy.conftest import gettestobjspace, option
-import py, sys
-
-# app-level testing of coroutine cloning
-
-class AppTestClonable:
-
-    def setup_class(cls):
-        if not option.runappdirect:
-            py.test.skip('pure appdirect test (run with -A)')
-        cls.space = space = gettestobjspace(usemodules=('_stackless',))
-        if not space.is_true(space.appexec([], """():
-            import _stackless
-            return hasattr(_stackless, 'clonable')
-        """)):
-            py.test.skip('no _stackless.clonable')
-
-
-    def test_solver(self):
-        import _stackless
-
-        class Fail(Exception):
-            pass
-
-        class Success(Exception):
-            pass
-
-        def first_solution(func):
-            global next_answer
-            co = _stackless.clonable()
-            co.bind(func)
-            pending = [(co, None)]
-            while pending:
-                co, next_answer = pending.pop()
-                try:
-                    co.switch()
-                except Fail:
-                    pass
-                except Success, e:
-                    return e.args[0]
-                else:
-                    # zero_or_one() called, clone the coroutine
-                    co2 = co.clone()
-                    pending.append((co2, 1))
-                    pending.append((co, 0))
-            raise Fail("no solution")
-
-        pending = []
-        main = _stackless.clonable.getcurrent()
-
-        def zero_or_one():
-            main.switch()
-            return next_answer
-
-        # ____________________________________________________________
-
-        invalid_prefixes = {
-            (0, 0): True,
-            (0, 1, 0): True,
-            (0, 1, 1): True,
-            (1, 0): True,
-            (1, 1, 0, 0): True,
-            }
-
-        def example():
-            test = []
-            for n in range(5):
-                test.append(zero_or_one())
-                if tuple(test) in invalid_prefixes:
-                    raise Fail
-            raise Success(test)
-
-        res = first_solution(example)
-        assert res == [1, 1, 0, 1, 0]
-
-
-    def test_myself_may_not_be_me_any_more(self):
-        import gc
-        from _stackless import clonable
-
-        counter = [0]
-
-        def runner():
-            while 1:
-                assert clonable.getcurrent() is coro
-                counter[0] += 1
-                main.switch()
-
-        main = clonable.getcurrent()
-        coro = clonable()
-        coro.bind(runner)
-
-        coro.switch()
-        assert counter == [1]
-
-        assert clonable.getcurrent() is main
-        coro1 = coro.clone()
-        assert counter == [1]
-        assert clonable.getcurrent() is main
-        coro.switch()
-        assert counter == [2]
-        coro.switch()
-        assert counter == [3]
-        assert clonable.getcurrent() is main
-        del coro1
-        gc.collect()
-        #print "collected!"
-        assert clonable.getcurrent() is main
-        assert counter == [3]
-        coro.switch()
-        assert clonable.getcurrent() is main
-        assert counter == [4]
-
-
-    def test_fork(self):
-        import _stackless
-
-        class Fail(Exception):
-            pass
-
-        class Success(Exception):
-            pass
-
-        def first_solution(func):
-            global next_answer
-            co = _stackless.clonable()
-            co.bind(func)
-            try:
-                co.switch()
-            except Success, e:
-                return e.args[0]
-
-        def zero_or_one():
-            sub = _stackless.fork()
-            if sub is not None:
-                # in the parent: run the child first
-                try:
-                    sub.switch()
-                except Fail:
-                    pass
-                # then proceed with answer '1'
-                return 1
-            else:
-                # in the child: answer '0'
-                return 0
-
-        # ____________________________________________________________
-
-        invalid_prefixes = {
-            (0, 0): True,
-            (0, 1, 0): True,
-            (0, 1, 1): True,
-            (1, 0): True,
-            (1, 1, 0, 0): True,
-            }
-
-        def example():
-            test = []
-            for n in range(5):
-                test.append(zero_or_one())
-                if tuple(test) in invalid_prefixes:
-                    raise Fail
-            raise Success(test)
-
-        res = first_solution(example)
-        assert res == [1, 1, 0, 1, 0]
-
-    def test_clone_before_start(self):
-        """Tests that a clonable coroutine can be
-        cloned before it is started
-        (this used to fail with a segmentation fault)
-        """
-        import _stackless
-
-        counter = [0]
-        def simple_coro():
-            print "hello"
-            counter[0] += 1
-
-        s = _stackless.clonable()
-        s.bind(simple_coro)
-        t = s.clone()
-        s.switch()
-        t.switch()
-        assert counter[0] == 2
diff --git a/pypy/module/_stackless/test/test_composable_coroutine.py b/pypy/module/_stackless/test/test_composable_coroutine.py
deleted file mode 100644
--- a/pypy/module/_stackless/test/test_composable_coroutine.py
+++ /dev/null
@@ -1,133 +0,0 @@
-""" a faith is the connection between past and future that divides the
-    application into switch-compatible chunks.
-    -- stakkars
-"""
-from pypy.conftest import gettestobjspace
-from py.test import skip
-
-class AppTest_ComposableCoroutine:
-
-    def setup_class(cls):
-        space = gettestobjspace(usemodules=('_stackless',))
-        cls.space = space
-
-        cls.w_generator_ = space.appexec([], """():
-            import _stackless
-
-            generators_costate = _stackless.usercostate()
-            main = generators_costate.getcurrent()
-
-            class generator_iterator(_stackless.coroutine):
-
-                def __iter__(self):
-                    return self
-
-                def next(self):
-                    if self.gi_answer is not None:
-                        raise ValueError('stackless-generator'
-                                         ' already executing')
-                    self.gi_answer = []
-                    self.gi_caller = generators_costate.getcurrent()
-                    self.switch()
-                    answer = self.gi_answer
-                    self.gi_answer = None
-                    if answer:
-                        return answer[0]
-                    else:
-                        raise StopIteration
-
-            def generator(f):
-                def myfunc(*args, **kwds):
-                    g = generators_costate.spawn(generator_iterator)
-                    g.gi_answer = None
-                    g.bind(f, *args, **kwds)
-                    return g
-                return myfunc
-
-            def Yield(value):
-                g = generators_costate.getcurrent()
-                if g is main:
-                    raise ValueError('Yield() outside any stackless-generator')
-                assert isinstance(g, generator_iterator)
-                assert g.gi_answer == []
-                g.gi_answer.append(value)
-                g.gi_caller.switch()
-
-            generator.Yield = Yield
-            generator._costate = generators_costate
-            return (generator,)
-        """)
-
-    def test_simple_costate(self):
-        import _stackless
-        costate = _stackless.usercostate()
-        main = costate.getcurrent()
-
-        result = []
-        def f():
-            result.append(costate.getcurrent())
-        co = costate.spawn()
-        co.bind(f)
-        co.switch()
-        assert result == [co]
-
-    def test_generator(self):
-        generator, = self.generator_
-
-        def squares(n):
-            for i in range(n):
-                generator.Yield(i*i)
-        squares = generator(squares)
-
-        lst1 = [i*i for i in range(10)]
-        for got in squares(10):
-            expected = lst1.pop(0)
-            assert got == expected
-        assert lst1 == []
-
-    def test_multiple_costates(self):
-        """Test that two independent costates mix transparently:
-
-        - compute_costate, used for a coroutine that fills a list with
-                           some more items each time it is switched to
-
-        - generators_costate, used interally by self.generator (see above)
-        """
-
-        import _stackless
-        generator, = self.generator_
-
-        # you can see how it fails if we don't have two different costates
-        # by setting compute_costate to generator._costate instead
-        compute_costate = _stackless.usercostate()
-        compute_main = compute_costate.getcurrent()
-        lst = []
-
-        def filler():     # -> 0, 1, 2, 100, 101, 102, 200, 201, 202, 300 ...
-            for k in range(5):
-                for j in range(3):
-                    lst.append(100 * k + j)
-                compute_main.switch()
-
-        filler_co = compute_costate.spawn()
-        filler_co.bind(filler)
-
-        def grab_next_value():
-            while not lst:
-                #print 'filling more...'
-                filler_co.switch()
-                #print 'now lst =', lst
-            #print 'grabbing', lst[0]
-            return lst.pop(0)
-
-        def squares(n):
-            for i in range(n):
-                #print 'square:', i
-                generator.Yield(i*grab_next_value())
-        squares = generator(squares)
-
-        lst1 = [0, 1, 4,  300, 404, 510,  1200, 1407, 1616,  2700]
-        for got in squares(10):
-            expected = lst1.pop(0)
-            assert got == expected
-        assert lst1 == []
diff --git a/pypy/module/_stackless/test/test_coroutine.py b/pypy/module/_stackless/test/test_coroutine.py
deleted file mode 100644
--- a/pypy/module/_stackless/test/test_coroutine.py
+++ /dev/null
@@ -1,168 +0,0 @@
-from pypy.conftest import gettestobjspace, option
-from py.test import skip
-
-
-class AppTest_Coroutine:
-
-    def setup_class(cls):
-        space = gettestobjspace(usemodules=('_stackless',))
-        cls.space = space
-
-    def test_raise_propagate(self):
-        import _stackless as stackless
-        co = stackless.coroutine()
-        def f():
-            return 1/0
-        co.bind(f)
-        try:
-            co.switch()
-        except ZeroDivisionError:
-            pass
-        else:
-            raise AssertionError("exception not propagated")
-
-    def test_strange_test(self):
-        from _stackless import coroutine
-        def f():
-            print "in new coro"
-            return 42
-        def create():
-            b = coroutine()
-            b.bind(f)
-            print "bound"
-            b.switch()
-            print "switched"
-            return b
-        a = coroutine()
-        a.bind(create)
-        b = a.switch()
-        # now b.parent = a
-        def nothing():
-            pass
-        a.bind(nothing)
-        def kill():
-            # this sets a.parent = b
-            a.kill()
-        b.bind(kill)
-        b.switch()
-
-    def test_kill(self):
-        import _stackless as stackless
-        co = stackless.coroutine()
-        def f():
-            pass
-        co.bind(f)
-        assert co.is_alive
-        co.kill()
-        assert not co.is_alive
-
-    def test_kill_running(self):
-        coroutineexit = []
-        import _stackless as stackless
-        main = stackless.coroutine.getcurrent()
-        result = []
-        co = stackless.coroutine()
-        def f():
-            x = 2
-            try:
-                result.append(1)
-                main.switch()
-                x = 3
-            except CoroutineExit:
-                coroutineexit.append(True)
-                raise
-            finally:
-                result.append(x)
-            result.append(4)
-        co.bind(f)
-        assert co.is_alive
-        co.switch()
-        assert co.is_alive
-        assert result == [1]
-        co.kill()
-        assert not co.is_alive
-        assert result == [1, 2]
-        assert coroutineexit == [True]
-
-    def test_bogus_bind(self):
-        import _stackless as stackless
-        co = stackless.coroutine()
-        def f():
-            pass
-        co.bind(f)
-        raises(ValueError, co.bind, f)
-
-    def test__framestack(self):
-        import _stackless as stackless
-        main = stackless.coroutine.getmain()
-        co = stackless.coroutine()
-        def g():
-            return co._framestack
-        def f():
-            return g()
-
-        co.bind(f)
-        stack = co.switch()
-        assert stack == () # running corountine, _framestack is empty
-
-        co = stackless.coroutine()
-        def g():
-            return main.switch()
-        def f():
-            return g()
-
-        co.bind(f)
-        co.switch()
-        stack = co._framestack
-        assert len(stack) == 2
-        assert stack[0].f_code is f.func_code
-        assert stack[1].f_code is g.func_code
-
-        co = stackless.coroutine()
-
-
-
-class AppTestDirect:
-    def setup_class(cls):
-        if not option.runappdirect:
-            skip('pure appdirect test (run with -A)')
-        cls.space = gettestobjspace(usemodules=('_stackless',))
-
-    def test_stack_depth_limit(self):
-        import sys
-        import _stackless as stackless
-        st = stackless.get_stack_depth_limit()
-        try:
-            stackless.set_stack_depth_limit(1)
-            assert stackless.get_stack_depth_limit() == 1
-            try:
-                co = stackless.coroutine()
-                def f():
-                    pass
-                co.bind(f)
-                co.switch()
-            except RuntimeError:
-                pass
-        finally:
-            stackless.set_stack_depth_limit(st)
-
-class TestRandomThings:
-    def setup_class(cls):
-        cls.space = gettestobjspace(usemodules=('_stackless',))
-
-    def test___del___handling(self):
-        space = self.space
-        w_l = space.newlist([])
-        coro = space.appexec([w_l], """(l):
-            from _stackless import coroutine
-            class MyCoroutine(coroutine):
-                def __del__(self):
-                    l.append(self.is_zombie)
-            return MyCoroutine()
-        """)
-        coro.__del__()
-        space.user_del_action.perform(space.getexecutioncontext(), None)
-        coro._kill_finally()
-        assert space.len_w(w_l) == 1
-        res = space.is_true(space.getitem(w_l, space.wrap(0)))
-        assert res
diff --git a/pypy/module/_stackless/test/test_greenlet.py b/pypy/module/_stackless/test/test_greenlet.py
deleted file mode 100644
--- a/pypy/module/_stackless/test/test_greenlet.py
+++ /dev/null
@@ -1,643 +0,0 @@
-from pypy.conftest import gettestobjspace, skip_on_missing_buildoption
-
-class AppTest_Greenlet:
-
-    def setup_class(cls):
-        space = gettestobjspace(usemodules=('_stackless',))
-        cls.space = space
-
-    def test_very_simple(self):
-        from _stackless import greenlet
-        lst = []
-        def f(x):
-            lst.append(x)
-            return x + 10
-        g = greenlet(f)
-        assert not g
-        res = g.switch(20)
-        assert res == 30
-        assert lst == [20]
-        assert g.dead
-        assert not g
-
-    def test_switch_back_to_main(self):
-        from _stackless import greenlet
-        lst = []
-        main = greenlet.getcurrent()
-        def f(x):
-            lst.append(x)
-            x = main.switch(x + 10)
-            return 40 + x 
-        g = greenlet(f)
-        res = g.switch(20)
-        assert res == 30
-        assert lst == [20]
-        assert not g.dead
-        res = g.switch(2)
-        assert res == 42
-        assert g.dead
-
-    def test_simple(self):
-        from _stackless import greenlet
-        lst = []
-        gs = []
-        def f():
-            lst.append(1)
-            greenlet.getcurrent().parent.switch()
-            lst.append(3)
-        g = greenlet(f)
-        lst.append(0)
-        g.switch()
-        lst.append(2)
-        g.switch()
-        lst.append(4)
-        assert lst == range(5)
-
-    def test_exception_simple(self):
-        from _stackless import greenlet
-        def f():
-            raise ValueError
-        g1 = greenlet(f)
-        raises(ValueError, g1.switch)
-
-    def test_exception_propagate(self):
-        from _stackless import greenlet
-        def f():
-            raise ValueError
-        def g():
-            return g1.switch()
-        g1 = greenlet(f)
-        g2 = greenlet(g)
-        raises(ValueError, g1.switch)
-        g1 = greenlet(f)
-        raises(ValueError, g2.switch)
-
-
-    def test_exc_info_save_restore(self):
-        from _stackless import greenlet
-        import sys
-        def f():
-            try:
-                raise ValueError('fun')
-            except:
-                exc_info = sys.exc_info()
-                greenlet(h).switch()
-                assert exc_info == sys.exc_info()
-
-        def h():
-            assert sys.exc_info() == (None, None, None)
-
-        greenlet(f).switch()
-
-    def test_exception(self):
-        from _stackless import greenlet
-        import sys
-        def fmain(seen):
-            try:
-                greenlet.getcurrent().parent.switch()
-            except:
-                seen.append(sys.exc_info()[0])
-                raise
-            raise ValueError
-        seen = []
-        g1 = greenlet(fmain)
-        g2 = greenlet(fmain)
-        g1.switch(seen)
-        g2.switch(seen)
-        raises(TypeError, "g2.parent = 1")
-        g2.parent = g1
-        assert seen == []
-        raises(ValueError, g2.switch)
-        assert seen == [ValueError]
-        g2.switch()
-        assert seen == [ValueError]
-
-    def test_send_exception(self):
-        from _stackless import greenlet
-        import sys
-        def send_exception(g, exc):
-            # note: send_exception(g, exc)  can be now done with  g.throw(exc).
-            # the purpose of this test is to explicitely check the propagation rules.
-            def crasher(exc):
-                raise exc
-            g1 = greenlet(crasher)
-            g1.parent = g
-            g1.switch(exc)
-        def fmain(seen):
-            try:
-                greenlet.getcurrent().parent.switch()
-            except:
-                seen.append(sys.exc_info()[0])
-                raise
-            raise ValueError
-
-        seen = []
-        g1 = greenlet(fmain)
-        g1.switch(seen)
-        raises(KeyError, "send_exception(g1, KeyError)")
-        assert seen == [KeyError]
-        seen = []
-        g1 = greenlet(fmain)
-        g1.switch(seen)
-        raises(KeyError, "g1.throw(KeyError)")
-        assert seen == [KeyError]
-        assert g1.dead
-
-    def test_frame(self):
-        from _stackless import greenlet
-        import sys
-        def f1():
-            f = sys._getframe(0)
-            assert f.f_back is None
-            greenlet.getcurrent().parent.switch(f)
-            return "meaning of life"
-        g = greenlet(f1)
-        frame = g.switch()
-        assert frame is g.gr_frame
-        assert g
-        next = g.switch()
-        assert not g
-        assert next == "meaning of life"
-        assert g.gr_frame is None
-
-    def test_mixing_greenlet_coroutine(self):
-        from _stackless import greenlet, coroutine
-        lst = []
-        def f():
-            lst.append(1)
-            greenlet.getcurrent().parent.switch()
-            lst.append(3)
-        def make_h(c):
-            def h():
-                g = greenlet(f)
-                lst.append(0)
-                g.switch()
-                c.switch()
-                lst.append(2)
-                g.switch()
-                c.switch()
-                lst.append(4)
-                c.switch()
-            return h
-        c1 = coroutine.getcurrent()
-        c2 = coroutine()
-        c3 = coroutine()
-        c2.bind(make_h(c3))
-        c3.bind(make_h(c2))
-        c2.switch()
-        assert lst == [0, 1, 0, 1, 2, 3, 2, 3, 4, 4]
-
-    def test_dealloc(self):
-        skip("not working yet")
-        from _stackless import greenlet
-        import sys
-        def fmain(seen):
-            try:
-                greenlet.getcurrent().parent.switch()
-            except:
-                seen.append(sys.exc_info()[0])
-                raise
-            raise ValueError
-        seen = []
-        seen = []
-        g1 = greenlet(fmain)
-        g2 = greenlet(fmain)
-        g1.switch(seen)
-        g2.switch(seen)
-        assert seen == []
-        del g1
-        assert seen == [greenlet.GreenletExit]
-        del g2
-        assert seen == [greenlet.GreenletExit, greenlet.GreenletExit]
-
-
-# ____________________________________________________________
-#
-# The tests from greenlets.
-# For now, without the ones that involve threads
-#
-class AppTest_PyMagicTestGreenlet:
-
-    def setup_class(cls):
-        space = gettestobjspace(usemodules=('_stackless',))
-        cls.space = space
-        cls.w_glob = space.appexec([], """():
-            import sys
-            from _stackless import greenlet
-
-            class SomeError(Exception):
-                pass
-
-            def fmain(seen):
-                try:
-                    greenlet.getcurrent().parent.switch()
-                except:
-                    seen.append(sys.exc_info()[0])
-                    raise
-                raise SomeError
-
-            class Glob: pass
-            glob = Glob()
-            glob.__dict__.update(locals())
-            return glob
-        """)
-
-    def test_simple(self):
-        greenlet = self.glob.greenlet
-        lst = []
-        def f():
-            lst.append(1)
-            greenlet.getcurrent().parent.switch()
-            lst.append(3)
-        g = greenlet(f)
-        lst.append(0)
-        g.switch()
-        lst.append(2)
-        g.switch()
-        lst.append(4)
-        assert lst == range(5)
-
-    def test_exception(self):
-        greenlet  = self.glob.greenlet
-        fmain     = self.glob.fmain
-        SomeError = self.glob.SomeError
-        seen = []
-        g1 = greenlet(fmain)
-        g2 = greenlet(fmain)
-        g1.switch(seen)
-        g2.switch(seen)
-        g2.parent = g1
-        assert seen == []
-        raises(SomeError, g2.switch)
-        assert seen == [SomeError]
-        g2.switch()
-        assert seen == [SomeError]
-
-    def test_send_exception(self):
-        greenlet  = self.glob.greenlet
-        fmain     = self.glob.fmain
-        def send_exception(g, exc):
-            # note: send_exception(g, exc)  can be now done with  g.throw(exc).
-            # the purpose of this test is to explicitely check the
-            # propagation rules.
-            def crasher(exc):
-                raise exc
-            g1 = greenlet(crasher, parent=g)
-            g1.switch(exc)
-
-        seen = []
-        g1 = greenlet(fmain)
-        g1.switch(seen)
-        raises(KeyError, "send_exception(g1, KeyError)")
-        assert seen == [KeyError]
-
-    def test_dealloc(self):
-        skip("XXX in-progress: GC handling of greenlets")
-        import gc
-        greenlet = self.glob.greenlet
-        fmain    = self.glob.fmain
-        seen = []
-        g1 = greenlet(fmain)
-        g2 = greenlet(fmain)
-        g1.switch(seen)
-        g2.switch(seen)
-        assert seen == []
-        del g1
-        gc.collect()
-        assert seen == [greenlet.GreenletExit]
-        del g2
-        gc.collect()
-        assert seen == [greenlet.GreenletExit, greenlet.GreenletExit]
-
-    def test_frame(self):
-        import sys
-        greenlet = self.glob.greenlet
-        def f1():
-            f = sys._getframe(0)
-            assert f.f_back is None
-            greenlet.getcurrent().parent.switch(f)
-            return "meaning of life"
-        g = greenlet(f1)
-        frame = g.switch()
-        assert frame is g.gr_frame
-        assert g
-        next = g.switch()
-        assert not g
-        assert next == "meaning of life"
-        assert g.gr_frame is None
-
-
-class AppTest_PyMagicTestThrow:
-
-    def setup_class(cls):
-        space = gettestobjspace(usemodules=('_stackless',))
-        cls.space = space
-
-    def test_class(self):
-        from _stackless import greenlet
-        def switch(*args):
-            return greenlet.getcurrent().parent.switch(*args)
-
-        def f():
-            try:
-                switch("ok")
-            except RuntimeError:
-                switch("ok")
-                return
-            switch("fail")
-
-        g = greenlet(f)
-        res = g.switch()
-        assert res == "ok"
-        res = g.throw(RuntimeError)
-        assert res == "ok"
-
-    def test_val(self):
-        from _stackless import greenlet
-        def switch(*args):
-            return greenlet.getcurrent().parent.switch(*args)
-
-        def f():
-            try:
-                switch("ok")
-            except RuntimeError, val:
-                if str(val) == "ciao":
-                    switch("ok")
-                    return
-            switch("fail")
-
-        g = greenlet(f)
-        res = g.switch()
-        assert res == "ok"
-        res = g.throw(RuntimeError("ciao"))
-        assert res == "ok"
-
-        g = greenlet(f)
-        res = g.switch()
-        assert res == "ok"
-        res = g.throw(RuntimeError, "ciao")
-        assert res == "ok"
-
-    def test_kill(self):
-        from _stackless import greenlet
-        def switch(*args):
-            return greenlet.getcurrent().parent.switch(*args)
-
-        def f():
-            switch("ok")
-            switch("fail")
-
-        g = greenlet(f)
-        res = g.switch()
-        assert res == "ok"
-        res = g.throw()
-        assert isinstance(res, greenlet.GreenletExit)
-        assert g.dead
-        res = g.throw()    # immediately eaten by the already-dead greenlet
-        assert isinstance(res, greenlet.GreenletExit)
-
-    def test_throw_goes_to_original_parent(self):
-        from _stackless import greenlet
-        main = greenlet.getcurrent()
-        def f1():
-            try:
-                main.switch("f1 ready to catch")
-            except IndexError:
-                return "caught"
-            else:
-                return "normal exit"
-        def f2():
-            main.switch("from f2")
-
-        g1 = greenlet(f1)
-        g2 = greenlet(f2, parent=g1)
-        raises(IndexError, g2.throw, IndexError)
-        assert g2.dead
-        assert g1.dead
-
-        g1 = greenlet(f1)
-        g2 = greenlet(f2, parent=g1)
-        res = g1.switch()
-        assert res == "f1 ready to catch"
-        res = g2.throw(IndexError)
-        assert res == "caught"
-        assert g2.dead
-        assert g1.dead
-
-        g1 = greenlet(f1)
-        g2 = greenlet(f2, parent=g1)
-        res = g1.switch()
-        assert res == "f1 ready to catch"
-        res = g2.switch()
-        assert res == "from f2"
-        res = g2.throw(IndexError)
-        assert res == "caught"
-        assert g2.dead
-        assert g1.dead
-            
-
-class AppTest_PyMagicTestGenerator:
-
-    def setup_class(cls):
-        space = gettestobjspace(usemodules=('_stackless',))
-        cls.space = space
-
-    def test_generator(self):
-        from _stackless import greenlet
-
-        class genlet(greenlet):
-
-            def __init__(self, *args, **kwds):
-                self.args = args
-                self.kwds = kwds
-
-            def run(self):
-                fn, = self.fn
-                fn(*self.args, **self.kwds)
-
-            def __iter__(self):
-                return self
-
-            def next(self):
-                self.parent = greenlet.getcurrent()
-                result = self.switch()
-                if self:
-                    return result
-                else:
-                    raise StopIteration
-
-        def Yield(value):
-            g = greenlet.getcurrent()
-            while not isinstance(g, genlet):
-                if g is None:
-                    raise RuntimeError, 'yield outside a genlet'
-                g = g.parent
-            g.parent.switch(value)
-
-        def generator(func):
-            class generator(genlet):
-                fn = (func,)
-            return generator
-
-        # ___ test starts here ___
-        seen = []
-        def g(n):
-            for i in range(n):
-                seen.append(i)
-                Yield(i)
-        g = generator(g)
-        for k in range(3):
-            for j in g(5):
-                seen.append(j)
-        assert seen == 3 * [0, 0, 1, 1, 2, 2, 3, 3, 4, 4]
-
-
-class AppTest_PyMagicTestGeneratorNested:
-
-    def setup_class(cls):
-        space = gettestobjspace(usemodules=('_stackless',))
-        cls.space = space
-        cls.w_glob = space.appexec([], """():
-            from _stackless import greenlet
-
-            class genlet(greenlet):
-
-                def __init__(self, *args, **kwds):
-                    self.args = args
-                    self.kwds = kwds
-                    self.child = None
-
-                def run(self):
-                    fn, = self.fn
-                    fn(*self.args, **self.kwds)
-
-                def __iter__(self):
-                    return self
-
-                def set_child(self, child):
-                    self.child = child
-
-                def next(self):
-                    if self.child:
-                        child = self.child
-                        while child.child:
-                            tmp = child
-                            child = child.child
-                            tmp.child = None
-
-                        result = child.switch()
-                    else:
-                        self.parent = greenlet.getcurrent()            
-                        result = self.switch()
-
-                    if self:
-                        return result
-                    else:
-                        raise StopIteration
-
-            def Yield(value, level = 1):
-                g = greenlet.getcurrent()
-
-                while level != 0:
-                    if not isinstance(g, genlet):
-                        raise RuntimeError, 'yield outside a genlet'
-                    if level > 1:
-                        g.parent.set_child(g)
-                    g = g.parent
-                    level -= 1
-
-                g.switch(value)
-
-            def Genlet(func):
-                class Genlet(genlet):
-                    fn = (func,)
-                return Genlet
-
-            class Glob: pass
-            glob = Glob()
-            glob.__dict__.update(locals())
-            return glob
-        """)
-
-    def test_genlet_1(self):
-        Genlet = self.glob.Genlet
-        Yield  = self.glob.Yield
-
-        def g1(n, seen):
-            for i in range(n):
-                seen.append(i+1)
-                yield i
-
-        def g2(n, seen):
-            for i in range(n):
-                seen.append(i+1)
-                Yield(i)
-
-        g2 = Genlet(g2)
-
-        def nested(i):
-            Yield(i)
-
-        def g3(n, seen):
-            for i in range(n):
-                seen.append(i+1)
-                nested(i)
-        g3 = Genlet(g3)
-
-        raises(RuntimeError, Yield, 10)
-        for g in [g1, g2, g3]:
-            seen = []
-            for k in range(3):
-                for j in g(5, seen):
-                    seen.append(j)
-            assert seen == 3 * [1, 0, 2, 1, 3, 2, 4, 3, 5, 4]
-        raises(RuntimeError, Yield, 10)
-
-    def test_nested_genlets(self):
-        Genlet = self.glob.Genlet
-        Yield  = self.glob.Yield
-        def a(n):
-            if n == 0:
-                return
-            for ii in ax(n-1):
-                Yield(ii)
-            Yield(n)
-        ax = Genlet(a)
-        seen = []
-        for ii in ax(5):
-            seen.append(ii)
-        assert seen == [1, 2, 3, 4, 5]
-
-    def test_perms(self):
-        Genlet = self.glob.Genlet
-        Yield  = self.glob.Yield
-        def perms(l):
-            if len(l) > 1:
-                for e in l:
-                    # No syntactical sugar for generator expressions
-                    [Yield([e] + p) for p in perms([x for x in l if x!=e])]
-            else:
-                Yield(l)
-        perms = Genlet(perms)
-        gen_perms = perms(range(4))
-        permutations = list(gen_perms)
-        assert len(permutations) == 4*3*2*1
-        assert [0,1,2,3] in permutations
-        assert [3,2,1,0] in permutations
-
-    def test_layered_genlets(self):
-        Genlet = self.glob.Genlet
-        Yield  = self.glob.Yield
-        def gr1(n):
-            for ii in range(1, n):
-                Yield(ii)
-                Yield(ii * ii, 2)
-        gr1 = Genlet(gr1)
-        def gr2(n, seen):
-            for ii in gr1(n):
-                seen.append(ii)
-        gr2 = Genlet(gr2)
-        seen = []
-        for ii in gr2(5, seen):
-            seen.append(ii)
-        assert seen == [1, 1, 2, 4, 3, 9, 4, 16]
diff --git a/pypy/module/_stackless/test/test_interp_clonable.py b/pypy/module/_stackless/test/test_interp_clonable.py
deleted file mode 100644
--- a/pypy/module/_stackless/test/test_interp_clonable.py
+++ /dev/null
@@ -1,118 +0,0 @@
-"""
-testing cloning
-"""
-import py; py.test.skip("clonable coroutines not really maintained any more")
-
-from pypy import conftest; conftest.translation_test_so_skip_if_appdirect()
-from pypy.translator.c import gc
-from pypy.rpython.memory.gctransform import stacklessframework
-from pypy.rpython.memory.test import test_transformed_gc
-from pypy.module._stackless.rclonable import InterpClonableCoroutine as ClonableCoroutine
-from pypy.module._stackless.rclonable import AbstractThunk, fork
-
-class TestClonableCoroutine(test_transformed_gc.GCTest):
-
-    gcname = "marksweep"
-    stacklessgc = True
-    class gcpolicy(gc.StacklessFrameworkGcPolicy):
-        class transformerclass(stacklessframework.StacklessFrameworkGCTransformer):
-            GC_PARAMS = {'start_heap_size': 4096 }
-
-    def test_clone(self):
-        class T(AbstractThunk):
-            def __init__(self, result):
-                self.result = result
-            def call(self):
-                self.result.append(2)
-                ClonableCoroutine.getmain().switch()
-                self.result.append(4)
-        def f():
-            result = []
-            coro = ClonableCoroutine()
-            coro.bind(T(result))
-            result.append(1)
-            coro.switch()
-            coro2 = coro.clone()
-            result.append(3)
-            coro2.switch()
-            result.append(5)
-            coro.switch()
-            result.append(6)
-            n = 0
-            for i in result:
-                n = n*10 + i
-            return n
-
-        run = self.runner(f)
-        res = run([])
-        assert res == 1234546
-
-    def test_clone_local_state(self):
-        class T(AbstractThunk):
-            def __init__(self, result):
-                self.result = result
-            def call(self):
-                localstate = []
-                localstate.append(10)
-                self.result.append(2)
-                ClonableCoroutine.getmain().switch()
-                localstate.append(20)
-                if localstate == [10, 20]:
-                    self.result.append(4)
-                else:
-                    self.result.append(0)
-        def f():
-            result = []
-            coro = ClonableCoroutine()
-            coro.bind(T(result))
-            result.append(1)
-            coro.switch()
-            coro2 = coro.clone()
-            result.append(3)
-            coro2.switch()
-            result.append(5)
-            coro.switch()
-            result.append(6)
-            n = 0
-            for i in result:
-                n = n*10 + i
-            return n
-
-        run = self.runner(f)
-        res = run([])
-        assert res == 1234546
-
-    def test_fork(self):
-        class T(AbstractThunk):
-            def __init__(self, result):
-                self.result = result
-            def call(self):
-                localdata = [10]
-                self.result.append(2)
-                newcoro = fork()
-                localdata.append(20)
-                if newcoro is not None:
-                    # in the parent
-                    self.result.append(3)
-                    newcoro.switch()
-                    self.result.append(5)
-                else:
-                    # in the child
-                    self.result.append(4)
-                localdata.append(30)
-                self.result.append(localdata != [10, 20, 30])
-        def f():
-            result = []
-            coro = ClonableCoroutine()
-            coro.bind(T(result))
-            result.append(1)
-            coro.switch()
-            result.append(6)
-            n = 0
-            for i in result:
-                n = n*10 + i
-            return n
-
-        run = self.runner(f)
-        res = run([])
-        assert res == 12340506
diff --git a/pypy/module/_stackless/test/test_pickle.py b/pypy/module/_stackless/test/test_pickle.py
deleted file mode 100644
--- a/pypy/module/_stackless/test/test_pickle.py
+++ /dev/null
@@ -1,487 +0,0 @@
-from pypy.conftest import gettestobjspace, option
-import py
-
-# app-level testing of coroutine pickling
-
-
-class AppTestBasic:
-    def setup_class(cls):
-        cls.space = gettestobjspace(usemodules=('_stackless',))
-
-    def test_pickle_main(self):
-        import _stackless, pickle
-        main = _stackless.coroutine.getcurrent()
-        s = pickle.dumps(main)
-        c = pickle.loads(s)
-        assert c is main
-
-
-class AppTestPickle:
-
-    def setup_class(cls):
-        cls.space = gettestobjspace(usemodules=('_stackless',), CALL_METHOD=True)
-
-    def test_pickle_coroutine_empty(self):
-        # this test is limited to basic pickling.
-        # real stacks can only tested with a stackless pypy build.
-        import _stackless as stackless
-        co = stackless.coroutine()
-        import pickle
-        pckl = pickle.dumps(co)
-        co2 = pickle.loads(pckl)
-        # the empty unpickled coroutine can still be used:
-        result = []
-        co2.bind(result.append, 42)
-        co2.switch()
-        assert result == [42]
-
-    def test_pickle_coroutine_bound(self):
-        import pickle
-        import _stackless
-        lst = [4]
-        co = _stackless.coroutine()
-        co.bind(lst.append, 2)
-        pckl = pickle.dumps((co, lst))
-
-        (co2, lst2) = pickle.loads(pckl)
-        assert lst2 == [4]
-        co2.switch()
-        assert lst2 == [4, 2]
-
-
-    def test_simple_ish(self):
-
-        import new, sys
-
-        mod = new.module('mod')
-        sys.modules['mod'] = mod
-        try:
-            exec '''
-output = []
-import _stackless
-def f(coro, n, x):
-    if n == 0:
-        coro.switch()
-        return
-    f(coro, n-1, 2*x)
-    output.append(x)
-
-def example():
-    main_coro = _stackless.coroutine.getcurrent()
-    sub_coro = _stackless.coroutine()
-    sub_coro.bind(f, main_coro, 5, 1)
-    sub_coro.switch()
-
-    import pickle
-    pckl = pickle.dumps(sub_coro)
-    new_coro = pickle.loads(pckl)
-
-    new_coro.switch()
-
-example()
-assert output == [16, 8, 4, 2, 1]
-''' in mod.__dict__
-        finally:
-            del sys.modules['mod']
-
-    def test_pickle_again(self):
-
-        import new, sys
-
-        mod = new.module('mod')
-        sys.modules['mod'] = mod
-        try:
-            exec '''
-output = []
-import _stackless
-def f(coro, n, x):
-    if n == 0:
-        coro.switch()
-        return
-    f(coro, n-1, 2*x)
-    output.append(x)
-
-def example():
-    main_coro = _stackless.coroutine.getcurrent()
-    sub_coro = _stackless.coroutine()
-    sub_coro.bind(f, main_coro, 5, 1)
-    sub_coro.switch()
-
-    import pickle
-    pckl = pickle.dumps(sub_coro)
-    new_coro = pickle.loads(pckl)
-    pckl = pickle.dumps(new_coro)
-    newer_coro = pickle.loads(pckl)
-
-    newer_coro.switch()
-
-example()
-assert output == [16, 8, 4, 2, 1]
-''' in mod.__dict__
-        finally:
-            del sys.modules['mod']
-
-    def test_kwargs(self):
-
-        import new, sys
-
-        mod = new.module('mod')
-        sys.modules['mod'] = mod
-        try:
-            exec '''
-output = []
-import _stackless
-def f(coro, n, x, step=4):
-    if n == 0:
-        coro.switch()
-        return
-    f(coro, n-1, 2*x, step=1)
-    output.append(x)
-
-def example():
-    main_coro = _stackless.coroutine.getcurrent()
-    sub_coro = _stackless.coroutine()
-    sub_coro.bind(f, main_coro, 5, 1, 1)
-    sub_coro.switch()
-
-    import pickle
-    pckl = pickle.dumps(sub_coro)
-    new_coro = pickle.loads(pckl)
-
-    new_coro.switch()
-
-example()
-assert output == [16, 8, 4, 2, 1]
-''' in mod.__dict__
-        finally:
-            del sys.modules['mod']
-
-    def test_starstarargs(self):
-
-        import new, sys
-
-        mod = new.module('mod')
-        sys.modules['mod'] = mod
-        try:
-            exec '''
-output = []
-import _stackless
-def f(coro, n, x, step=4):
-    if n == 0:
-        coro.switch()
-        return
-    f(coro, n-1, 2*x, **{'step': 1})
-    output.append(x)
-
-def example():
-    main_coro = _stackless.coroutine.getcurrent()
-    sub_coro = _stackless.coroutine()
-    sub_coro.bind(f, main_coro, 5, 1, 1)
-    sub_coro.switch()
-
-    import pickle
-    pckl = pickle.dumps(sub_coro)
-    new_coro = pickle.loads(pckl)
-
-    new_coro.switch()
-
-example()
-assert output == [16, 8, 4, 2, 1]
-''' in mod.__dict__
-        finally:
-            del sys.modules['mod']
-
-    def test_closure(self):
-        import new, sys
-
-        mod = new.module('mod')
-        sys.modules['mod'] = mod
-        try:
-            exec '''
-output = []
-import _stackless
-def example():
-    main_coro = _stackless.coroutine.getcurrent()
-    sub_coro = _stackless.coroutine()
-    y = 3
-    def f(coro, n, x):
-        if n == 0:
-            coro.switch()
-            return
-        f(coro, n-1, 2*x)
-        output.append(x+y)
-
-    sub_coro.bind(f, main_coro, 5, 1)
-    sub_coro.switch()
-
-    import pickle
-    pckl = pickle.dumps(sub_coro)
-    new_coro = pickle.loads(pckl)
-
-    new_coro.switch()
-
-example()
-assert output == [19, 11, 7, 5, 4]
-''' in mod.__dict__
-        finally:
-            del sys.modules['mod']
-
-    def test_exception(self):
-        import new, sys
-
-        mod = new.module('mod')
-        sys.modules['mod'] = mod
-        try:
-            exec '''
-output = []
-import _stackless
-def f(coro):
-    try:
-        raise ValueError
-    except:
-        coro.switch()
-        import sys
-        t, v, tb = sys.exc_info()
-        output.append(t)
-
-def example():
-    main_coro = _stackless.coroutine.getcurrent()
-    sub_coro = _stackless.coroutine()
-
-    sub_coro.bind(f, main_coro)
-    sub_coro.switch()
-
-    import pickle
-    pckl = pickle.dumps(sub_coro)
-    new_coro = pickle.loads(pckl)
-
-    new_coro.switch()
-
-example()
-assert output == [ValueError]
-''' in mod.__dict__
-        finally:
-            del sys.modules['mod']
-
-    def test_exception_after_unpickling(self):
-
-        import new, sys
-
-        mod = new.module('mod')
-        sys.modules['mod'] = mod
-        try:
-            exec '''
-output = []
-import _stackless
-def f(coro, n, x):
-    if n == 0:
-        coro.switch()
-        raise ValueError
-    try:
-        f(coro, n-1, 2*x)
-    finally:
-        output.append(x)
-
-def example():
-    main_coro = _stackless.coroutine.getcurrent()
-    sub_coro = _stackless.coroutine()
-    sub_coro.bind(f, main_coro, 5, 1)
-    sub_coro.switch()
-
-    import pickle
-    pckl = pickle.dumps(sub_coro)
-    new_coro = pickle.loads(pckl)
-
-    try:
-        sub_coro.switch()
-    except ValueError:
-        pass
-    else:
-        assert 0
-    try:
-        new_coro.switch()
-    except ValueError:
-        pass
-    else:
-        assert 0
-
-example()
-assert output == [16, 8, 4, 2, 1] * 2
-''' in mod.__dict__
-        finally:
-            del sys.modules['mod']
-
-    def test_loop(self):
-        import new, sys
-
-        mod = new.module('mod')
-        sys.modules['mod'] = mod
-        try:
-            exec '''
-output = []
-import _stackless
-def f(coro):
-    for x in (1,2,3):
-        coro.switch()
-        output.append(x)
-
-def example():
-    main_coro = _stackless.coroutine.getcurrent()
-    sub_coro = _stackless.coroutine()
-
-    sub_coro.bind(f, main_coro)
-    sub_coro.switch()
-
-    import pickle
-    pckl = pickle.dumps(sub_coro)
-    new_coro = pickle.loads(pckl)
-
-    new_coro.switch()
-    new_coro.switch()
-    new_coro.switch()
-
-example()
-assert output == [1, 2, 3]
-''' in mod.__dict__
-        finally:
-            del sys.modules['mod']
-
-    def test_valstack(self):
-        import new, sys
-
-        mod = new.module('mod')
-        sys.modules['mod'] = mod
-        try:
-            exec '''
-output = []
-import _stackless
-def f(coro):
-    r = 1+g(coro)+3
-    output.append(r)
-
-def g(coro):
-    coro.switch()
-    return 2
-
-def example():
-    main_coro = _stackless.coroutine.getcurrent()
-    sub_coro = _stackless.coroutine()
-
-    sub_coro.bind(f, main_coro)
-    sub_coro.switch()
-
-    import pickle
-    pckl = pickle.dumps(sub_coro)
-    new_coro = pickle.loads(pckl)
-
-    new_coro.switch()
-
-
-example()
-assert output == [6]
-''' in mod.__dict__
-        finally:
-            del sys.modules['mod']
-
-
-    def test_exec_and_locals(self):
-        import new, sys
-
-        mod = new.module('mod')
-        sys.modules['mod'] = mod
-        try:
-            exec '''
-output = []
-import _stackless
-
-def f(coro):
-    x = None
-    exec "x = 9"
-    coro.switch()
-    output.append(x)
-
-def example():
-    main_coro = _stackless.coroutine.getcurrent()
-    sub_coro = _stackless.coroutine()
-    sub_coro.bind(f, main_coro)
-    sub_coro.switch()
-
-    import pickle
-    pckl = pickle.dumps(sub_coro)
-    new_coro = pickle.loads(pckl)
-
-    new_coro.switch()
-
-example()
-assert output == [9]
-''' in mod.__dict__
-        finally:
-            del sys.modules['mod']
-
-
-    def test_solver(self):
-        import new, sys
-
-        mod = new.module('mod')
-        sys.modules['mod'] = mod
-        try:
-            exec '''
-import _stackless, pickle
-
-class Fail(Exception):
-    pass
-
-class Success(Exception):
-    pass
-
-def first_solution(func):
-    global next_answer
-    co = _stackless.coroutine()
-    co.bind(func)
-    pending = [(co, None)]
-    while pending:
-        co, next_answer = pending.pop()
-        try:
-            co.switch()
-        except Fail:
-            pass
-        except Success, e:
-            return e.args[0]
-        else:
-            # zero_or_one() called, clone the coroutine
-            # NB. this seems to be quite slow
-            co2 = pickle.loads(pickle.dumps(co))
-            pending.append((co2, 1))
-            pending.append((co, 0))
-    raise Fail("no solution")
-
-pending = []
-main = _stackless.coroutine.getcurrent()
-
-def zero_or_one():
-    main.switch()
-    return next_answer
-
-# ____________________________________________________________
-
-invalid_prefixes = {
-    (0, 0): True,
-    (0, 1, 0): True,
-    (0, 1, 1): True,
-    (1, 0): True,
-    (1, 1, 0, 0): True,
-    }
-
-def example():
-    test = []
-    for n in range(5):
-        test.append(zero_or_one())
-        if tuple(test) in invalid_prefixes:
-            raise Fail
-    raise Success(test)
-
-res = first_solution(example)
-assert res == [1, 1, 0, 1, 0]
-''' in mod.__dict__
-        finally:
-            del sys.modules['mod']
diff --git a/pypy/module/_weakref/interp__weakref.py b/pypy/module/_weakref/interp__weakref.py
--- a/pypy/module/_weakref/interp__weakref.py
+++ b/pypy/module/_weakref/interp__weakref.py
@@ -8,24 +8,12 @@
 
 
 class WeakrefLifeline(W_Root):
+    cached_weakref_index = -1
+    cached_proxy_index = -1
+
     def __init__(self, space):
         self.space = space
         self.refs_weak = []
-        self.cached_weakref_index = -1
-        self.cached_proxy_index = -1
-
-    def __del__(self):
-        """This runs when the interp-level object goes away, and allows
-        its lifeline to go away.  The purpose of this is to activate the
-        callbacks even if there is no __del__ method on the interp-level
-        W_Root subclass implementing the object.
-        """
-        for i in range(len(self.refs_weak) - 1, -1, -1):
-            w_ref = self.refs_weak[i]()
-            if w_ref is not None and w_ref.w_callable is not None:
-                w_ref.enqueue_for_destruction(self.space,
-                                              W_WeakrefBase.activate_callback,
-                                              'weakref callback of ')
 
     def clear_all_weakrefs(self):
         """Clear all weakrefs.  This is called when an app-level object has
@@ -39,12 +27,11 @@
         # weakref callbacks are not invoked eagerly here.  They are
         # invoked by self.__del__() anyway.
 
-    @jit.dont_look_inside
-    def get_or_make_weakref(self, space, w_subtype, w_obj, w_callable):
+    def get_or_make_weakref(self, w_subtype, w_obj):
+        space = self.space
         w_weakreftype = space.gettypeobject(W_Weakref.typedef)
         is_weakreftype = space.is_w(w_weakreftype, w_subtype)
-        can_reuse = space.is_w(w_callable, space.w_None)
-        if is_weakreftype and can_reuse and self.cached_weakref_index >= 0:
+        if is_weakreftype and self.cached_weakref_index >= 0:
             w_cached = self.refs_weak[self.cached_weakref_index]()
             if w_cached is not None:
                 return w_cached
@@ -52,16 +39,15 @@
                 self.cached_weakref_index = -1
         w_ref = space.allocate_instance(W_Weakref, w_subtype)
         index = len(self.refs_weak)
-        W_Weakref.__init__(w_ref, space, w_obj, w_callable)
+        W_Weakref.__init__(w_ref, space, w_obj, None)
         self.refs_weak.append(weakref.ref(w_ref))
-        if is_weakreftype and can_reuse:
+        if is_weakreftype:
             self.cached_weakref_index = index
         return w_ref
 
-    @jit.dont_look_inside
-    def get_or_make_proxy(self, space, w_obj, w_callable):
-        can_reuse = space.is_w(w_callable, space.w_None)
-        if can_reuse and self.cached_proxy_index >= 0:
+    def get_or_make_proxy(self, w_obj):
+        space = self.space
+        if self.cached_proxy_index >= 0:
             w_cached = self.refs_weak[self.cached_proxy_index]()
             if w_cached is not None:
                 return w_cached
@@ -69,12 +55,11 @@
                 self.cached_proxy_index = -1
         index = len(self.refs_weak)
         if space.is_true(space.callable(w_obj)):
-            w_proxy = W_CallableProxy(space, w_obj, w_callable)
+            w_proxy = W_CallableProxy(space, w_obj, None)
         else:
-            w_proxy = W_Proxy(space, w_obj, w_callable)
+            w_proxy = W_Proxy(space, w_obj, None)
         self.refs_weak.append(weakref.ref(w_proxy))
-        if can_reuse:
-            self.cached_proxy_index = index
+        self.cached_proxy_index = index
         return w_proxy
 
     def get_any_weakref(self, space):
@@ -90,6 +75,45 @@
                 return w_ref
         return space.w_None
 
+
+class WeakrefLifelineWithCallbacks(WeakrefLifeline):
+
+    def __init__(self, space, oldlifeline=None):
+        self.space = space
+        if oldlifeline is None:
+            self.refs_weak = []
+        else:
+            self.refs_weak = oldlifeline.refs_weak
+
+    def __del__(self):
+        """This runs when the interp-level object goes away, and allows
+        its lifeline to go away.  The purpose of this is to activate the
+        callbacks even if there is no __del__ method on the interp-level
+        W_Root subclass implementing the object.
+        """
+        for i in range(len(self.refs_weak) - 1, -1, -1):
+            w_ref = self.refs_weak[i]()
+            if w_ref is not None and w_ref.w_callable is not None:
+                w_ref.enqueue_for_destruction(self.space,
+                                              W_WeakrefBase.activate_callback,
+                                              'weakref callback of ')
+
+    def make_weakref_with_callback(self, w_subtype, w_obj, w_callable):
+        space = self.space
+        w_ref = space.allocate_instance(W_Weakref, w_subtype)
+        W_Weakref.__init__(w_ref, space, w_obj, w_callable)
+        self.refs_weak.append(weakref.ref(w_ref))
+        return w_ref
+
+    def make_proxy_with_callback(self, w_obj, w_callable):
+        space = self.space
+        if space.is_true(space.callable(w_obj)):
+            w_proxy = W_CallableProxy(space, w_obj, w_callable)
+        else:
+            w_proxy = W_Proxy(space, w_obj, w_callable)
+        self.refs_weak.append(weakref.ref(w_proxy))
+        return w_proxy
+
 # ____________________________________________________________
 
 class Dummy:
@@ -103,8 +127,7 @@
 
 class W_WeakrefBase(Wrappable):
     def __init__(w_self, space, w_obj, w_callable):
-        if space.is_w(w_callable, space.w_None):
-            w_callable = None
+        assert w_callable is not space.w_None    # should be really None
         w_self.space = space
         assert w_obj is not None
         w_self.w_obj_weak = weakref.ref(w_obj)
@@ -177,16 +200,39 @@
     def descr__ne__(self, space, w_ref2):
         return space.not_(space.eq(self, w_ref2))
 
+def getlifeline(space, w_obj):
+    lifeline = w_obj.getweakref()
+    if lifeline is None:
+        lifeline = WeakrefLifeline(space)
+        w_obj.setweakref(space, lifeline)
+    return lifeline
+
+def getlifelinewithcallbacks(space, w_obj):
+    lifeline = w_obj.getweakref()
+    if not isinstance(lifeline, WeakrefLifelineWithCallbacks):  # or None
+        oldlifeline = lifeline
+        lifeline = WeakrefLifelineWithCallbacks(space, oldlifeline)
+        w_obj.setweakref(space, lifeline)
+    return lifeline
+
+ at jit.dont_look_inside
+def get_or_make_weakref(space, w_subtype, w_obj):
+    return getlifeline(space, w_obj).get_or_make_weakref(w_subtype, w_obj)
+
+ at jit.dont_look_inside
+def make_weakref_with_callback(space, w_subtype, w_obj, w_callable):
+    lifeline = getlifelinewithcallbacks(space, w_obj)
+    return lifeline.make_weakref_with_callback(w_subtype, w_obj, w_callable)
+
 def descr__new__weakref(space, w_subtype, w_obj, w_callable=None,
                         __args__=None):
     if __args__.arguments_w:
         raise OperationError(space.w_TypeError, space.wrap(
             "__new__ expected at most 2 arguments"))
-    lifeline = w_obj.getweakref()
-    if lifeline is None:
-        lifeline = WeakrefLifeline(space)
-        w_obj.setweakref(space, lifeline)
-    return lifeline.get_or_make_weakref(space, w_subtype, w_obj, w_callable)
+    if space.is_w(w_callable, space.w_None):
+        return get_or_make_weakref(space, w_subtype, w_obj)
+    else:
+        return make_weakref_with_callback(space, w_subtype, w_obj, w_callable)
 
 W_Weakref.typedef = TypeDef("weakref",
     __doc__ = """A weak reference to an object 'obj'.  A 'callback' can be given,
@@ -239,15 +285,23 @@
         w_obj = force(space, self)
         return space.call_args(w_obj, __args__)
 
+ at jit.dont_look_inside
+def get_or_make_proxy(space, w_obj):
+    return getlifeline(space, w_obj).get_or_make_proxy(w_obj)
+
+ at jit.dont_look_inside
+def make_proxy_with_callback(space, w_obj, w_callable):
+    lifeline = getlifelinewithcallbacks(space, w_obj)
+    return lifeline.make_proxy_with_callback(w_obj, w_callable)
+
 def proxy(space, w_obj, w_callable=None):
     """Create a proxy object that weakly references 'obj'.
 'callback', if given, is called with the proxy as an argument when 'obj'
 is about to be finalized."""
-    lifeline = w_obj.getweakref()
-    if lifeline is None:
-        lifeline = WeakrefLifeline(space)
-        w_obj.setweakref(space, lifeline)
-    return lifeline.get_or_make_proxy(space, w_obj, w_callable)
+    if space.is_w(w_callable, space.w_None):
+        return get_or_make_proxy(space, w_obj)
+    else:
+        return make_proxy_with_callback(space, w_obj, w_callable)
 
 def descr__new__proxy(space, w_subtype, w_obj, w_callable=None):
     raise OperationError(
diff --git a/pypy/module/_weakref/test/test_weakref.py b/pypy/module/_weakref/test/test_weakref.py
--- a/pypy/module/_weakref/test/test_weakref.py
+++ b/pypy/module/_weakref/test/test_weakref.py
@@ -369,6 +369,26 @@
             return A
         raises(TypeError, tryit)
 
+    def test_proxy_to_dead_object(self):
+        import _weakref, gc
+        class A(object):
+            pass
+        p = _weakref.proxy(A())
+        gc.collect()
+        raises(ReferenceError, "p + 1")
+
+    def test_proxy_with_callback(self):
+        import _weakref, gc
+        class A(object):
+            pass
+        a2 = A()
+        def callback(proxy):
+            a2.seen = proxy
+        p = _weakref.proxy(A(), callback)
+        gc.collect()
+        raises(ReferenceError, "p + 1")
+        assert a2.seen is p
+
     def test_repr(self):
         import _weakref, gc
         for kind in ('ref', 'proxy'):
diff --git a/pypy/module/bz2/interp_bz2.py b/pypy/module/bz2/interp_bz2.py
--- a/pypy/module/bz2/interp_bz2.py
+++ b/pypy/module/bz2/interp_bz2.py
@@ -446,7 +446,9 @@
             result = self.buffer[pos:pos + n]
             self.pos += n
         else:
-            result = self.buffer
+            pos = self.pos
+            assert pos >= 0
+            result = self.buffer[pos:]
             self.pos = 0
             self.buffer = ""
         self.readlength += len(result)
diff --git a/pypy/module/bz2/test/test_bz2_file.py b/pypy/module/bz2/test/test_bz2_file.py
--- a/pypy/module/bz2/test/test_bz2_file.py
+++ b/pypy/module/bz2/test/test_bz2_file.py
@@ -274,14 +274,14 @@
             pass
         del bz2f   # delete from this frame, which is captured in the traceback
 
-    def test_read_chunk10(self):
+    def test_read_chunk9(self):
         from bz2 import BZ2File
         self.create_temp_file()
         
         bz2f = BZ2File(self.temppath)
         text_read = ""
         while True:
-            data = bz2f.read(10)
+            data = bz2f.read(9) # 9 doesn't divide evenly into data length
             if not data:
                 break
             text_read = "%s%s" % (text_read, data)
diff --git a/pypy/module/cpyext/frameobject.py b/pypy/module/cpyext/frameobject.py
--- a/pypy/module/cpyext/frameobject.py
+++ b/pypy/module/cpyext/frameobject.py
@@ -57,7 +57,7 @@
     code = space.interp_w(PyCode, w_code)
     w_globals = from_ref(space, py_frame.c_f_globals)
 
-    frame = space.FrameClass(space, code, w_globals, closure=None)
+    frame = space.FrameClass(space, code, w_globals, outer_func=None)
     frame.f_lineno = py_frame.c_f_lineno
     w_obj = space.wrap(frame)
     track_reference(space, py_obj, w_obj)
diff --git a/pypy/module/marshal/interp_marshal.py b/pypy/module/marshal/interp_marshal.py
--- a/pypy/module/marshal/interp_marshal.py
+++ b/pypy/module/marshal/interp_marshal.py
@@ -40,7 +40,7 @@
         reader = FileReader(space, w_f)
     try:
         u = Unmarshaller(space, reader)
-        return u.load_w_obj(False)
+        return u.load_w_obj()
     finally:
         reader.finished()
 
@@ -49,7 +49,7 @@
 ignored."""
     space.timer.start("marshal loads")
     u = StringUnmarshaller(space, w_str)
-    obj = u.load_w_obj(False)
+    obj = u.load_w_obj()
     space.timer.stop("marshal loads")
     return obj
 
@@ -424,7 +424,7 @@
         lng = self.get_lng()
         return self.get(lng)
 
-    def get_w_obj(self, allow_null):
+    def get_w_obj(self, allow_null=False):
         space = self.space
         w_ret = space.w_None # something not None
         tc = self.get1()
@@ -434,9 +434,9 @@
                 'NULL object in marshal data'))
         return w_ret
 
-    def load_w_obj(self, allow_null):
+    def load_w_obj(self):
         try:
-            return self.get_w_obj(allow_null)
+            return self.get_w_obj()
         except rstackovf.StackOverflow:
             rstackovf.check_stack_overflow()
             self._overflow()
diff --git a/pypy/module/micronumpy/__init__.py b/pypy/module/micronumpy/__init__.py
--- a/pypy/module/micronumpy/__init__.py
+++ b/pypy/module/micronumpy/__init__.py
@@ -1,42 +1,51 @@
-
 from pypy.interpreter.mixedmodule import MixedModule
 
+
 class Module(MixedModule):
-
     applevel_name = 'numpy'
 
     interpleveldefs = {
         'array': 'interp_numarray.SingleDimArray',
         'dtype': 'interp_dtype.W_Dtype',
+        'ufunc': 'interp_ufuncs.W_Ufunc',
 
         'zeros': 'interp_numarray.zeros',
         'empty': 'interp_numarray.zeros',
         'ones': 'interp_numarray.ones',
         'fromstring': 'interp_support.fromstring',
+    }
 
-        # ufuncs
-        'abs': 'interp_ufuncs.absolute',
-        'absolute': 'interp_ufuncs.absolute',
-        'add': 'interp_ufuncs.add',
-        'copysign': 'interp_ufuncs.copysign',
-        'divide': 'interp_ufuncs.divide',
-        'exp': 'interp_ufuncs.exp',
-        'fabs': 'interp_ufuncs.fabs',
-        'floor': 'interp_ufuncs.floor',
-        'maximum': 'interp_ufuncs.maximum',
-        'minimum': 'interp_ufuncs.minimum',
-        'multiply': 'interp_ufuncs.multiply',
-        'negative': 'interp_ufuncs.negative',
-        'reciprocal': 'interp_ufuncs.reciprocal',
-        'sign': 'interp_ufuncs.sign',
-        'subtract': 'interp_ufuncs.subtract',
-        'sin': 'interp_ufuncs.sin',
-        'cos': 'interp_ufuncs.cos',
-        'tan': 'interp_ufuncs.tan',
-        'arcsin': 'interp_ufuncs.arcsin',
-        'arccos': 'interp_ufuncs.arccos',
-        'arctan': 'interp_ufuncs.arctan',
-    }
+    # ufuncs
+    for exposed, impl in [
+        ("abs", "absolute"),
+        ("absolute", "absolute"),
+        ("add", "add"),
+        ("arccos", "arccos"),
+        ("arcsin", "arcsin"),
+        ("arctan", "arctan"),
+        ("copysign", "copysign"),
+        ("cos", "cos"),
+        ("divide", "divide"),
+        ("equal", "equal"),
+        ("exp", "exp"),
+        ("fabs", "fabs"),
+        ("floor", "floor"),
+        ("greater", "greater"),
+        ("greater_equal", "greater_equal"),
+        ("less", "less"),
+        ("less_equal", "less_equal"),
+        ("maximum", "maximum"),
+        ("minimum", "minimum"),
+        ("multiply", "multiply"),
+        ("negative", "negative"),
+        ("not_equal", "not_equal"),
+        ("reciprocal", "reciprocal"),
+        ("sign", "sign"),
+        ("sin", "sin"),
+        ("subtract", "subtract"),
+        ("tan", "tan"),
+    ]:
+        interpleveldefs[exposed] = "interp_ufuncs.get(space).%s" % impl
 
     appleveldefs = {
         'average': 'app_numpy.average',
diff --git a/pypy/module/micronumpy/compile.py b/pypy/module/micronumpy/compile.py
--- a/pypy/module/micronumpy/compile.py
+++ b/pypy/module/micronumpy/compile.py
@@ -20,6 +20,7 @@
 
 class FakeSpace(object):
     w_ValueError = None
+    w_TypeError = None
 
     def __init__(self):
         """NOT_RPYTHON"""
diff --git a/pypy/module/micronumpy/interp_dtype.py b/pypy/module/micronumpy/interp_dtype.py
--- a/pypy/module/micronumpy/interp_dtype.py
+++ b/pypy/module/micronumpy/interp_dtype.py
@@ -53,7 +53,9 @@
 
 VOID_TP = lltype.Ptr(lltype.Array(lltype.Void, hints={'nolength': True, "uncast_on_llgraph": True}))
 
-def create_low_level_dtype(num, kind, name, aliases, applevel_types, T, valtype):
+def create_low_level_dtype(num, kind, name, aliases, applevel_types, T, valtype,
+    expected_size=None):
+
     class Box(BaseBox):
         def __init__(self, val):
             self.val = val
@@ -113,6 +115,8 @@
     W_LowLevelDtype.aliases = aliases
     W_LowLevelDtype.applevel_types = applevel_types
     W_LowLevelDtype.num_bytes = rffi.sizeof(T)
+    if expected_size is not None:
+        assert W_LowLevelDtype.num_bytes == expected_size
     return W_LowLevelDtype
 
 
@@ -125,6 +129,16 @@
         ))
     return impl
 
+def raw_binop(func):
+    # Returns the result unwrapped.
+    @functools.wraps(func)
+    def impl(self, v1, v2):
+        return func(self,
+            self.for_computation(self.unbox(v1)),
+            self.for_computation(self.unbox(v2))
+        )
+    return impl
+
 def unaryop(func):
     @functools.wraps(func)
     def impl(self, v):
@@ -166,8 +180,24 @@
 
     def bool(self, v):
         return bool(self.for_computation(self.unbox(v)))
+    @raw_binop
+    def eq(self, v1, v2):
+        return v1 == v2
+    @raw_binop
     def ne(self, v1, v2):
-        return self.for_computation(self.unbox(v1)) != self.for_computation(self.unbox(v2))
+        return v1 != v2
+    @raw_binop
+    def lt(self, v1, v2):
+        return v1 < v2
+    @raw_binop
+    def le(self, v1, v2):
+        return v1 <= v2
+    @raw_binop
+    def gt(self, v1, v2):
+        return v1 > v2
+    @raw_binop
+    def ge(self, v1, v2):
+        return v1 >= v2
 
 
 class FloatArithmeticDtype(ArithmaticTypeMixin):
@@ -220,7 +250,7 @@
         return math.tan(v)
     @unaryop
     def arcsin(self, v):
-        if v < -1.0 or  v > 1.0:
+        if v < -1.0 or v > 1.0:
             return rfloat.NAN
         return math.asin(v)
     @unaryop
@@ -282,10 +312,21 @@
     applevel_types = [],
     T = rffi.SIGNEDCHAR,
     valtype = rffi.SIGNEDCHAR._type,
+    expected_size = 1,
 )
 class W_Int8Dtype(IntegerArithmeticDtype, W_Int8Dtype):
-    def unwrap(self, space, w_item):
-        return self.adapt_val(space.int_w(space.int(w_item)))
+    pass
+
+W_Int16Dtype = create_low_level_dtype(
+    num = 3, kind = SIGNEDLTR, name = "int16",
+    aliases = ["int16"],
+    applevel_types = [],
+    T = rffi.SHORT,
+    valtype = rffi.SHORT._type,
+    expected_size = 2,
+)
+class W_Int16Dtype(IntegerArithmeticDtype, W_Int16Dtype):
+    pass
 
 W_Int32Dtype = create_low_level_dtype(
     num = 5, kind = SIGNEDLTR, name = "int32",
@@ -293,6 +334,7 @@
     applevel_types = [],
     T = rffi.INT,
     valtype = rffi.INT._type,
+    expected_size = 4,
 )
 class W_Int32Dtype(IntegerArithmeticDtype, W_Int32Dtype):
     pass
@@ -303,6 +345,7 @@
     applevel_types = ["long"],
     T = rffi.LONGLONG,
     valtype = rffi.LONGLONG._type,
+    expected_size = 8,
 )
 class W_Int64Dtype(IntegerArithmeticDtype, W_Int64Dtype):
     pass
@@ -313,6 +356,7 @@
     applevel_types = ["float"],
     T = lltype.Float,
     valtype = float,
+    expected_size = 8,
 )
 class W_Float64Dtype(FloatArithmeticDtype, W_Float64Dtype):
     def unwrap(self, space, w_item):
@@ -323,7 +367,7 @@
 
 ALL_DTYPES = [
     W_BoolDtype,
-    W_Int8Dtype, W_Int32Dtype, W_Int64Dtype,
+    W_Int8Dtype, W_Int16Dtype, W_Int32Dtype, W_Int64Dtype,
     W_Float64Dtype
 ]
 
@@ -353,4 +397,4 @@
     kind = interp_attrproperty("kind", cls=W_Dtype),
     shape = GetSetProperty(W_Dtype.descr_get_shape),
 )
-W_Dtype.typedef.acceptable_as_base_class = False
\ No newline at end of file
+W_Dtype.typedef.acceptable_as_base_class = False
diff --git a/pypy/module/micronumpy/interp_numarray.py b/pypy/module/micronumpy/interp_numarray.py
--- a/pypy/module/micronumpy/interp_numarray.py
+++ b/pypy/module/micronumpy/interp_numarray.py
@@ -53,90 +53,59 @@
             i += 1
         return arr
 
-    def _unaryop_impl(w_ufunc):
+    def _unaryop_impl(ufunc_name):
         def impl(self, space):
-            return w_ufunc(space, self)
-        return func_with_new_name(impl, "unaryop_%s_impl" % w_ufunc.__name__)
+            return getattr(interp_ufuncs.get(space), ufunc_name).call(space, [self])
+        return func_with_new_name(impl, "unaryop_%s_impl" % ufunc_name)
 
-    descr_pos = _unaryop_impl(interp_ufuncs.positive)
-    descr_neg = _unaryop_impl(interp_ufuncs.negative)
-    descr_abs = _unaryop_impl(interp_ufuncs.absolute)
+    descr_pos = _unaryop_impl("positive")
+    descr_neg = _unaryop_impl("negative")
+    descr_abs = _unaryop_impl("absolute")
 
-    def _binop_impl(w_ufunc):
+    def _binop_impl(ufunc_name):
         def impl(self, space, w_other):
-            return w_ufunc(space, self, w_other)
-        return func_with_new_name(impl, "binop_%s_impl" % w_ufunc.__name__)
+            return getattr(interp_ufuncs.get(space), ufunc_name).call(space, [self, w_other])
+        return func_with_new_name(impl, "binop_%s_impl" % ufunc_name)
 
-    descr_add = _binop_impl(interp_ufuncs.add)
-    descr_sub = _binop_impl(interp_ufuncs.subtract)
-    descr_mul = _binop_impl(interp_ufuncs.multiply)
-    descr_div = _binop_impl(interp_ufuncs.divide)
-    descr_pow = _binop_impl(interp_ufuncs.power)
-    descr_mod = _binop_impl(interp_ufuncs.mod)
+    descr_add = _binop_impl("add")
+    descr_sub = _binop_impl("subtract")
+    descr_mul = _binop_impl("multiply")
+    descr_div = _binop_impl("divide")
+    descr_pow = _binop_impl("power")
+    descr_mod = _binop_impl("mod")
 
-    def _binop_right_impl(w_ufunc):
+    descr_eq = _binop_impl("equal")
+    descr_ne = _binop_impl("not_equal")
+    descr_lt = _binop_impl("less")
+    descr_le = _binop_impl("less_equal")
+    descr_gt = _binop_impl("greater")
+    descr_ge = _binop_impl("greater_equal")
+
+    def _binop_right_impl(ufunc_name):
         def impl(self, space, w_other):
             w_other = scalar_w(space,
                 interp_ufuncs.find_dtype_for_scalar(space, w_other, self.find_dtype()),
                 w_other
             )
-            return w_ufunc(space, w_other, self)
-        return func_with_new_name(impl, "binop_right_%s_impl" % w_ufunc.__name__)
+            return getattr(interp_ufuncs.get(space), ufunc_name).call(space, [w_other, self])
+        return func_with_new_name(impl, "binop_right_%s_impl" % ufunc_name)
 
-    descr_radd = _binop_right_impl(interp_ufuncs.add)
-    descr_rsub = _binop_right_impl(interp_ufuncs.subtract)
-    descr_rmul = _binop_right_impl(interp_ufuncs.multiply)
-    descr_rdiv = _binop_right_impl(interp_ufuncs.divide)
-    descr_rpow = _binop_right_impl(interp_ufuncs.power)
-    descr_rmod = _binop_right_impl(interp_ufuncs.mod)
+    descr_radd = _binop_right_impl("add")
+    descr_rsub = _binop_right_impl("subtract")
+    descr_rmul = _binop_right_impl("multiply")
+    descr_rdiv = _binop_right_impl("divide")
+    descr_rpow = _binop_right_impl("power")
+    descr_rmod = _binop_right_impl("mod")
 
-    def _reduce_sum_prod_impl(op_name, init):
-        reduce_driver = jit.JitDriver(greens=['signature'],
-                         reds = ['i', 'size', 'self', 'result', 'res_dtype'])
+    def _reduce_ufunc_impl(ufunc_name):
+        def impl(self, space):
+            return getattr(interp_ufuncs.get(space), ufunc_name).descr_reduce(space, self)
+        return func_with_new_name(impl, "reduce_%s_impl" % ufunc_name)
 
-        def loop(self, res_dtype, result, size):
-            i = 0
-            while i < size:
-                reduce_driver.jit_merge_point(signature=self.signature,
-                                              self=self, res_dtype=res_dtype,
-                                              size=size, i=i, result=result)
-                result = getattr(res_dtype, op_name)(
-                    result,
-                    self.eval(i).convert_to(res_dtype)
-                )
-                i += 1
-            return result
-
-        def impl(self, space):
-            dtype = interp_ufuncs.find_unaryop_result_dtype(
-                space, self.find_dtype(), promote_to_largest=True
-            )
-            result = dtype.adapt_val(init)
-            return loop(self, dtype, result, self.find_size()).wrap(space)
-        return func_with_new_name(impl, "reduce_%s_impl" % op_name)
-
-    def _reduce_max_min_impl(op_name):
-        reduce_driver = jit.JitDriver(greens=['signature'],
-                         reds = ['i', 'size', 'self', 'result', 'dtype'])
-        def loop(self, result, size):
-            i = 1
-            dtype = self.find_dtype()
-            while i < size:
-                reduce_driver.jit_merge_point(signature=self.signature,
-                                              self=self, dtype=dtype,
-                                              size=size, i=i, result=result)
-                result = getattr(dtype, op_name)(result, self.eval(i))
-                i += 1
-            return result
-
-        def impl(self, space):
-            size = self.find_size()
-            if size == 0:
-                raise OperationError(space.w_ValueError,
-                    space.wrap("Can't call %s on zero-size arrays" \
-                            % op_name))
-            return loop(self, self.eval(0), size).wrap(space)
-        return func_with_new_name(impl, "reduce_%s_impl" % op_name)
+    descr_sum = _reduce_ufunc_impl("add")
+    descr_prod = _reduce_ufunc_impl("multiply")
+    descr_max = _reduce_ufunc_impl("maximum")
+    descr_min = _reduce_ufunc_impl("minimum")
 
     def _reduce_argmax_argmin_impl(op_name):
         reduce_driver = jit.JitDriver(greens=['signature'],
@@ -192,10 +161,6 @@
     def descr_any(self, space):
         return space.wrap(self._any())
 
-    descr_sum = _reduce_sum_prod_impl("add", 0)
-    descr_prod = _reduce_sum_prod_impl("mul", 1)
-    descr_max = _reduce_max_min_impl("max")
-    descr_min = _reduce_max_min_impl("min")
     descr_argmax = _reduce_argmax_argmin_impl("max")
     descr_argmin = _reduce_argmax_argmin_impl("min")
 
@@ -248,7 +213,7 @@
         res = "array([" + ", ".join(concrete._getnums(False)) + "]"
         dtype = concrete.find_dtype()
         if (dtype is not space.fromcache(interp_dtype.W_Float64Dtype) and
-            dtype is not space.fromcache(interp_dtype.W_Int64Dtype)):
+            dtype is not space.fromcache(interp_dtype.W_Int64Dtype)) or not self.find_size():
             res += ", dtype=" + dtype.name
         res += ")"
         return space.wrap(res)
@@ -259,7 +224,15 @@
         return space.wrap("[" + " ".join(concrete._getnums(True)) + "]")
 
     def descr_getitem(self, space, w_idx):
-        # TODO: indexing by tuples
+        # TODO: indexing by arrays and lists
+        if space.isinstance_w(w_idx, space.w_tuple):
+            length = space.len_w(w_idx)
+            if length == 0:
+                return space.wrap(self)
+            if length > 1: # only one dimension for now.
+                raise OperationError(space.w_IndexError,
+                                     space.wrap("invalid index"))
+            w_idx = space.getitem(w_idx, space.wrap(0))
         start, stop, step, slice_length = space.decode_index4(w_idx, self.find_size())
         if step == 0:
             # Single index
@@ -273,8 +246,19 @@
             return space.wrap(res)
 
     def descr_setitem(self, space, w_idx, w_value):
-        # TODO: indexing by tuples and lists
+        # TODO: indexing by arrays and lists
         self.invalidated()
+        if space.isinstance_w(w_idx, space.w_tuple):
+            length = space.len_w(w_idx)
+            if length > 1: # only one dimension for now.
+                raise OperationError(space.w_IndexError,
+                                     space.wrap("invalid index"))
+            if length == 0:
+                w_idx = space.newslice(space.wrap(0),
+                                      space.wrap(self.find_size()),
+                                      space.wrap(1))
+            else:
+                w_idx = space.getitem(w_idx, space.wrap(0))
         start, stop, step, slice_length = space.decode_index4(w_idx,
                                                               self.find_size())
         if step == 0:
@@ -427,10 +411,11 @@
     """
     Intermediate class for performing binary operations.
     """
-    def __init__(self, signature, res_dtype, left, right):
+    def __init__(self, signature, calc_dtype, res_dtype, left, right):
         VirtualArray.__init__(self, signature, res_dtype)
         self.left = left
         self.right = right
+        self.calc_dtype = calc_dtype
 
     def _del_sources(self):
         self.left = None
@@ -444,14 +429,14 @@
         return self.right.find_size()
 
     def _eval(self, i):
-        lhs = self.left.eval(i).convert_to(self.res_dtype)
-        rhs = self.right.eval(i).convert_to(self.res_dtype)
+        lhs = self.left.eval(i).convert_to(self.calc_dtype)
+        rhs = self.right.eval(i).convert_to(self.calc_dtype)
 
         sig = jit.promote(self.signature)
         assert isinstance(sig, signature.Signature)
         call_sig = sig.components[0]
         assert isinstance(call_sig, signature.Call2)
-        return call_sig.func(self.res_dtype, lhs, rhs)
+        return call_sig.func(self.calc_dtype, lhs, rhs)
 
 class ViewArray(BaseArray):
     """
@@ -596,18 +581,28 @@
     __pos__ = interp2app(BaseArray.descr_pos),
     __neg__ = interp2app(BaseArray.descr_neg),
     __abs__ = interp2app(BaseArray.descr_abs),
+
     __add__ = interp2app(BaseArray.descr_add),
     __sub__ = interp2app(BaseArray.descr_sub),
     __mul__ = interp2app(BaseArray.descr_mul),
     __div__ = interp2app(BaseArray.descr_div),
     __pow__ = interp2app(BaseArray.descr_pow),
     __mod__ = interp2app(BaseArray.descr_mod),
+
     __radd__ = interp2app(BaseArray.descr_radd),
     __rsub__ = interp2app(BaseArray.descr_rsub),
     __rmul__ = interp2app(BaseArray.descr_rmul),
     __rdiv__ = interp2app(BaseArray.descr_rdiv),
     __rpow__ = interp2app(BaseArray.descr_rpow),
     __rmod__ = interp2app(BaseArray.descr_rmod),
+
+    __eq__ = interp2app(BaseArray.descr_eq),
+    __ne__ = interp2app(BaseArray.descr_ne),
+    __lt__ = interp2app(BaseArray.descr_lt),
+    __le__ = interp2app(BaseArray.descr_le),
+    __gt__ = interp2app(BaseArray.descr_gt),
+    __ge__ = interp2app(BaseArray.descr_ge),
+
     __repr__ = interp2app(BaseArray.descr_repr),
     __str__ = interp2app(BaseArray.descr_str),
 
diff --git a/pypy/module/micronumpy/interp_ufuncs.py b/pypy/module/micronumpy/interp_ufuncs.py
--- a/pypy/module/micronumpy/interp_ufuncs.py
+++ b/pypy/module/micronumpy/interp_ufuncs.py
@@ -1,57 +1,168 @@
+from pypy.interpreter.baseobjspace import Wrappable
+from pypy.interpreter.error import OperationError, operationerrfmt
+from pypy.interpreter.gateway import interp2app
+from pypy.interpreter.typedef import TypeDef, GetSetProperty, interp_attrproperty
 from pypy.module.micronumpy import interp_dtype, signature
+from pypy.rlib import jit
 from pypy.tool.sourcetools import func_with_new_name
 
 
-def ufunc(func=None, promote_to_float=False, promote_bools=False):
-    if func is None:
-        return lambda func: ufunc(func, promote_to_float, promote_bools)
-    call_sig = signature.Call1(func)
-    def impl(space, w_obj):
+reduce_driver = jit.JitDriver(
+    greens = ["signature"],
+    reds = ["i", "size", "self", "dtype", "value", "obj"]
+)
+
+class W_Ufunc(Wrappable):
+    _attrs_ = ["name", "promote_to_float", "promote_bools", "identity"]
+
+    def __init__(self, name, promote_to_float, promote_bools, identity):
+        self.name = name
+        self.promote_to_float = promote_to_float
+        self.promote_bools = promote_bools
+
+        self.identity = identity
+
+    def descr_repr(self, space):
+        return space.wrap("<ufunc '%s'>" % self.name)
+
+    def descr_get_identity(self, space):
+        if self.identity is None:
+            return space.w_None
+        return self.identity.wrap(space)
+
+    def descr_call(self, space, __args__):
+        try:
+            args_w = __args__.fixedunpack(self.argcount)
+        except ValueError, e:
+            raise OperationError(space.w_TypeError, space.wrap(str(e)))
+        return self.call(space, args_w)
+
+    def descr_reduce(self, space, w_obj):
+        from pypy.module.micronumpy.interp_numarray import convert_to_array, Scalar
+
+        if self.argcount != 2:
+            raise OperationError(space.w_ValueError, space.wrap("reduce only "
+                "supported for binary functions"))
+
+        assert isinstance(self, W_Ufunc2)
+        obj = convert_to_array(space, w_obj)
+        if isinstance(obj, Scalar):
+            raise OperationError(space.w_TypeError, space.wrap("cannot reduce "
+                "on a scalar"))
+
+        size = obj.find_size()
+        dtype = find_unaryop_result_dtype(
+            space, obj.find_dtype(),
+            promote_to_largest=True
+        )
+        start = 0
+        if self.identity is None:
+            if size == 0:
+                raise operationerrfmt(space.w_ValueError, "zero-size array to "
+                    "%s.reduce without identity", self.name)
+            value = obj.eval(0).convert_to(dtype)
+            start += 1
+        else:
+            value = self.identity.convert_to(dtype)
+        new_sig = signature.Signature.find_sig([
+            self.reduce_signature, obj.signature
+        ])
+        return self.reduce(new_sig, start, value, obj, dtype, size).wrap(space)
+
+    def reduce(self, signature, start, value, obj, dtype, size):
+        i = start
+        while i < size:
+            reduce_driver.jit_merge_point(signature=signature, self=self,
+                                          value=value, obj=obj, i=i,
+                                          dtype=dtype, size=size)
+            value = self.func(dtype, value, obj.eval(i).convert_to(dtype))
+            i += 1
+        return value
+
+class W_Ufunc1(W_Ufunc):
+    argcount = 1
+
+    def __init__(self, func, name, promote_to_float=False, promote_bools=False,
+        identity=None):
+
+        W_Ufunc.__init__(self, name, promote_to_float, promote_bools, identity)
+        self.func = func
+        self.signature = signature.Call1(func)
+
+    def call(self, space, args_w):
         from pypy.module.micronumpy.interp_numarray import (Call1,
             convert_to_array, Scalar)
 
+        [w_obj] = args_w
         w_obj = convert_to_array(space, w_obj)
         res_dtype = find_unaryop_result_dtype(space,
             w_obj.find_dtype(),
-            promote_to_float=promote_to_float,
-            promote_bools=promote_bools,
+            promote_to_float=self.promote_to_float,
+            promote_bools=self.promote_bools,
         )
         if isinstance(w_obj, Scalar):
-            return func(res_dtype, w_obj.value.convert_to(res_dtype)).wrap(space)
+            return self.func(res_dtype, w_obj.value.convert_to(res_dtype)).wrap(space)
 
-        new_sig = signature.Signature.find_sig([call_sig, w_obj.signature])
+        new_sig = signature.Signature.find_sig([self.signature, w_obj.signature])
         w_res = Call1(new_sig, res_dtype, w_obj)
         w_obj.add_invalidates(w_res)
         return w_res
-    return func_with_new_name(impl, "%s_dispatcher" % func.__name__)
 
-def ufunc2(func=None, promote_to_float=False, promote_bools=False):
-    if func is None:
-        return lambda func: ufunc2(func, promote_to_float, promote_bools)
 
-    call_sig = signature.Call2(func)
-    def impl(space, w_lhs, w_rhs):
+class W_Ufunc2(W_Ufunc):
+    argcount = 2
+
+    def __init__(self, func, name, promote_to_float=False, promote_bools=False,
+        identity=None, comparison_func=False):
+
+        W_Ufunc.__init__(self, name, promote_to_float, promote_bools, identity)
+        self.func = func
+        self.comparison_func = comparison_func
+        self.signature = signature.Call2(func)
+        self.reduce_signature = signature.BaseSignature()
+
+    def call(self, space, args_w):
         from pypy.module.micronumpy.interp_numarray import (Call2,
             convert_to_array, Scalar)
 
+        [w_lhs, w_rhs] = args_w
         w_lhs = convert_to_array(space, w_lhs)
         w_rhs = convert_to_array(space, w_rhs)
-        res_dtype = find_binop_result_dtype(space,
+        calc_dtype = find_binop_result_dtype(space,
             w_lhs.find_dtype(), w_rhs.find_dtype(),
-            promote_to_float=promote_to_float,
-            promote_bools=promote_bools,
+            promote_to_float=self.promote_to_float,
+            promote_bools=self.promote_bools,
         )
+        if self.comparison_func:
+            res_dtype = space.fromcache(interp_dtype.W_BoolDtype)
+        else:
+            res_dtype = calc_dtype
         if isinstance(w_lhs, Scalar) and isinstance(w_rhs, Scalar):
-            return func(res_dtype, w_lhs.value, w_rhs.value).wrap(space)
+            return self.func(calc_dtype,
+                w_lhs.value.convert_to(calc_dtype),
+                w_rhs.value.convert_to(calc_dtype)
+            ).wrap(space)
 
         new_sig = signature.Signature.find_sig([
-            call_sig, w_lhs.signature, w_rhs.signature
+            self.signature, w_lhs.signature, w_rhs.signature
         ])
-        w_res = Call2(new_sig, res_dtype, w_lhs, w_rhs)
+        w_res = Call2(new_sig, calc_dtype, res_dtype, w_lhs, w_rhs)
         w_lhs.add_invalidates(w_res)
         w_rhs.add_invalidates(w_res)
         return w_res
-    return func_with_new_name(impl, "%s_dispatcher" % func.__name__)
+
+
+W_Ufunc.typedef = TypeDef("ufunc",
+    __module__ = "numpy",
+
+    __call__ = interp2app(W_Ufunc.descr_call),
+    __repr__ = interp2app(W_Ufunc.descr_repr),
+
+    identity = GetSetProperty(W_Ufunc.descr_get_identity),
+    nin = interp_attrproperty("argcount", cls=W_Ufunc),
+
+    reduce = interp2app(W_Ufunc.descr_reduce),
+)
 
 def find_binop_result_dtype(space, dt1, dt2, promote_to_float=False,
     promote_bools=False):
@@ -74,7 +185,7 @@
     assert False
 
 def find_unaryop_result_dtype(space, dt, promote_to_float=False,
-    promote_to_largest=False, promote_bools=False):
+    promote_bools=False, promote_to_largest=False):
     if promote_bools and (dt.kind == interp_dtype.BOOLLTR):
         return space.fromcache(interp_dtype.W_Int8Dtype)
     if promote_to_float:
@@ -106,53 +217,77 @@
     return space.fromcache(interp_dtype.W_Float64Dtype)
 
 
-def ufunc_dtype_caller(ufunc_name, op_name, argcount, **kwargs):
+def ufunc_dtype_caller(space, ufunc_name, op_name, argcount, comparison_func):
     if argcount == 1:
-        @ufunc(**kwargs)
         def impl(res_dtype, value):
             return getattr(res_dtype, op_name)(value)
     elif argcount == 2:
-        @ufunc2(**kwargs)
         def impl(res_dtype, lvalue, rvalue):
-            return getattr(res_dtype, op_name)(lvalue, rvalue)
+            res = getattr(res_dtype, op_name)(lvalue, rvalue)
+            if comparison_func:
+                res = space.fromcache(interp_dtype.W_BoolDtype).box(res)
+            return res
     return func_with_new_name(impl, ufunc_name)
 
-for ufunc_def in [
-    ("add", "add", 2),
-    ("subtract", "sub", 2),
-    ("multiply", "mul", 2),
-    ("divide", "div", 2, {"promote_bools": True}),
-    ("mod", "mod", 2, {"promote_bools": True}),
-    ("power", "pow", 2, {"promote_bools": True}),
+class UfuncState(object):
+    def __init__(self, space):
+        "NOT_RPYTHON"
+        for ufunc_def in [
+            ("add", "add", 2, {"identity": 0}),
+            ("subtract", "sub", 2),
+            ("multiply", "mul", 2, {"identity": 1}),
+            ("divide", "div", 2, {"promote_bools": True}),
+            ("mod", "mod", 2, {"promote_bools": True}),
+            ("power", "pow", 2, {"promote_bools": True}),
 
-    ("maximum", "max", 2),
-    ("minimum", "min", 2),
+            ("equal", "eq", 2, {"comparison_func": True}),
+            ("not_equal", "ne", 2, {"comparison_func": True}),
+            ("less", "lt", 2, {"comparison_func": True}),
+            ("less_equal", "le", 2, {"comparison_func": True}),
+            ("greater", "gt", 2, {"comparison_func": True}),
+            ("greater_equal", "ge", 2, {"comparison_func": True}),
 
-    ("copysign", "copysign", 2, {"promote_to_float": True}),
+            ("maximum", "max", 2),
+            ("minimum", "min", 2),
 
-    ("positive", "pos", 1),
-    ("negative", "neg", 1),
-    ("absolute", "abs", 1),
-    ("sign", "sign", 1, {"promote_bools": True}),
-    ("reciprocal", "reciprocal", 1),
+            ("copysign", "copysign", 2, {"promote_to_float": True}),
 
-    ("fabs", "fabs", 1, {"promote_to_float": True}),
-    ("floor", "floor", 1, {"promote_to_float": True}),
-    ("exp", "exp", 1, {"promote_to_float": True}),
+            ("positive", "pos", 1),
+            ("negative", "neg", 1),
+            ("absolute", "abs", 1),
+            ("sign", "sign", 1, {"promote_bools": True}),
+            ("reciprocal", "reciprocal", 1),
 
-    ("sin", "sin", 1, {"promote_to_float": True}),
-    ("cos", "cos", 1, {"promote_to_float": True}),
-    ("tan", "tan", 1, {"promote_to_float": True}),
-    ("arcsin", "arcsin", 1, {"promote_to_float": True}),
-    ("arccos", "arccos", 1, {"promote_to_float": True}),
-    ("arctan", "arctan", 1, {"promote_to_float": True}),
-]:
-    ufunc_name = ufunc_def[0]
-    op_name = ufunc_def[1]
-    argcount = ufunc_def[2]
-    try:
-        extra_kwargs = ufunc_def[3]
-    except IndexError:
-        extra_kwargs = {}
+            ("fabs", "fabs", 1, {"promote_to_float": True}),
+            ("floor", "floor", 1, {"promote_to_float": True}),
+            ("exp", "exp", 1, {"promote_to_float": True}),
 
-    globals()[ufunc_name] = ufunc_dtype_caller(ufunc_name, op_name, argcount, **extra_kwargs)
+            ("sin", "sin", 1, {"promote_to_float": True}),
+            ("cos", "cos", 1, {"promote_to_float": True}),
+            ("tan", "tan", 1, {"promote_to_float": True}),
+            ("arcsin", "arcsin", 1, {"promote_to_float": True}),
+            ("arccos", "arccos", 1, {"promote_to_float": True}),
+            ("arctan", "arctan", 1, {"promote_to_float": True}),
+        ]:
+            self.add_ufunc(space, *ufunc_def)
+
+    def add_ufunc(self, space, ufunc_name, op_name, argcount, extra_kwargs=None):
+        if extra_kwargs is None:
+            extra_kwargs = {}
+
+        identity = extra_kwargs.get("identity")
+        if identity is not None:
+            identity = space.fromcache(interp_dtype.W_Int64Dtype).adapt_val(identity)
+        extra_kwargs["identity"] = identity
+
+        func = ufunc_dtype_caller(space, ufunc_name, op_name, argcount,
+            comparison_func=extra_kwargs.get("comparison_func", False)
+        )
+        if argcount == 1:
+            ufunc = W_Ufunc1(func, ufunc_name, **extra_kwargs)
+        elif argcount == 2:
+            ufunc = W_Ufunc2(func, ufunc_name, **extra_kwargs)
+        setattr(self, ufunc_name, ufunc)
+
+def get(space):
+    return space.fromcache(UfuncState)
\ No newline at end of file
diff --git a/pypy/module/micronumpy/test/test_dtypes.py b/pypy/module/micronumpy/test/test_dtypes.py
--- a/pypy/module/micronumpy/test/test_dtypes.py
+++ b/pypy/module/micronumpy/test/test_dtypes.py
@@ -82,10 +82,20 @@
             assert a[1] == 1
 
     def test_add_int8(self):
-        from numpy import array
+        from numpy import array, dtype
 
         a = array(range(5), dtype="int8")
         b = a + a
+        assert b.dtype is dtype("int8")
+        for i in range(5):
+            assert b[i] == i * 2
+
+    def test_add_int16(self):
+        from numpy import array, dtype
+
+        a = array(range(5), dtype="int16")
+        b = a + a
+        assert b.dtype is dtype("int16")
         for i in range(5):
             assert b[i] == i * 2
 
@@ -98,4 +108,4 @@
         from numpy import dtype
 
         # You can't subclass dtype
-        raises(TypeError, type, "Foo", (dtype,), {})
\ No newline at end of file
+        raises(TypeError, type, "Foo", (dtype,), {})
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
@@ -52,10 +52,14 @@
         from numpy import array, zeros
         a = array(range(5), float)
         assert repr(a) == "array([0.0, 1.0, 2.0, 3.0, 4.0])"
+        a = array([], float)
+        assert repr(a) == "array([], dtype=float64)"
         a = zeros(1001)
         assert repr(a) == "array([0.0, 0.0, 0.0, ..., 0.0, 0.0, 0.0])"
         a = array(range(5), long)
         assert repr(a) == "array([0, 1, 2, 3, 4])"
+        a = array([], long)
+        assert repr(a) == "array([], dtype=int64)"
         a = array([True, False, True, False], "?")
         assert repr(a) == "array([True, False, True, False], dtype=bool)"
 
@@ -84,6 +88,9 @@
         a = array(range(5), dtype="int8")
         assert str(a) == "[0 1 2 3 4]"
 
+        a = array(range(5), dtype="int16")
+        assert str(a) == "[0 1 2 3 4]"
+
     def test_str_slice(self):
         from numpy import array, zeros
         a = array(range(5), float)
@@ -102,6 +109,16 @@
         assert a[-1] == 8
         raises(IndexError, "a[-6]")
 
+    def test_getitem_tuple(self):
+        from numpy import array
+        a = array(range(5))
+        raises(IndexError, "a[(1,2)]")
+        for i in xrange(5):
+            assert a[(i,)] == i
+        b = a[()]
+        for i in xrange(5):
+            assert a[i] == b[i]
+
     def test_setitem(self):
         from numpy import array
         a = array(range(5))
@@ -110,6 +127,17 @@
         raises(IndexError, "a[5] = 0.0")
         raises(IndexError, "a[-6] = 3.0")
 
+    def test_setitem_tuple(self):
+        from numpy import array
+        a = array(range(5))
+        raises(IndexError, "a[(1,2)] = [0,1]")
+        for i in xrange(5):
+            a[(i,)] = i+1
+            assert a[i] == i+1
+        a[()] = range(5)
+        for i in xrange(5):
+            assert a[i] == i
+
     def test_setslice_array(self):
         from numpy import array
         a = array(range(5))
@@ -529,6 +557,26 @@
         assert array([1.2, 5]).dtype is dtype(float)
         assert array([]).dtype is dtype(float)
 
+    def test_comparison(self):
+        import operator
+        from numpy import array, dtype
+
+        a = array(range(5))
+        b = array(range(5), float)
+        for func in [
+            operator.eq, operator.ne, operator.lt, operator.le, operator.gt,
+            operator.ge
+        ]:
+            c = func(a, 3)
+            assert c.dtype is dtype(bool)
+            for i in xrange(5):
+                assert c[i] == func(a[i], 3)
+
+            c = func(b, 3)
+            assert c.dtype is dtype(bool)
+            for i in xrange(5):
+                assert c[i] == func(b[i], 3)
+
 
 class AppTestSupport(object):
     def setup_class(cls):
@@ -541,4 +589,4 @@
         a = fromstring(self.data)
         for i in range(4):
             assert a[i] == i + 1
-        raises(ValueError, fromstring, "abc")
\ No newline at end of file
+        raises(ValueError, fromstring, "abc")
diff --git a/pypy/module/micronumpy/test/test_ufuncs.py b/pypy/module/micronumpy/test/test_ufuncs.py
--- a/pypy/module/micronumpy/test/test_ufuncs.py
+++ b/pypy/module/micronumpy/test/test_ufuncs.py
@@ -3,6 +3,32 @@
 
 
 class AppTestUfuncs(BaseNumpyAppTest):
+    def test_ufunc_instance(self):
+        from numpy import add, ufunc
+
+        assert isinstance(add, ufunc)
+        assert repr(add) == "<ufunc 'add'>"
+        assert repr(ufunc) == "<type 'numpy.ufunc'>"
+
+    def test_ufunc_attrs(self):
+        from numpy import add, multiply, sin
+
+        assert add.identity == 0
+        assert multiply.identity == 1
+        assert sin.identity is None
+
+        assert add.nin == 2
+        assert multiply.nin == 2
+        assert sin.nin == 1
+
+    def test_wrong_arguments(self):
+        from numpy import add, sin
+
+        raises(TypeError, add, 1)
+        raises(TypeError, add, 1, 2, 3)
+        raises(TypeError, sin, 1, 2)
+        raises(TypeError, sin)
+
     def test_single_item(self):
         from numpy import negative, sign, minimum
 
@@ -272,3 +298,42 @@
         b = arctan(a)
         assert math.isnan(b[0])
 
+    def test_reduce_errors(self):
+        from numpy import sin, add
+
+        raises(ValueError, sin.reduce, [1, 2, 3])
+        raises(TypeError, add.reduce, 1)
+
+    def test_reduce(self):
+        from numpy import add, maximum
+
+        assert add.reduce([1, 2, 3]) == 6
+        assert maximum.reduce([1]) == 1
+        assert maximum.reduce([1, 2, 3]) == 3
+        raises(ValueError, maximum.reduce, [])
+
+    def test_comparisons(self):
+        import operator
+        from numpy import equal, not_equal, less, less_equal, greater, greater_equal
+
+        for ufunc, func in [
+            (equal, operator.eq),
+            (not_equal, operator.ne),
+            (less, operator.lt),
+            (less_equal, operator.le),
+            (greater, operator.gt),
+            (greater_equal, operator.ge),
+        ]:
+            for a, b in [
+                (3, 3),
+                (3, 4),
+                (4, 3),
+                (3.0, 3.0),
+                (3.0, 3.5),
+                (3.5, 3.0),
+                (3.0, 3),
+                (3, 3.0),
+                (3.5, 3),
+                (3, 3.5),
+            ]:
+                assert ufunc(a, b) is func(a, b)
diff --git a/pypy/module/micronumpy/test/test_zjit.py b/pypy/module/micronumpy/test/test_zjit.py
--- a/pypy/module/micronumpy/test/test_zjit.py
+++ b/pypy/module/micronumpy/test/test_zjit.py
@@ -19,7 +19,7 @@
     def test_add(self):
         def f(i):
             ar = SingleDimArray(i, dtype=self.float64_dtype)
-            v = interp_ufuncs.add(self.space, ar, ar)
+            v = interp_ufuncs.get(self.space).add.call(self.space, [ar, ar])
             return v.get_concrete().eval(3).val
 
         result = self.meta_interp(f, [5], listops=True, backendopt=True)
@@ -31,9 +31,10 @@
     def test_floatadd(self):
         def f(i):
             ar = SingleDimArray(i, dtype=self.float64_dtype)
-            v = interp_ufuncs.add(self.space,
-                ar,
-                scalar_w(self.space, self.float64_dtype, self.space.wrap(4.5))
+            v = interp_ufuncs.get(self.space).add.call(self.space, [
+                    ar,
+                    scalar_w(self.space, self.float64_dtype, self.space.wrap(4.5))
+                ],
             )
             assert isinstance(v, BaseArray)
             return v.get_concrete().eval(3).val
@@ -89,14 +90,21 @@
     def test_max(self):
         space = self.space
         float64_dtype = self.float64_dtype
+        int64_dtype = self.int64_dtype
 
         def f(i):
-            ar = SingleDimArray(i, dtype=NonConstant(float64_dtype))
+            if NonConstant(False):
+                dtype = int64_dtype
+            else:
+                dtype = float64_dtype
+            ar = SingleDimArray(i, dtype=dtype)
             j = 0
             while j < i:
                 ar.get_concrete().setitem(j, float64_dtype.box(float(j)))
                 j += 1
-            return ar.descr_add(space, ar).descr_max(space).floatval
+            v = ar.descr_add(space, ar).descr_max(space)
+            assert isinstance(v, FloatObject)
+            return v.floatval
 
         result = self.meta_interp(f, [5], listops=True, backendopt=True)
         self.check_loops({"getarrayitem_raw": 2, "float_add": 1,
@@ -108,14 +116,21 @@
     def test_min(self):
         space = self.space
         float64_dtype = self.float64_dtype
+        int64_dtype = self.int64_dtype
 
         def f(i):
-            ar = SingleDimArray(i, dtype=NonConstant(float64_dtype))
+            if NonConstant(False):
+                dtype = int64_dtype
+            else:
+                dtype = float64_dtype
+            ar = SingleDimArray(i, dtype=dtype)
             j = 0
             while j < i:
                 ar.get_concrete().setitem(j, float64_dtype.box(float(j)))
                 j += 1
-            return ar.descr_add(space, ar).descr_min(space).floatval
+            v = ar.descr_add(space, ar).descr_min(space)
+            assert isinstance(v, FloatObject)
+            return v.floatval
 
         result = self.meta_interp(f, [5], listops=True, backendopt=True)
         self.check_loops({"getarrayitem_raw": 2, "float_add": 1,
@@ -180,9 +195,9 @@
 
         def f(i):
             ar = SingleDimArray(i, dtype=self.float64_dtype)
-            v1 = interp_ufuncs.add(space, ar, scalar_w(space, self.float64_dtype, space.wrap(4.5)))
+            v1 = interp_ufuncs.get(self.space).add.call(space, [ar, scalar_w(space, self.float64_dtype, space.wrap(4.5))])
             assert isinstance(v1, BaseArray)
-            v2 = interp_ufuncs.multiply(space, v1, scalar_w(space, self.float64_dtype, space.wrap(4.5)))
+            v2 = interp_ufuncs.get(self.space).multiply.call(space, [v1, scalar_w(space, self.float64_dtype, space.wrap(4.5))])
             v1.force_if_needed()
             assert isinstance(v2, BaseArray)
             return v2.get_concrete().eval(3).val
@@ -200,8 +215,8 @@
         space = self.space
         def f(i):
             ar = SingleDimArray(i, dtype=self.float64_dtype)
-            v1 = interp_ufuncs.add(space, ar, ar)
-            v2 = interp_ufuncs.negative(space, v1)
+            v1 = interp_ufuncs.get(self.space).add.call(space, [ar, ar])
+            v2 = interp_ufuncs.get(self.space).negative.call(space, [v1])
             return v2.get_concrete().eval(3).val
 
         result = self.meta_interp(f, [5], listops=True, backendopt=True)
@@ -216,13 +231,13 @@
         def f(i):
             ar = SingleDimArray(i, dtype=self.float64_dtype)
 
-            v1 = interp_ufuncs.add(space, ar, ar)
-            v2 = interp_ufuncs.negative(space, v1)
+            v1 = interp_ufuncs.get(self.space).add.call(space, [ar, ar])
+            v2 = interp_ufuncs.get(self.space).negative.call(space, [v1])
             v2.get_concrete()
 
             for i in xrange(5):
-                v1 = interp_ufuncs.multiply(space, ar, ar)
-                v2 = interp_ufuncs.negative(space, v1)
+                v1 = interp_ufuncs.get(self.space).multiply.call(space, [ar, ar])
+                v2 = interp_ufuncs.get(self.space).negative.call(space, [v1])
                 v2.get_concrete()
 
         self.meta_interp(f, [5], listops=True, backendopt=True)
@@ -237,7 +252,7 @@
                 SingleDimSlice.signature, ar.signature
             ])
             s = SingleDimSlice(0, step*i, step, i, ar, new_sig)
-            v = interp_ufuncs.add(self.space, s, s)
+            v = interp_ufuncs.get(self.space).add.call(self.space, [s, s])
             return v.get_concrete().eval(3).val
 
         result = self.meta_interp(f, [5], listops=True, backendopt=True)
@@ -259,7 +274,7 @@
                 SingleDimSlice.signature, s1.signature
             ])
             s2 = SingleDimSlice(0, step2*i, step2, i, ar, new_sig)
-            v = interp_ufuncs.add(self.space, s1, s2)
+            v = interp_ufuncs.get(self.space).add.call(self.space, [s1, s2])
             return v.get_concrete().eval(3).val
 
         result = self.meta_interp(f, [5], listops=True, backendopt=True)
diff --git a/pypy/module/pwd/__init__.py b/pypy/module/pwd/__init__.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/pwd/__init__.py
@@ -0,0 +1,25 @@
+from pypy.interpreter.mixedmodule import MixedModule
+
+class Module(MixedModule):
+    """
+    This module provides access to the Unix password database.
+    It is available on all Unix versions.
+
+    Password database entries are reported as 7-tuples containing the following
+    items from the password database (see `<pwd.h>'), in order:
+    pw_name, pw_passwd, pw_uid, pw_gid, pw_gecos, pw_dir, pw_shell.
+    The uid and gid items are integers, all others are strings. An
+    exception is raised if the entry asked for cannot be found.
+    """
+
+    interpleveldefs = {
+        'getpwuid': 'interp_pwd.getpwuid',
+        'getpwnam': 'interp_pwd.getpwnam',
+        'getpwall': 'interp_pwd.getpwall',
+    }
+
+    appleveldefs = {
+        'struct_passwd': 'app_pwd.struct_passwd',
+        'struct_pwent': 'app_pwd.struct_passwd',
+    }
+
diff --git a/pypy/module/pwd/app_pwd.py b/pypy/module/pwd/app_pwd.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/pwd/app_pwd.py
@@ -0,0 +1,20 @@
+from _structseq import structseqtype, structseqfield
+
+class struct_passwd:
+    """
+    pwd.struct_passwd: Results from getpw*() routines.
+
+    This object may be accessed either as a tuple of
+      (pw_name,pw_passwd,pw_uid,pw_gid,pw_gecos,pw_dir,pw_shell)
+    or via the object attributes as named in the above tuple.
+    """
+    __metaclass__ = structseqtype
+    name = "pwd.struct_passwd"
+
+    pw_name   = structseqfield(0, "user name")
+    pw_passwd = structseqfield(1, "password")
+    pw_uid    = structseqfield(2, "user id")
+    pw_gid    = structseqfield(3, "group id")
+    pw_gecos  = structseqfield(4, "real name")
+    pw_dir    = structseqfield(5, "home directory")
+    pw_shell  = structseqfield(6, "shell program")
diff --git a/pypy/module/pwd/interp_pwd.py b/pypy/module/pwd/interp_pwd.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/pwd/interp_pwd.py
@@ -0,0 +1,95 @@
+from pypy.translator.tool.cbuild import ExternalCompilationInfo
+from pypy.rpython.tool import rffi_platform
+from pypy.rpython.lltypesystem import rffi, lltype
+from pypy.interpreter.gateway import interp2app, unwrap_spec
+from pypy.interpreter.error import OperationError, operationerrfmt
+from pypy.rlib.rarithmetic import intmask
+
+eci = ExternalCompilationInfo(
+    includes=['pwd.h']
+    )
+
+class CConfig:
+    _compilation_info_ = eci
+
+    uid_t = rffi_platform.SimpleType("uid_t")
+
+    passwd = rffi_platform.Struct(
+        'struct passwd',
+        [('pw_name', rffi.CCHARP),
+         ('pw_passwd', rffi.CCHARP),
+         ('pw_uid', rffi.INT),
+         ('pw_gid', rffi.INT),
+         ('pw_gecos', rffi.CCHARP),
+         ('pw_dir', rffi.CCHARP),
+         ('pw_shell', rffi.CCHARP),
+         ])
+
+config = rffi_platform.configure(CConfig)
+passwd_p = lltype.Ptr(config['passwd'])
+uid_t = config['uid_t']
+
+def external(name, args, result, **kwargs):
+    return rffi.llexternal(name, args, result, compilation_info=eci, **kwargs)
+
+c_getpwuid = external("getpwuid", [uid_t], passwd_p)
+c_getpwnam = external("getpwnam", [rffi.CCHARP], passwd_p)
+c_setpwent = external("setpwent", [], lltype.Void)
+c_getpwent = external("getpwent", [], passwd_p)
+c_endpwent = external("endpwent", [], lltype.Void)
+
+def make_struct_passwd(space, pw):
+    w_passwd_struct = space.getattr(space.getbuiltinmodule('pwd'),
+                                    space.wrap('struct_passwd'))
+    w_tuple = space.newtuple([
+        space.wrap(rffi.charp2str(pw.c_pw_name)),
+        space.wrap(rffi.charp2str(pw.c_pw_passwd)),
+        space.wrap(intmask(pw.c_pw_uid)),
+        space.wrap(intmask(pw.c_pw_gid)),
+        space.wrap(rffi.charp2str(pw.c_pw_gecos)),
+        space.wrap(rffi.charp2str(pw.c_pw_dir)),
+        space.wrap(rffi.charp2str(pw.c_pw_shell)),
+        ])
+    return space.call_function(w_passwd_struct, w_tuple)
+
+ at unwrap_spec(uid=int)
+def getpwuid(space, uid):
+    """
+    getpwuid(uid) -> (pw_name,pw_passwd,pw_uid,
+                      pw_gid,pw_gecos,pw_dir,pw_shell)
+    Return the password database entry for the given numeric user ID.
+    See pwd.__doc__ for more on password database entries.
+    """
+    pw = c_getpwuid(uid)
+    if not pw:
+        raise operationerrfmt(space.w_KeyError,
+            "getpwuid(): uid not found: %d", uid)
+    return make_struct_passwd(space, pw)
+
+ at unwrap_spec(name=str)
+def getpwnam(space, name):
+    """
+    getpwnam(name) -> (pw_name,pw_passwd,pw_uid,
+                        pw_gid,pw_gecos,pw_dir,pw_shell)
+    Return the password database entry for the given user name.
+    See pwd.__doc__ for more on password database entries.
+    """
+    pw = c_getpwnam(name)
+    if not pw:
+        raise operationerrfmt(space.w_KeyError,
+            "getpwnam(): name not found: %s", name)
+    return make_struct_passwd(space, pw)
+
+def getpwall(space):
+    users_w = []
+    c_setpwent()
+    try:
+        while True:
+            pw = c_getpwent()
+            if not pw:
+                break
+            users_w.append(make_struct_passwd(space, pw))
+    finally:
+        c_endpwent()
+    return space.newlist(users_w)
+    
diff --git a/pypy/module/pwd/test/test_pwd.py b/pypy/module/pwd/test/test_pwd.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/pwd/test/test_pwd.py
@@ -0,0 +1,28 @@
+from pypy.conftest import gettestobjspace
+
+class AppTestPwd:
+    def setup_class(cls):
+        cls.space = gettestobjspace(usemodules=['pwd'])
+
+    def test_getpwuid(self):
+        import pwd
+        raises(KeyError, pwd.getpwuid, -1)
+        pw = pwd.getpwuid(0)
+        assert pw.pw_name == 'root'
+        assert isinstance(pw.pw_passwd, str)
+        assert pw.pw_uid == 0
+        assert pw.pw_gid == 0
+        assert pw.pw_dir == '/root'
+        assert pw.pw_shell.startswith('/')
+        #
+        assert type(pw.pw_uid) is int
+        assert type(pw.pw_gid) is int
+
+    def test_getpwnam(self):
+        import pwd
+        raises(KeyError, pwd.getpwnam, '~invalid~')
+        assert pwd.getpwnam('root').pw_name == 'root'
+
+    def test_getpwall(self):
+        import pwd
+        assert pwd.getpwnam('root') in pwd.getpwall()
diff --git a/pypy/module/pypyjit/interp_jit.py b/pypy/module/pypyjit/interp_jit.py
--- a/pypy/module/pypyjit/interp_jit.py
+++ b/pypy/module/pypyjit/interp_jit.py
@@ -21,6 +21,7 @@
 
 PyFrame._virtualizable2_ = ['last_instr', 'pycode',
                             'valuestackdepth', 'locals_stack_w[*]',
+                            'cells[*]',
                             'last_exception',
                             'lastblock',
                             'is_being_profiled',
diff --git a/pypy/module/pypyjit/policy.py b/pypy/module/pypyjit/policy.py
--- a/pypy/module/pypyjit/policy.py
+++ b/pypy/module/pypyjit/policy.py
@@ -8,7 +8,8 @@
                 modname == '__builtin__.interp_classobj' or
                 modname == '__builtin__.functional' or
                 modname == '__builtin__.descriptor' or
-                modname == 'thread.os_local'):
+                modname == 'thread.os_local' or
+                modname == 'thread.os_thread'):
             return True
         if '.' in modname:
             modname, _ = modname.split('.', 1)
diff --git a/pypy/module/pypyjit/test/test_policy.py b/pypy/module/pypyjit/test/test_policy.py
--- a/pypy/module/pypyjit/test/test_policy.py
+++ b/pypy/module/pypyjit/test/test_policy.py
@@ -34,7 +34,9 @@
 
 def test_thread_local():
     from pypy.module.thread.os_local import Local
+    from pypy.module.thread.os_thread import get_ident
     assert pypypolicy.look_inside_function(Local.getdict.im_func)
+    assert pypypolicy.look_inside_function(get_ident)
 
 def test_pypy_module():
     from pypy.module._collections.interp_deque import W_Deque
diff --git a/pypy/module/pypyjit/test_pypy_c/model.py b/pypy/module/pypyjit/test_pypy_c/model.py
--- a/pypy/module/pypyjit/test_pypy_c/model.py
+++ b/pypy/module/pypyjit/test_pypy_c/model.py
@@ -2,7 +2,10 @@
 import sys
 import re
 import os.path
-from _pytest.assertion import newinterpret
+try:
+    from _pytest.assertion import newinterpret
+except ImportError:   # e.g. Python 2.5
+    newinterpret = None
 from pypy.tool.jitlogparser.parser import SimpleParser, Function, TraceForOpcode
 from pypy.tool.jitlogparser.storage import LoopStorage
 
@@ -196,7 +199,7 @@
                     source = str(source.deindent()).strip()
         except py.error.ENOENT:
             source = None
-        if source and source.startswith('self._assert('):
+        if source and source.startswith('self._assert(') and newinterpret:
             # transform self._assert(x, 'foo') into assert x, 'foo'
             source = source.replace('self._assert(', 'assert ')
             source = source[:-1] # remove the trailing ')'
diff --git a/pypy/module/pypyjit/test_pypy_c/test_00_model.py b/pypy/module/pypyjit/test_pypy_c/test_00_model.py
--- a/pypy/module/pypyjit/test_pypy_c/test_00_model.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_00_model.py
@@ -1,3 +1,4 @@
+from __future__ import with_statement
 import sys
 import types
 import subprocess
diff --git a/pypy/module/pypyjit/test_pypy_c/test_call.py b/pypy/module/pypyjit/test_pypy_c/test_call.py
--- a/pypy/module/pypyjit/test_pypy_c/test_call.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_call.py
@@ -174,7 +174,7 @@
             guard_no_overflow(descr=...)
             i18 = force_token()
             --TICK--
-            jump(p0, p1, p2, p3, p4, i8, p7, i17, p8, i9, i17, p10, p11, p12, descr=<Loop0>)
+            jump(..., descr=<Loop0>)
         """)
 
     def test_default_and_kw(self):
@@ -396,3 +396,70 @@
             --TICK--
             jump(..., descr=<Loop0>)
         """)
+
+    def test_global_closure_has_constant_cells(self):
+        log = self.run("""
+            def make_adder(n):
+                def add(x):
+                    return x + n
+                return add
+            add5 = make_adder(5)
+            def main():
+                i = 0
+                while i < 5000:
+                    i = add5(i) # ID: call
+            """, [])
+        loop, = log.loops_by_id('call', is_entry_bridge=True)
+        assert loop.match("""
+            guard_value(i6, 1, descr=...)
+            guard_nonnull_class(p8, ConstClass(W_IntObject), descr=...)
+            guard_value(i4, 0, descr=...)
+            guard_value(p3, ConstPtr(ptr14), descr=...)
+            i15 = getfield_gc_pure(p8, descr=<SignedFieldDescr pypy.objspace.std.intobject.W_IntObject.inst_intval .*>)
+            i17 = int_lt(i15, 5000)
+            guard_true(i17, descr=...)
+            p18 = getfield_gc(p0, descr=<GcPtrFieldDescr pypy.interpreter.eval.Frame.inst_w_globals .*>)
+            guard_value(p18, ConstPtr(ptr19), descr=...)
+            p20 = getfield_gc(p18, descr=<GcPtrFieldDescr pypy.objspace.std.dictmultiobject.W_DictMultiObject.inst_strategy .*>)
+            guard_value(p20, ConstPtr(ptr21), descr=...)
+            guard_not_invalidated(descr=...)
+            # most importantly, there is no getarrayitem_gc here
+            p23 = call(ConstClass(getexecutioncontext), descr=<GcPtrCallDescr>)
+            p24 = getfield_gc(p23, descr=<GcPtrFieldDescr pypy.interpreter.executioncontext.ExecutionContext.inst_topframeref .*>)
+            i25 = force_token()
+            p26 = getfield_gc(p23, descr=<GcPtrFieldDescr pypy.interpreter.executioncontext.ExecutionContext.inst_w_tracefunc .*>)
+            guard_isnull(p26, descr=...)
+            i27 = getfield_gc(p23, descr=<NonGcPtrFieldDescr pypy.interpreter.executioncontext.ExecutionContext.inst_profilefunc .*>)
+            i28 = int_is_zero(i27)
+            guard_true(i28, descr=...)
+            p30 = getfield_gc(ConstPtr(ptr29), descr=<GcPtrFieldDescr pypy.interpreter.nestedscope.Cell.inst_w_value .*>)
+            guard_nonnull_class(p30, ConstClass(W_IntObject), descr=...)
+            i32 = getfield_gc_pure(p30, descr=<SignedFieldDescr pypy.objspace.std.intobject.W_IntObject.inst_intval .*>)
+            i33 = int_add_ovf(i15, i32)
+            guard_no_overflow(descr=...)
+            --TICK--
+            jump(p0, p1, p2, p5, i33, i32, p23, p30, p24, descr=<Loop0>)
+        """)
+
+    def test_local_closure_is_virtual(self):
+        log = self.run("""
+            def main():
+                i = 0
+                while i < 5000:
+                    def add():
+                        return i + 1
+                    i = add() # ID: call
+            """, [])
+        loop, = log.loops_by_id('call')
+        assert loop.match("""
+            i8 = getfield_gc_pure(p6, descr=<SignedFieldDescr pypy.objspace.std.intobject.W_IntObject.inst_intval .*>)
+            i10 = int_lt(i8, 5000)
+            guard_true(i10, descr=...)
+            i11 = force_token()
+            i13 = int_add(i8, 1)
+            --TICK--
+            p22 = new_with_vtable(ConstClass(W_IntObject))
+            setfield_gc(p22, i13, descr=<SignedFieldDescr pypy.objspace.std.intobject.W_IntObject.inst_intval .*>)
+            setfield_gc(p4, p22, descr=<GcPtrFieldDescr pypy.interpreter.nestedscope.Cell.inst_w_value .*>)
+            jump(p0, p1, p2, p3, p4, p7, p22, p7, descr=<Loop0>)
+        """)
diff --git a/pypy/module/pypyjit/test_pypy_c/test_globals.py b/pypy/module/pypyjit/test_pypy_c/test_globals.py
--- a/pypy/module/pypyjit/test_pypy_c/test_globals.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_globals.py
@@ -23,6 +23,4 @@
             guard_not_invalidated(descr=...)
             p19 = getfield_gc(ConstPtr(p17), descr=<GcPtrFieldDescr .*W_DictMultiObject.inst_strategy .*>)
             guard_value(p19, ConstPtr(ptr20), descr=...)
-            p22 = getfield_gc(ConstPtr(ptr21), descr=<GcPtrFieldDescr .*ModuleCell.inst_w_value .*>)
-            guard_nonnull(p22, descr=...)
-        """)
+        """)
\ No newline at end of file
diff --git a/pypy/module/pypyjit/test_pypy_c/test_instance.py b/pypy/module/pypyjit/test_pypy_c/test_instance.py
--- a/pypy/module/pypyjit/test_pypy_c/test_instance.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_instance.py
@@ -142,6 +142,7 @@
             i = 0
             b = B(1)
             while i < 100:
+                b.x
                 v = b.x # ID: loadattr
                 i += v
             return i
@@ -150,8 +151,6 @@
         loop, = log.loops_by_filename(self.filepath)
         assert loop.match_by_id('loadattr',
         '''
-        guard_not_invalidated(descr=...)
-        i16 = arraylen_gc(p10, descr=<GcPtrArrayDescr>)
         i19 = call(ConstClass(ll_dict_lookup), _, _, _, descr=...)
         guard_no_exception(descr=...)
         i21 = int_and(i19, _)
@@ -181,8 +180,7 @@
         assert loop.match_by_id("contains", """
             guard_not_invalidated(descr=...)
             i11 = force_token()
-            i12 = int_add_ovf(i5, i7)
-            guard_no_overflow(descr=...)
+            i12 = int_add(i5, 1)
         """)
 
     def test_id_compare_optimization(self):
diff --git a/pypy/module/sys/__init__.py b/pypy/module/sys/__init__.py
--- a/pypy/module/sys/__init__.py
+++ b/pypy/module/sys/__init__.py
@@ -47,6 +47,7 @@
         'pypy_initial_path'     : 'state.pypy_initial_path',
 
         '_getframe'             : 'vm._getframe', 
+        '_current_frames'       : 'vm._current_frames', 
         'setrecursionlimit'     : 'vm.setrecursionlimit', 
         'getrecursionlimit'     : 'vm.getrecursionlimit', 
         'setcheckinterval'      : 'vm.setcheckinterval', 
diff --git a/pypy/module/sys/test/test_encoding.py b/pypy/module/sys/test/test_encoding.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/sys/test/test_encoding.py
@@ -0,0 +1,30 @@
+import os, py
+from pypy.rlib import rlocale
+from pypy.module.sys.interp_encoding import _getfilesystemencoding
+from pypy.module.sys.interp_encoding import base_encoding
+
+
+def test__getfilesystemencoding(space):
+    if not (rlocale.HAVE_LANGINFO and rlocale.CODESET):
+        py.test.skip("requires HAVE_LANGINFO and CODESET")
+
+    def clear():
+        for key in os.environ.keys():
+            if key == 'LANG' or key.startswith('LC_'):
+                del os.environ[key]
+
+    def get(**env):
+        original_env = os.environ.copy()
+        try:
+            clear()
+            os.environ.update(env)
+            return _getfilesystemencoding(space)
+        finally:
+            clear()
+            os.environ.update(original_env)
+
+    assert get() in (base_encoding, 'ANSI_X3.4-1968')
+    assert get(LANG='foobar') in (base_encoding, 'ANSI_X3.4-1968')
+    assert get(LANG='en_US.UTF-8') == 'UTF-8'
+    assert get(LC_ALL='en_US.UTF-8') == 'UTF-8'
+    assert get(LC_CTYPE='en_US.UTF-8') == 'UTF-8'
diff --git a/pypy/module/sys/test/test_sysmodule.py b/pypy/module/sys/test/test_sysmodule.py
--- a/pypy/module/sys/test/test_sysmodule.py
+++ b/pypy/module/sys/test/test_sysmodule.py
@@ -1,6 +1,6 @@
 # -*- coding: iso-8859-1 -*-
 import autopath
-from pypy.conftest import option
+from pypy.conftest import option, gettestobjspace
 from py.test import raises
 from pypy.interpreter.gateway import app2interp_temp
 import sys
@@ -524,3 +524,51 @@
         # If this ever actually becomes a compilation option this test should
         # be changed.
         assert sys.float_repr_style == "short"
+
+class AppTestCurrentFrames:
+
+    def test_current_frames(self):
+        try:
+            import thread
+        except ImportError:
+            pass
+        else:
+            skip('This test requires an intepreter without threads')
+        import sys
+
+        def f():
+            return sys._current_frames()
+        frames = f()
+        assert frames.keys() == [0]
+        assert frames[0].f_code.co_name == 'f'
+
+class AppTestCurrentFramesWithThread(AppTestCurrentFrames):
+    def setup_class(cls):
+        cls.space = gettestobjspace(usemodules=('thread',))
+
+    def test_current_frames(self):
+        import sys
+        import time
+        import thread
+
+        thread_id = thread.get_ident()
+        self.ready = False
+        def other_thread():
+            self.ready = True
+            print "thread started"
+            time.sleep(5)
+        thread.start_new_thread(other_thread, ())
+
+        def f():
+            for i in range(100):
+                if self.ready: break
+                time.sleep(0.1)
+            return sys._current_frames()
+        
+        frames = f()
+        thisframe = frames.pop(thread_id)
+        assert thisframe.f_code.co_name == 'f'
+
+        assert len(frames) == 1
+        _, other_frame = frames.popitem()
+        assert other_frame.f_code.co_name == 'other_thread'
diff --git a/pypy/module/sys/version.py b/pypy/module/sys/version.py
--- a/pypy/module/sys/version.py
+++ b/pypy/module/sys/version.py
@@ -14,7 +14,7 @@
 
 if platform.name == 'msvc':
     COMPILER_INFO = 'MSC v.%d 32 bit' % (platform.version * 10 + 600)
-elif platform.cc.startswith('gcc'):
+elif platform.cc is not None and platform.cc.startswith('gcc'):
     out = platform.execute(platform.cc, '--version').out
     match = re.search(' (\d+\.\d+(\.\d+)*)', out)
     if match:
diff --git a/pypy/module/sys/vm.py b/pypy/module/sys/vm.py
--- a/pypy/module/sys/vm.py
+++ b/pypy/module/sys/vm.py
@@ -43,6 +43,23 @@
     f.mark_as_escaped()
     return space.wrap(f)
 
+def _current_frames(space):
+    """_current_frames() -> dictionary
+
+    Return a dictionary mapping each current thread T's thread id to T's
+    current stack frame.
+
+    This function should be used for specialized purposes only."""
+    w_result = space.newdict()
+    ecs = space.threadlocals.getallvalues()
+    for thread_ident, ec in ecs.items():
+        f = ec.gettopframe_nohidden()
+        f.mark_as_escaped()
+        space.setitem(w_result,
+                      space.wrap(thread_ident),
+                      space.wrap(f))
+    return w_result                      
+
 def setrecursionlimit(space, w_new_limit):
     """setrecursionlimit() sets the maximum number of nested calls that
 can occur before a RuntimeError is raised.  On PyPy the limit is
diff --git a/pypy/module/test_lib_pypy/test_distributed/test_distributed.py b/pypy/module/test_lib_pypy/test_distributed/test_distributed.py
--- a/pypy/module/test_lib_pypy/test_distributed/test_distributed.py
+++ b/pypy/module/test_lib_pypy/test_distributed/test_distributed.py
@@ -1,3 +1,4 @@
+import py; py.test.skip("xxx remove")
 
 """ Controllers tests
 """
@@ -8,7 +9,7 @@
 class AppTestDistributed(object):
     def setup_class(cls):
         cls.space = gettestobjspace(**{"objspace.std.withtproxy": True,
-            "usemodules":("_stackless",)})
+            "usemodules":("_continuation",)})
 
     def test_init(self):
         import distributed
@@ -90,14 +91,12 @@
 
 class AppTestDistributedTasklets(object):
     spaceconfig = {"objspace.std.withtproxy": True,
-                   "objspace.usemodules._stackless": True}
+                   "objspace.usemodules._continuation": True}
     reclimit = sys.getrecursionlimit()
 
     def setup_class(cls):
         import py.test
         py.test.importorskip('greenlet')
-        #cls.space = gettestobjspace(**{"objspace.std.withtproxy": True,
-        #    "usemodules":("_stackless",)})
         cls.w_test_env_ = cls.space.appexec([], """():
         from distributed import test_env
         return (test_env,)
diff --git a/pypy/module/test_lib_pypy/test_distributed/test_greensock.py b/pypy/module/test_lib_pypy/test_distributed/test_greensock.py
--- a/pypy/module/test_lib_pypy/test_distributed/test_greensock.py
+++ b/pypy/module/test_lib_pypy/test_distributed/test_greensock.py
@@ -1,5 +1,4 @@
-
-import py
+import py; py.test.skip("xxx remove")
 from pypy.conftest import gettestobjspace, option
 
 def setup_module(mod):
@@ -10,7 +9,7 @@
         if not option.runappdirect:
             py.test.skip("Cannot run this on top of py.py because of PopenGateway")
         cls.space = gettestobjspace(**{"objspace.std.withtproxy": True,
-                                       "usemodules":("_stackless",)})
+                                       "usemodules":("_continuation",)})
         cls.w_remote_side_code = cls.space.appexec([], """():
         import sys
         sys.path.insert(0, '%s')
diff --git a/pypy/module/test_lib_pypy/test_distributed/test_socklayer.py b/pypy/module/test_lib_pypy/test_distributed/test_socklayer.py
--- a/pypy/module/test_lib_pypy/test_distributed/test_socklayer.py
+++ b/pypy/module/test_lib_pypy/test_distributed/test_socklayer.py
@@ -1,4 +1,4 @@
-import py
+import py; py.test.skip("xxx remove")
 from pypy.conftest import gettestobjspace
 
 def setup_module(mod):
@@ -9,7 +9,8 @@
 class AppTestSocklayer:
     def setup_class(cls):
         cls.space = gettestobjspace(**{"objspace.std.withtproxy": True,
-                                       "usemodules":("_stackless","_socket", "select")})
+                                       "usemodules":("_continuation",
+                                                     "_socket", "select")})
     
     def test_socklayer(self):
         class X(object):
diff --git a/pypy/module/test_lib_pypy/test_greenlet.py b/pypy/module/test_lib_pypy/test_greenlet.py
--- a/pypy/module/test_lib_pypy/test_greenlet.py
+++ b/pypy/module/test_lib_pypy/test_greenlet.py
@@ -231,3 +231,13 @@
         assert res == "next step"
         res = g2.switch("goes to f1 instead")
         assert res == "all ok"
+
+    def test_throw_in_not_started_yet(self):
+        from greenlet import greenlet
+        #
+        def f1():
+            never_reached
+        #
+        g1 = greenlet(f1)
+        raises(ValueError, g1.throw, ValueError)
+        assert g1.dead
diff --git a/pypy/module/test_lib_pypy/test_stackless.py b/pypy/module/test_lib_pypy/test_stackless_pickle.py
rename from pypy/module/test_lib_pypy/test_stackless.py
rename to pypy/module/test_lib_pypy/test_stackless_pickle.py
--- a/pypy/module/test_lib_pypy/test_stackless.py
+++ b/pypy/module/test_lib_pypy/test_stackless_pickle.py
@@ -1,3 +1,4 @@
+import py; py.test.skip("XXX port me")
 from pypy.conftest import gettestobjspace, option
 
 class AppTest_Stackless:
diff --git a/pypy/module/thread/threadlocals.py b/pypy/module/thread/threadlocals.py
--- a/pypy/module/thread/threadlocals.py
+++ b/pypy/module/thread/threadlocals.py
@@ -43,6 +43,9 @@
         ident = self._mainthreadident
         return self._valuedict.get(ident, None)
 
+    def getallvalues(self):
+        return self._valuedict
+
     def enter_thread(self, space):
         "Notification that the current thread is just starting."
         ec = space.getexecutioncontext()
diff --git a/pypy/objspace/flow/flowcontext.py b/pypy/objspace/flow/flowcontext.py
--- a/pypy/objspace/flow/flowcontext.py
+++ b/pypy/objspace/flow/flowcontext.py
@@ -184,7 +184,7 @@
 
 class FlowExecutionContext(ExecutionContext):
 
-    def __init__(self, space, code, globals, constargs={}, closure=None,
+    def __init__(self, space, code, globals, constargs={}, outer_func=None,
                  name=None):
         ExecutionContext.__init__(self, space)
         self.code = code
@@ -193,11 +193,11 @@
 
         self.crnt_offset = -1
         self.crnt_frame = None
-        if closure is None:
+        if outer_func and outer_func.closure:
+            self.closure = [nestedscope.Cell(Constant(value))
+                            for value in outer_func.closure]
+        else:
             self.closure = None
-        else:
-            self.closure = [nestedscope.Cell(Constant(value))
-                            for value in closure]
         frame = self.create_frame()
         formalargcount = code.getformalargcount()
         arg_list = [Variable() for i in range(formalargcount)]
@@ -216,7 +216,7 @@
         # while ignoring any operation like the creation of the locals dict
         self.recorder = []
         frame = FlowSpaceFrame(self.space, self.code,
-                               self.w_globals, self.closure)
+                               self.w_globals, self)
         frame.last_instr = 0
         return frame
 
diff --git a/pypy/objspace/flow/objspace.py b/pypy/objspace/flow/objspace.py
--- a/pypy/objspace/flow/objspace.py
+++ b/pypy/objspace/flow/objspace.py
@@ -252,9 +252,9 @@
             raise TypeError("%r is a generator" % (func,))
         code = PyCode._from_code(self, code)
         if func.func_closure is None:
-            closure = None
+            cl = None
         else:
-            closure = [extract_cell_content(c) for c in func.func_closure]
+            cl = [extract_cell_content(c) for c in func.func_closure]
         # CallableFactory.pycall may add class_ to functions that are methods
         name = func.func_name
         class_ = getattr(func, 'class_', None)
@@ -262,8 +262,10 @@
             name = '%s.%s' % (class_.__name__, name)
         for c in "<>&!":
             name = name.replace(c, '_')
+        class outerfunc: # hack
+            closure = cl
         ec = flowcontext.FlowExecutionContext(self, code, func.func_globals,
-                                              constargs, closure, name)
+                                              constargs, outerfunc, name)
         graph = ec.graph
         graph.func = func
         # attach a signature and defaults to the graph
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
@@ -65,6 +65,10 @@
         if isinstance(cell, ModuleCell):
             cell.w_value = w_value
             return
+        # If the new value and the current value are the same, don't create a
+        # level of indirection, or mutate are version.
+        if self.space.is_w(w_value, cell):
+            return
         if cell is not None:
             w_value = ModuleCell(w_value)
         self.mutated()
diff --git a/pypy/objspace/std/fake.py b/pypy/objspace/std/fake.py
--- a/pypy/objspace/std/fake.py
+++ b/pypy/objspace/std/fake.py
@@ -142,7 +142,7 @@
 
     def funcrun(self, func, args):
         frame = func.space.createframe(self, func.w_func_globals,
-                                        func.closure)
+                                       func)
         sig = self.signature()
         scope_w = args.parse_obj(None, func.name, sig, func.defs_w)
         frame.setfastscope(scope_w)
diff --git a/pypy/objspace/std/floatobject.py b/pypy/objspace/std/floatobject.py
--- a/pypy/objspace/std/floatobject.py
+++ b/pypy/objspace/std/floatobject.py
@@ -355,9 +355,13 @@
     y = w_float2.floatval
     if y == 0.0:
         raise FailedToImplementArgs(space.w_ZeroDivisionError, space.wrap("float modulo"))
-    mod = math.fmod(x, y)
-    if (mod and ((y < 0.0) != (mod < 0.0))):
-        mod += y
+    try:
+        mod = math.fmod(x, y)
+    except ValueError:
+        mod = rfloat.NAN
+    else:
+        if (mod and ((y < 0.0) != (mod < 0.0))):
+            mod += y
 
     return W_FloatObject(mod)
 
@@ -366,7 +370,10 @@
     y = w_float2.floatval
     if y == 0.0:
         raise FailedToImplementArgs(space.w_ZeroDivisionError, space.wrap("float modulo"))
-    mod = math.fmod(x, y)
+    try:
+        mod = math.fmod(x, y)
+    except ValueError:
+        return [W_FloatObject(rfloat.NAN), W_FloatObject(rfloat.NAN)]
     # fmod is typically exact, so vx-mod is *mathematically* an
     # exact multiple of wx.  But this is fp arithmetic, and fp
     # vx - mod is an approximation; the result is that div may
diff --git a/pypy/objspace/std/marshal_impl.py b/pypy/objspace/std/marshal_impl.py
--- a/pypy/objspace/std/marshal_impl.py
+++ b/pypy/objspace/std/marshal_impl.py
@@ -325,10 +325,10 @@
     # of building a list of tuples.
     w_dic = space.newdict()
     while 1:
-        w_key = u.get_w_obj(True)
+        w_key = u.get_w_obj(allow_null=True)
         if w_key is None:
             break
-        w_value = u.get_w_obj(False)
+        w_value = u.get_w_obj()
         space.setitem(w_dic, w_key, w_value)
     return w_dic
 register(TYPE_DICT, unmarshal_DictMulti)
@@ -364,7 +364,7 @@
 # so we no longer can handle it in interp_marshal.atom_strlist
 
 def unmarshal_str(u):
-    w_obj = u.get_w_obj(False)
+    w_obj = u.get_w_obj()
     try:
         return u.space.str_w(w_obj)
     except OperationError, e:
diff --git a/pypy/objspace/std/objecttype.py b/pypy/objspace/std/objecttype.py
--- a/pypy/objspace/std/objecttype.py
+++ b/pypy/objspace/std/objecttype.py
@@ -24,7 +24,12 @@
     return w_obj.getrepr(space, '%s object' % (classname,))
 
 def descr__str__(space, w_obj):
-    return space.repr(w_obj)
+    w_type = space.type(w_obj)
+    w_impl = w_type.lookup("__repr__")
+    if w_impl is None:
+        raise OperationError(space.w_TypeError,      # can it really occur?
+                             space.wrap("operand does not support unary str"))
+    return space.get_and_call_function(w_impl, w_obj)
 
 def descr__class__(space, w_obj):
     return space.type(w_obj)
diff --git a/pypy/objspace/std/objspace.py b/pypy/objspace/std/objspace.py
--- a/pypy/objspace/std/objspace.py
+++ b/pypy/objspace/std/objspace.py
@@ -129,12 +129,12 @@
         ec._py_repr = None
         return ec
 
-    def createframe(self, code, w_globals, closure=None):
+    def createframe(self, code, w_globals, outer_func=None):
         from pypy.objspace.std.fake import CPythonFakeCode, CPythonFakeFrame
         if not we_are_translated() and isinstance(code, CPythonFakeCode):
             return CPythonFakeFrame(self, code, w_globals)
         else:
-            return ObjSpace.createframe(self, code, w_globals, closure)
+            return ObjSpace.createframe(self, code, w_globals, outer_func)
 
     def gettypefor(self, cls):
         return self.gettypeobject(cls.typedef)
diff --git a/pypy/objspace/std/stringobject.py b/pypy/objspace/std/stringobject.py
--- a/pypy/objspace/std/stringobject.py
+++ b/pypy/objspace/std/stringobject.py
@@ -913,12 +913,16 @@
 def repr__String(space, w_str):
     s = w_str._value
 
-    buf = StringBuilder(len(s) + 2)
-
     quote = "'"
     if quote in s and '"' not in s:
         quote = '"'
 
+    return space.wrap(string_escape_encode(s, quote))
+
+def string_escape_encode(s, quote):
+
+    buf = StringBuilder(len(s) + 2)
+
     buf.append(quote)
     startslice = 0
 
@@ -959,7 +963,7 @@
 
     buf.append(quote)
 
-    return space.wrap(buf.build())
+    return buf.build()
 
 
 DEFAULT_NOOP_TABLE = ''.join([chr(i) for i in range(256)])
diff --git a/pypy/objspace/std/test/test_celldict.py b/pypy/objspace/std/test/test_celldict.py
--- a/pypy/objspace/std/test/test_celldict.py
+++ b/pypy/objspace/std/test/test_celldict.py
@@ -39,6 +39,20 @@
         assert d.getitem("a") is None
         assert d.strategy.getdictvalue_no_unwrapping(d, "a") is None
 
+    def test_same_key_set_twice(self):
+        strategy = ModuleDictStrategy(space)
+        storage = strategy.get_empty_storage()
+        d = W_DictMultiObject(space, strategy, storage)
+
+        v1 = strategy.version
+        x = object()
+        d.setitem("a", x)
+        v2 = strategy.version
+        assert v1 is not v2
+        d.setitem("a", x)
+        v3 = strategy.version
+        assert v2 is v3
+
 class AppTestModuleDict(object):
     def setup_class(cls):
         cls.space = gettestobjspace(**{"objspace.std.withcelldict": True})
diff --git a/pypy/objspace/std/test/test_floatobject.py b/pypy/objspace/std/test/test_floatobject.py
--- a/pypy/objspace/std/test/test_floatobject.py
+++ b/pypy/objspace/std/test/test_floatobject.py
@@ -767,3 +767,19 @@
 
     def test_invalid(self):
         raises(ValueError, float.fromhex, "0P")
+
+    def test_division_edgecases(self):
+        import math
+
+        # inf
+        inf = float("inf")
+        assert math.isnan(inf % 3)
+        assert math.isnan(inf // 3)
+        x, y = divmod(inf, 3)
+        assert math.isnan(x)
+        assert math.isnan(y)
+
+        # divide by 0
+        raises(ZeroDivisionError, lambda: inf % 0)
+        raises(ZeroDivisionError, lambda: inf // 0)
+        raises(ZeroDivisionError, divmod, inf, 0)
\ No newline at end of file
diff --git a/pypy/objspace/std/test/test_methodcache.py b/pypy/objspace/std/test/test_methodcache.py
--- a/pypy/objspace/std/test/test_methodcache.py
+++ b/pypy/objspace/std/test/test_methodcache.py
@@ -88,30 +88,37 @@
   
     def test_many_names(self):
         import __pypy__
-        class A(object):
-            foo = 5
-            bar = 6
-            baz = 7
-            xyz = 8
-            stuff = 9
-            a = 10
-            foobar = 11
+        for j in range(20):
+            class A(object):
+                foo = 5
+                bar = 6
+                baz = 7
+                xyz = 8
+                stuff = 9
+                a = 10
+                foobar = 11
 
-        a = A()
-        names = [name for name in A.__dict__.keys()
-                      if not name.startswith('_')]
-        names.sort()
-        names_repeated = names * 10
-        result = []
-        __pypy__.reset_method_cache_counter()
-        for name in names_repeated:
-            result.append(getattr(a, name))
-        append_counter = __pypy__.method_cache_counter("append")
-        names_counters = [__pypy__.method_cache_counter(name)
-                          for name in names]
-        assert append_counter[0] >= 5 * len(names)
-        for name, count in zip(names, names_counters):
-            assert count[0] >= 5, str((name, count))
+            a = A()
+            names = [name for name in A.__dict__.keys()
+                          if not name.startswith('_')]
+            names.sort()
+            names_repeated = names * 10
+            result = []
+            __pypy__.reset_method_cache_counter()
+            for name in names_repeated:
+                result.append(getattr(a, name))
+            append_counter = __pypy__.method_cache_counter("append")
+            names_counters = [__pypy__.method_cache_counter(name)
+                              for name in names]
+            try:
+                assert append_counter[0] >= 10 * len(names) - 1
+                for name, count in zip(names, names_counters):
+                    assert count == (9, 1), str((name, count))
+                break
+            except AssertionError:
+                pass
+        else:
+            raise
 
     def test_mutating_bases(self):
         class C(object):
@@ -134,20 +141,24 @@
 
     def test_custom_metaclass(self):
         import __pypy__
-        class MetaA(type):
-            def __getattribute__(self, x):
-                return 1
-        def f(self):
-            return 42
-        A = type.__new__(MetaA, "A", (), {"f": f})
-        l = [type.__getattribute__(A, "__new__")(A)] * 10
-        __pypy__.reset_method_cache_counter()
-        for i, a in enumerate(l):
-            assert a.f() == 42
-        cache_counter = __pypy__.method_cache_counter("f")
-        assert cache_counter[0] >= 5
-        assert cache_counter[1] >= 1 # should be (27, 3)
-        assert sum(cache_counter) == 10
+        for j in range(20):
+            class MetaA(type):
+                def __getattribute__(self, x):
+                    return 1
+            def f(self):
+                return 42
+            A = type.__new__(MetaA, "A", (), {"f": f})
+            l = [type.__getattribute__(A, "__new__")(A)] * 10
+            __pypy__.reset_method_cache_counter()
+            for i, a in enumerate(l):
+                assert a.f() == 42
+            cache_counter = __pypy__.method_cache_counter("f")
+            assert sum(cache_counter) == 10
+            if cache_counter == (9, 1):
+                break
+            #else the moon is misaligned, try again
+        else:
+            raise AssertionError("cache_counter = %r" % (cache_counter,))
 
     def test_mutate_class(self):
         import __pypy__
diff --git a/pypy/objspace/std/test/test_obj.py b/pypy/objspace/std/test/test_obj.py
--- a/pypy/objspace/std/test/test_obj.py
+++ b/pypy/objspace/std/test/test_obj.py
@@ -94,3 +94,11 @@
         #assert len(log) == 1
         #assert log[0].message.args == ("object.__init__() takes no parameters",)
         #assert type(log[0].message) is DeprecationWarning
+
+    def test_object_str(self):
+        # obscure case: __str__() must delegate to __repr__() without adding
+        # type checking on its own
+        class A(object):
+            def __repr__(self):
+                return 123456
+        assert A().__str__() == 123456
diff --git a/pypy/objspace/std/test/test_rangeobject.py b/pypy/objspace/std/test/test_rangeobject.py
--- a/pypy/objspace/std/test/test_rangeobject.py
+++ b/pypy/objspace/std/test/test_rangeobject.py
@@ -89,6 +89,9 @@
         assert not self.not_forced(r)
         r.sort()
         assert r == range(1, 100) + [999]
+        r = range(10)
+        r.sort(key=lambda x: -x)
+        assert r == range(9, -1, -1)
 
     def test_pop(self):
         r = range(10)
diff --git a/pypy/objspace/std/test/test_stringformat.py b/pypy/objspace/std/test/test_stringformat.py
--- a/pypy/objspace/std/test/test_stringformat.py
+++ b/pypy/objspace/std/test/test_stringformat.py
@@ -168,7 +168,7 @@
 
     def test_incomplete_format(self):
         raises(ValueError, '%'.__mod__, ((23,),))
-        raises(ValueError, '%('.__mod__, ({},))
+        raises((ValueError, TypeError), '%('.__mod__, ({},))
 
     def test_format_char(self):
         import sys
diff --git a/pypy/objspace/std/test/test_unicodeobject.py b/pypy/objspace/std/test/test_unicodeobject.py
--- a/pypy/objspace/std/test/test_unicodeobject.py
+++ b/pypy/objspace/std/test/test_unicodeobject.py
@@ -780,8 +780,22 @@
         assert type(s) is unicode
         assert s == u'\u1234'
 
+        # now the same with a new-style class...
+        class A(object):
+            def __init__(self, num):
+                self.num = num
+            def __str__(self):
+                return unichr(self.num)
+
+        s = '%s' % A(111)    # this is ASCII
+        assert type(s) is unicode
+        assert s == chr(111)
+
+        s = '%s' % A(0x1234)    # this is not ASCII
+        assert type(s) is unicode
+        assert s == u'\u1234'
+
     def test_formatting_unicode__str__2(self):
-        skip("this is completely insane")
         class A:
             def __str__(self):
                 return u'baz'
@@ -798,9 +812,22 @@
         s = '%s %s' % (a, b)
         assert s == u'baz bar'
 
+        skip("but this case here is completely insane")
         s = '%s %s' % (b, a)
         assert s == u'foo baz'
 
+    def test_formatting_unicode__str__3(self):
+        # "bah" is all I can say
+        class X(object):
+            def __repr__(self):
+                return u'\u1234'
+        '%s' % X()
+        #
+        class X(object):
+            def __str__(self):
+                return u'\u1234'
+        '%s' % X()
+
     def test_str_subclass(self):
         class Foo9(str):
             def __unicode__(self):
diff --git a/pypy/rlib/clibffi.py b/pypy/rlib/clibffi.py
--- a/pypy/rlib/clibffi.py
+++ b/pypy/rlib/clibffi.py
@@ -286,10 +286,10 @@
 
 FFI_OK = cConfig.FFI_OK
 FFI_BAD_TYPEDEF = cConfig.FFI_BAD_TYPEDEF
-FFI_DEFAULT_ABI = rffi.cast(rffi.USHORT, cConfig.FFI_DEFAULT_ABI)
+FFI_DEFAULT_ABI = cConfig.FFI_DEFAULT_ABI
 if _WIN32:
-    FFI_STDCALL = rffi.cast(rffi.USHORT, cConfig.FFI_STDCALL)
-FFI_TYPE_STRUCT = rffi.cast(rffi.USHORT, cConfig.FFI_TYPE_STRUCT)
+    FFI_STDCALL = cConfig.FFI_STDCALL
+FFI_TYPE_STRUCT = cConfig.FFI_TYPE_STRUCT
 FFI_CIFP = rffi.COpaquePtr('ffi_cif', compilation_info=eci)
 
 FFI_CLOSUREP = lltype.Ptr(cConfig.ffi_closure)
@@ -319,7 +319,7 @@
        which the 'ffistruct' member is a regular FFI_TYPE.
     """
     tpe = lltype.malloc(FFI_STRUCT_P.TO, len(field_types)+1, flavor='raw')
-    tpe.ffistruct.c_type = FFI_TYPE_STRUCT
+    tpe.ffistruct.c_type = rffi.cast(rffi.USHORT, FFI_TYPE_STRUCT)
     tpe.ffistruct.c_size = rffi.cast(rffi.SIZE_T, size)
     tpe.ffistruct.c_alignment = rffi.cast(rffi.USHORT, aligment)
     tpe.ffistruct.c_elements = rffi.cast(FFI_TYPE_PP,
@@ -402,12 +402,20 @@
 
 closureHeap = ClosureHeap()
 
-FUNCFLAG_STDCALL   = 0
-FUNCFLAG_CDECL     = 1  # for WINAPI calls
+FUNCFLAG_STDCALL   = 0    # on Windows: for WINAPI calls
+FUNCFLAG_CDECL     = 1    # on Windows: for __cdecl calls
 FUNCFLAG_PYTHONAPI = 4
 FUNCFLAG_USE_ERRNO = 8
 FUNCFLAG_USE_LASTERROR = 16
 
+def get_call_conv(flags, from_jit):
+    if _WIN32 and (flags & FUNCFLAG_CDECL == 0):
+        return FFI_STDCALL
+    else:
+        return FFI_DEFAULT_ABI
+get_call_conv._annspecialcase_ = 'specialize:arg(1)'     # hack :-/
+
+
 class AbstractFuncPtr(object):
     ll_cif = lltype.nullptr(FFI_CIFP.TO)
     ll_argtypes = lltype.nullptr(FFI_TYPE_PP.TO)
@@ -427,21 +435,17 @@
         self.ll_cif = lltype.malloc(FFI_CIFP.TO, flavor='raw',
                                     track_allocation=False) # freed by the __del__
 
-        if _WIN32 and (flags & FUNCFLAG_CDECL == 0):
-            cc = FFI_STDCALL
-        else:
-            cc = FFI_DEFAULT_ABI
-
         if _MSVC:
             # This little trick works correctly with MSVC.
             # It returns small structures in registers
-            if r_uint(restype.c_type) == FFI_TYPE_STRUCT:
+            if intmask(restype.c_type) == FFI_TYPE_STRUCT:
                 if restype.c_size <= 4:
                     restype = ffi_type_sint32
                 elif restype.c_size <= 8:
                     restype = ffi_type_sint64
 
-        res = c_ffi_prep_cif(self.ll_cif, cc,
+        res = c_ffi_prep_cif(self.ll_cif,
+                             rffi.cast(rffi.USHORT, get_call_conv(flags,False)),
                              rffi.cast(rffi.UINT, argnum), restype,
                              self.ll_argtypes)
         if not res == FFI_OK:
diff --git a/pypy/rlib/libffi.py b/pypy/rlib/libffi.py
--- a/pypy/rlib/libffi.py
+++ b/pypy/rlib/libffi.py
@@ -75,7 +75,7 @@
     @staticmethod
     @jit.elidable
     def is_struct(ffi_type):
-        return intmask(ffi_type.c_type) == intmask(FFI_TYPE_STRUCT)
+        return intmask(ffi_type.c_type) == FFI_TYPE_STRUCT
 
 types._import()
 
@@ -206,6 +206,7 @@
     _immutable_fields_ = ['funcsym']
     argtypes = []
     restype = lltype.nullptr(clibffi.FFI_TYPE_P.TO)
+    flags = 0
     funcsym = lltype.nullptr(rffi.VOIDP.TO)
 
     def __init__(self, name, argtypes, restype, funcsym, flags=FUNCFLAG_CDECL,
diff --git a/pypy/rlib/parsing/tree.py b/pypy/rlib/parsing/tree.py
--- a/pypy/rlib/parsing/tree.py
+++ b/pypy/rlib/parsing/tree.py
@@ -6,9 +6,16 @@
         content = ["digraph G{"]
         content.extend(self.dot())
         content.append("}")
-        p = py.test.ensuretemp("automaton").join("temp.dot")
+        try:
+            p = py.test.ensuretemp("automaton").join("temp.dot")
+            remove = False
+        except AttributeError: # pytest lacks ensuretemp, make a normal one
+            p = py.path.local.mkdtemp().join('automaton.dot')
+            remove = True
         p.write("\n".join(content))
         graphclient.display_dot_file(str(p))
+        if remove:
+            p.dirpath().remove()
 
 class Symbol(Node):
 
diff --git a/pypy/rlib/rcoroutine.py b/pypy/rlib/rcoroutine.py
deleted file mode 100644
--- a/pypy/rlib/rcoroutine.py
+++ /dev/null
@@ -1,357 +0,0 @@
-"""
-Basic Concept:
---------------
-
-All concurrency is expressed by some means of coroutines.
-This is the lowest possible exposable interface.
-
-A coroutine is a structure that controls a sequence
-of continuations in time. It contains a frame object
-that is a restartable stack chain. This frame object
-is updated on every switch.
-
-The frame can be None. Either the coroutine is not yet
-bound, or it is the current coroutine of some costate.
-See below. XXX rewrite a definition of these terms.
-
-There is always a notation of a "current" and a "last"
-coroutine. Current has no frame and represents the
-running program. last is needed to keep track of the
-coroutine that receives a new frame chain after a switch.
-
-A costate object holds last and current.
-There are different coroutine concepts existing in
-parallel, like plain interp-level coroutines and
-app-level structures like coroutines, greenlets and
-tasklets.
-Every concept is associated with its own costate object.
-This allows for peaceful co-existence of many concepts.
-The type of a switch is determined by the target's costate.
-"""
-
-import py; py.test.skip("fixme: rewrite using rlib.rstacklet")
-# XXX ^^^ the reason it is not done is that pypy.rlib.rcoroutine
-# plus pypy/module/_stackless look like faaaaaar too much code
-# to me :-(
-
-from pypy.rlib.rstack import yield_current_frame_to_caller
-from pypy.rlib.objectmodel import we_are_translated
-
-from pypy.interpreter.error import OperationError
-
-try:
-    from greenlet import greenlet
-    main_greenlet = greenlet.getcurrent()
-except (ImportError, ValueError):
-    def greenlet(*args, **kwargs):
-        raise NotImplementedError("need either greenlets or a translated version of pypy")
-
-class FrameChain(object):
-    """Greenlet-based emulation of the primitive rstack 'frames' of RPython"""
-
-    def __init__(self, thunk=None):
-        if thunk:
-            self.greenlet = greenlet(thunk)
-        else:
-            self.greenlet = greenlet.getcurrent()
-
-    def switch(self):
-        last = FrameChain()
-        return self.greenlet.switch(last)
-
-import sys, os
-
-def make_coroutine_classes(baseclass):
-    class BaseCoState(object):
-        def __init__(self):
-            self.current = self.main = None
-
-        def __repr__(self):
-            "NOT_RPYTHON"
-            # for debugging only
-            return '<%s current=%r>' % (self.__class__.__name__, self.current)
-
-        def update(self, new):
-            syncstate.leaving = self.current
-            syncstate.entering = new
-            self.current = new
-            frame, new.frame = new.frame, None
-            return frame
-
-
-    class CoState(BaseCoState):
-        def __init__(self):
-            BaseCoState.__init__(self)
-            self.current = self.main = Coroutine(self)
-
-    class CoroutineDamage(SystemError):
-        pass
-
-
-    class SyncState(object):
-        def __init__(self):
-            self.reset()
-
-        def reset(self):
-            self.default_costate = None
-            self.leaving = None
-            self.entering = None
-            self.things_to_do = False
-            self.temp_exc = None
-            self.to_delete = []
-
-        def switched(self, incoming_frame):
-            left = syncstate.leaving
-            entered = syncstate.entering
-            syncstate.leaving = syncstate.entering = None
-            if left is not None:   # mostly to work around an annotation problem;
-                                   # should not really be None
-                left.frame = incoming_frame
-                left.goodbye()
-            if entered is not None:
-                entered.hello()
-            if self.things_to_do:
-                self._do_things_to_do()
-
-        def push_exception(self, exc):
-            self.things_to_do = True
-            self.temp_exc = exc
-
-        def check_for_zombie(self, obj):
-            return obj in self.to_delete
-
-        def postpone_deletion(self, obj):
-            self.to_delete.append(obj)
-            self.things_to_do = True
-
-        def _do_things_to_do(self):
-            if self.temp_exc is not None:
-                # somebody left an unhandled exception and switched to us.
-                # this both provides default exception handling and the
-                # way to inject an exception, like CoroutineExit.
-                e, self.temp_exc = self.temp_exc, None
-                self.things_to_do = bool(self.to_delete)
-                raise e
-            while self.to_delete:
-                delete, self.to_delete = self.to_delete, []
-                for obj in delete:
-                    obj.parent = obj.costate.current
-                    obj._kill_finally()
-            else:
-                self.things_to_do = False
-
-        def _freeze_(self):
-            self.reset()
-            return False
-
-    syncstate = SyncState()
-
-
-    class CoroutineExit(SystemExit):
-        # XXX SystemExit's __init__ creates problems in bookkeeper.
-        def __init__(self):
-            pass
-
-    class AbstractThunk(object):
-        def call(self):
-            raise NotImplementedError("abstract base class")
-
-
-    class Coroutine(baseclass):
-        def __init__(self, state=None):
-            self.frame = None
-            if state is None:
-                state = self._get_default_costate()
-            self.costate = state
-            self.parent = None
-            self.thunk = None
-            self.coroutine_exit = False
-
-        def __repr__(self):
-            'NOT_RPYTHON'
-            # just for debugging
-            if hasattr(self, '__name__'):
-                return '<Coro %s frame=%r %s>' % (self.__name__, self.frame, self.thunk is not None)
-            else:
-                return '<coro frame=%r %s>' % (self.frame, self.thunk is not None)
-
-        def _get_default_costate():
-            state = syncstate.default_costate
-            if state is None:
-                state = syncstate.default_costate = CoState()
-            return state
-        _get_default_costate = staticmethod(_get_default_costate)
-
-        def _get_default_parent(self):
-            return self.costate.current
-
-        def bind(self, thunk):
-            assert isinstance(thunk, AbstractThunk)
-            if self.frame is not None:
-                raise CoroutineDamage
-            if self.parent is None:
-                self.parent = self._get_default_parent()
-            assert self.parent is not None
-            self.thunk = thunk
-            if we_are_translated():
-                self.frame = self._bind()
-            else:
-                self.frame = self._greenlet_bind()
-
-        def _greenlet_bind(self):
-            weak = [self]
-            def _greenlet_execute(incoming_frame):
-                try:
-                    chain2go2next = weak[0]._execute(incoming_frame)
-                except:
-                    # no exception is supposed to get out of _execute()
-                    # better report it directly into the main greenlet then,
-                    # and hidden to prevent catching
-                    main_greenlet.throw(AssertionError(
-                        "unexpected exception out of Coroutine._execute()",
-                        *sys.exc_info()))
-                    assert 0
-                del weak[0]
-                greenlet.getcurrent().parent = chain2go2next.greenlet
-                return None   # as the result of the FrameChain.switch()
-            chain = FrameChain(_greenlet_execute)
-            return chain
-
-        def _bind(self):
-            state = self.costate
-            incoming_frame = yield_current_frame_to_caller()
-            self = state.current
-            return self._execute(incoming_frame)
-
-        def _execute(self, incoming_frame):
-            state = self.costate
-            try:
-                try:
-                    try:
-                        exc = None
-                        thunk = self.thunk
-                        self.thunk = None
-                        syncstate.switched(incoming_frame)
-                        thunk.call()
-                    except Exception, e:
-                        exc = e
-                        raise
-                finally:
-                    # warning! we must reload the 'self' from the costate,
-                    # because after a clone() the 'self' of both copies
-                    # point to the original!
-                    self = state.current
-                    self.finish(exc)
-            except CoroutineExit:
-                pass
-            except Exception, e:
-                if self.coroutine_exit is False:
-                    # redirect all unhandled exceptions to the parent
-                    syncstate.push_exception(e)
-
-            while self.parent is not None and self.parent.frame is None:
-                # greenlet behavior is fine
-                self.parent = self.parent.parent
-            return state.update(self.parent)
-
-        def switch(self):
-            if self.frame is None:
-                # considered a programming error.
-                # greenlets and tasklets have different ideas about this.
-                raise CoroutineDamage
-            state = self.costate
-            incoming_frame = state.update(self).switch()
-            syncstate.switched(incoming_frame)
-
-        def kill(self):
-            self._kill(CoroutineExit())
-
-        def _kill(self, exc):
-            if self.frame is None:
-                return
-            state = self.costate
-            syncstate.push_exception(exc)
-            # careful here - if setting self.parent to state.current would
-            # create a loop, break it.  The assumption is that 'self'
-            # will die, so that state.current's chain of parents can be
-            # modified to skip 'self' without too many people noticing.
-            p = state.current
-            if p is self or self.parent is None:
-                pass  # killing the current of the main - don't change any parent
-            else:
-                while p.parent is not None:
-                    if p.parent is self:
-                        p.parent = self.parent
-                        break
-                    p = p.parent
-                self.parent = state.current
-            self.switch()
-
-        def _kill_finally(self):
-            try:
-                self._userdel()
-            except Exception:
-                pass # maybe print a warning?
-            self.kill()
-
-        __already_postponed = False
-    
-        def __del__(self):
-            # provide the necessary clean-up
-            # note that AppCoroutine has to take care about this
-            # as well, including a check for user-supplied __del__.
-            # Additionally note that in the context of __del__, we are
-            # not in the position to issue a switch.
-            # we defer it completely.
-            
-            # it is necessary to check whether syncstate is None because CPython
-            # sets it to None when it cleans up the modules, which will lead to
-            # very strange effects
-
-            if not we_are_translated():
-                # we need to make sure that we postpone each coroutine only once on
-                # top of CPython, because this resurrects the coroutine and CPython
-                # calls __del__ again, thus postponing and resurrecting the
-                # coroutine once more :-(
-                if self.__already_postponed:
-                    return
-                self.__already_postponed = True
-            if syncstate is not None:
-                syncstate.postpone_deletion(self)
-
-        # coroutines need complete control over their __del__ behaviour. In
-        # particular they need to care about calling space.userdel themselves
-        handle_del_manually = True
-
-        def _userdel(self):
-            # override this for exposed coros
-            pass
-
-        def is_alive(self):
-            return self.frame is not None or self is self.costate.current
-
-        def is_zombie(self):
-            return self.frame is not None and syncstate.check_for_zombie(self)
-
-        def getcurrent():
-            costate = Coroutine._get_default_costate()
-            return costate.current
-        getcurrent = staticmethod(getcurrent)
-
-        def getmain():
-            costate = Coroutine._get_default_costate()
-            return costate.main
-        getmain = staticmethod(getmain)
-
-        def hello(self):
-            "Called when execution is transferred into this coroutine."
-
-        def goodbye(self):
-            "Called just after execution is transferred away from this coroutine."
-
-        def finish(self, exc=None):
-            "stephan forgot me"
-
-    return locals()
-
-# _________________________________________________
diff --git a/pypy/rlib/runicode.py b/pypy/rlib/runicode.py
--- a/pypy/rlib/runicode.py
+++ b/pypy/rlib/runicode.py
@@ -1403,7 +1403,7 @@
                                     s, pos, pos + unicode_bytes)
             result.append(res)
             continue
-        result.append(unichr(t))
+        result.append(UNICHR(t))
         pos += unicode_bytes
     return result.build(), pos
 
diff --git a/pypy/rlib/test/test_rcoroutine.py b/pypy/rlib/test/test_rcoroutine.py
deleted file mode 100644
--- a/pypy/rlib/test/test_rcoroutine.py
+++ /dev/null
@@ -1,348 +0,0 @@
-"""
-testing coroutines at interprepter level
-"""
-import py
-import os
-from pypy import conftest; conftest.translation_test_so_skip_if_appdirect()
-from pypy.rlib.rcoroutine import make_coroutine_classes
-from pypy.translator.c.test.test_stackless import StacklessTest
-from pypy.translator.c import gc
-
-def setup_module(mod):
-    py.test.importorskip('greenlet')
-
-d = make_coroutine_classes(object)
-syncstate = d['syncstate']
-Coroutine = d['Coroutine']
-AbstractThunk = d['AbstractThunk']
-
-def output(stuff):
-    os.write(2, stuff + '\n')
-
-class _TestCoroutine(StacklessTest):
-    backendopt = True
-    Coroutine = Coroutine
-
-    def setup_method(self, method):
-        syncstate.reset()
-
-    def _freeze_(self):    # for 'self.Coroutine'
-        return True
-
-    def test_coroutine1(self):
-
-        def g(lst, coros):
-            coro_f, coro_g, coro_h = coros
-            lst.append(2)
-            output('g appended 2')
-            coro_h.switch()
-            lst.append(5)
-            output('g appended 5')
-
-        def h(lst, coros):
-            coro_f, coro_g, coro_h = coros
-            lst.append(3)
-            output('h appended 3')
-            coro_f.switch()
-            lst.append(7)
-            output('h appended 7')
-
-        class T(AbstractThunk):
-            def __init__(self, func, arg1, arg2):
-                self.func = func
-                self.arg1 = arg1
-                self.arg2 = arg2
-            def call(self):
-                self.func(self.arg1, self.arg2)
-
-        def f():
-            lst = [1]
-            coro_f = Coroutine.getcurrent()
-            coro_g = self.Coroutine()
-            coro_h = self.Coroutine()
-            coros = [coro_f, coro_g, coro_h]
-            thunk_g = T(g, lst, coros)
-            output('binding g after f set 1')
-            coro_g.bind(thunk_g)
-            thunk_h = T(h, lst, coros)
-            output('binding h after f set 1')
-            coro_h.bind(thunk_h)
-            output('switching to g')
-            coro_g.switch()
-            lst.append(4)
-            output('f appended 4')
-            coro_g.switch()
-            lst.append(6)
-            output('f appended 6')
-            coro_h.switch()
-            lst.append(8)
-            output('f appended 8')
-            n = 0
-            for i in lst:
-                n = n*10 + i
-            return n
-
-        data = self.wrap_stackless_function(f)
-        assert data == 12345678
-
-    def test_coroutine2(self):
-
-        class TBase(AbstractThunk):
-            def call(self):
-                pass
-
-        class T(TBase):
-            def __init__(self, func, arg1, arg2):
-                self.func = func
-                self.arg1 = arg1
-                self.arg2 = arg2
-            def call(self):
-                self.res = self.func(self.arg1, self.arg2)
-
-        class T1(TBase):
-            def __init__(self, func, arg1):
-                self.func = func
-                self.arg1 = arg1
-            def call(self):
-                self.res = self.func(self.arg1)
-
-        def g(lst, coros):
-            coro_f1, coro_g, coro_h = coros
-            lst.append(2)
-            output('g appended 2')
-            coro_h.switch()
-            lst.append(5)
-            output('g appended 5')
-            output('exiting g')
-
-        def h(lst, coros):
-            coro_f1, coro_g, coro_h = coros
-            lst.append(3)
-            output('h appended 3')
-            coro_f1.switch()
-            lst.append(7)
-            output('h appended 7')
-            output('exiting h')
-
-        def f1(coro_f1):
-            lst = [1]
-            coro_g = self.Coroutine()
-            coro_g.__name__ = 'coro_g'
-            coro_h = self.Coroutine()
-            coro_h.__name__ = 'coro_h'
-            coros = [coro_f1, coro_g, coro_h]
-            thunk_g = T(g, lst, coros)
-            output('binding g after f1 set 1')
-            coro_g.bind(thunk_g)
-            thunk_h = T(h, lst, coros)
-            output('binding h after f1 set 1')
-            coro_h.bind(thunk_h)
-            output('switching to g')
-            coro_g.switch()
-            lst.append(4)
-            output('f1 appended 4')
-            coro_g.switch()
-            lst.append(6)
-            output('f1 appended 6')
-            coro_h.switch()
-            lst.append(8)
-            output('f1 appended 8')
-            n = 0
-            for i in lst:
-                n = n*10 + i
-            output('exiting f1')
-            return n     
-
-        def f():
-            coro_f = Coroutine.getcurrent()
-            coro_f.__name__ = 'coro_f'
-            coro_f1 = self.Coroutine()
-            coro_f1.__name__ = 'coro_f1'
-            thunk_f1 = T1(f1, coro_f1)
-            output('binding f1 after f set 1')
-            coro_f1.bind(thunk_f1)
-            coro_f1.switch()
-            output('return to main :-(')
-            return thunk_f1.res
-
-        data = self.wrap_stackless_function(f)
-        assert data == 12345678
-
-    def test_kill_raise_del_coro(self):
-        class T(AbstractThunk):
-            def __init__(self, func, arg):
-                self.func = func
-                self.arg = arg
-            def call(self):
-                self.func(self.arg, self)
-
-        def g(nrec, t, count=0):
-            t.count = count
-            if nrec < 0:
-                raise ValueError
-            if nrec:
-                g(nrec-1, t, count+1)
-            Coroutine.getmain().switch()
-
-        def f():
-            assert Coroutine.getmain().frame is None
-            coro_g = self.Coroutine()
-            coro_g.__name__ = 'coro_g'
-            thunk_g = T(g, 42)
-            coro_g.bind(thunk_g)
-            coro_g.switch()
-            res = thunk_g.count
-            res *= 10
-            res |= coro_g.frame is not None
-            # testing kill
-            coro_g.kill()
-            res *= 10
-            res |= coro_g.frame is None
-            coro_g = self.Coroutine()
-            # see what happens if we __del__
-            thunk_g = T(g, -42)
-            coro_g.bind(thunk_g)
-            try:
-                coro_g.switch()
-            except ValueError:
-                res += 500
-            return res
-
-        data = self.wrap_stackless_function(f)
-        assert data == 4711
-
-    def test_tree_compare(self):
-        class Node:
-            def __init__(self, value, left=None, right=None):
-                self.value = value
-                self.left = left
-                self.right = right
-            def __repr__(self):
-                return 'Node(%r, %r, %r)'%(self.value, self.left, self.right)
-
-        tree1 = Node(1, Node(2, Node(3)))
-        tree2 = Node(1, Node(3, Node(2)))
-        tree3 = Node(1, Node(2), Node(3))
-
-        class Producer(AbstractThunk):
-            def __init__(self, tree, objects, consumer):
-                self.tree = tree
-                self.objects = objects
-                self.consumer = consumer
-            def produce(self, t):
-                if t is None:
-                    return
-                self.objects.append(t.value)
-                self.consumer.switch()
-                self.produce(t.left)
-                self.produce(t.right)
-            def call(self):
-                self.produce(self.tree)
-                while 1:
-                    self.consumer.switch()
-        class Consumer(AbstractThunk):
-            def __init__(self, tree, objects, producer):
-                self.tree = tree
-                self.objects = objects
-                self.producer = producer
-            def consume(self, t):
-                if t is None:
-                    return True
-                self.producer.switch()
-                if not self.objects:
-                    return False
-                if self.objects.pop(0) != t.value:
-                    return False
-                if not self.consume(t.left):
-                    return False
-                return self.consume(t.right)
-
-            def call(self):
-                self.result = self.consume(self.tree)
-                Coroutine.getmain().switch()
-
-        def pre_order_eq(t1, t2):
-            objects = []
-            producer = self.Coroutine()
-            consumer = self.Coroutine()
-
-            producer.bind(Producer(t1, objects, consumer))
-            cons = Consumer(t2, objects, producer)
-            consumer.bind(cons)
-
-            consumer.switch()
-
-            return cons.result
-
-        def ep():
-            return int("%d%d%d%d"%(pre_order_eq(tree1, tree2),
-                                   pre_order_eq(tree1, tree1),
-                                   pre_order_eq(tree1, tree3),
-                                   pre_order_eq(tree2, tree1),
-                                   ))
-
-        output = self.wrap_stackless_function(ep)
-        assert output == int('0110')
-
-    def test_hello_goodbye(self):
-
-        class C(Coroutine):
-            n = 2
-            def __init__(self, n):
-                Coroutine.__init__(self)
-                self.n = n
-            def hello(self):
-                costate.hello_goodbye *= 10
-                costate.hello_goodbye += self.n
-            def goodbye(self):
-                costate.hello_goodbye *= 10
-                costate.hello_goodbye += self.n + 1
-
-        class T(AbstractThunk):
-            def call(self):
-                pass
-
-        costate = Coroutine._get_default_costate()
-        costate.current.__class__ = C
-        costate.hello_goodbye = 0
-
-        def ep():
-            syncstate.default_costate = costate
-            costate.hello_goodbye = 0
-            c1 = C(4)
-            c1.bind(T())
-            c1.switch()
-            return costate.hello_goodbye
-
-        output = self.wrap_stackless_function(ep)
-        # expected result:
-        #   goodbye main   3
-        #   hello   c1     4
-        #   goodbye c1     5
-        #   hello   main   2
-        assert output == 3452
-
-    def test_raise_propagate(self):
-        class T(AbstractThunk):
-            def call(self):
-                raise ValueError
-
-        def ep():
-            c = self.Coroutine()
-            c.bind(T())
-            try:
-                c.switch()
-            except ValueError:
-                return 100
-            else:
-                return -5
-
-        output = self.wrap_stackless_function(ep)
-        assert output == 100
-
-
-TestCoroutine = _TestCoroutine # to activate
-class TestCoroutineOnCPython(_TestCoroutine):
-    def wrap_stackless_function(self, func):
-        return func()
-
diff --git a/pypy/rpython/lltypesystem/ll2ctypes.py b/pypy/rpython/lltypesystem/ll2ctypes.py
--- a/pypy/rpython/lltypesystem/ll2ctypes.py
+++ b/pypy/rpython/lltypesystem/ll2ctypes.py
@@ -113,7 +113,7 @@
         rffi.LONGLONG:   ctypes.c_longlong,
         rffi.ULONGLONG:  ctypes.c_ulonglong,
         rffi.SIZE_T:     ctypes.c_size_t,
-        lltype.Bool:     ctypes.c_bool,
+        lltype.Bool:     getattr(ctypes, "c_bool", ctypes.c_long),
         llmemory.Address:  ctypes.c_void_p,
         llmemory.GCREF:    ctypes.c_void_p,
         llmemory.WeakRef:  ctypes.c_void_p, # XXX
@@ -1153,7 +1153,11 @@
         # an OverflowError on the following line.
         cvalue = ctypes.cast(ctypes.c_void_p(cvalue), cresulttype)
     else:
-        cvalue = cresulttype(cvalue).value   # mask high bits off if needed
+        try:
+            cvalue = cresulttype(cvalue).value   # mask high bits off if needed
+        except TypeError:
+            cvalue = int(cvalue)   # float -> int
+            cvalue = cresulttype(cvalue).value   # try again
     return ctypes2lltype(RESTYPE, cvalue)
 
 class ForceCastEntry(ExtRegistryEntry):
diff --git a/pypy/rpython/lltypesystem/lltype.py b/pypy/rpython/lltypesystem/lltype.py
--- a/pypy/rpython/lltypesystem/lltype.py
+++ b/pypy/rpython/lltypesystem/lltype.py
@@ -1283,6 +1283,8 @@
         try:
             return p._obj._hash_cache_
         except AttributeError:
+            assert self._T._gckind == 'gc'
+            assert self      # not for NULL
             result = hash(p._obj)
             if cache:
                 try:
diff --git a/pypy/rpython/lltypesystem/test/test_rffi.py b/pypy/rpython/lltypesystem/test/test_rffi.py
--- a/pypy/rpython/lltypesystem/test/test_rffi.py
+++ b/pypy/rpython/lltypesystem/test/test_rffi.py
@@ -699,7 +699,10 @@
     def test_cast(self):
         res = cast(SIZE_T, -1)
         assert type(res) is r_size_t
-        assert res == r_size_t(-1)    
+        assert res == r_size_t(-1)
+        #
+        res = cast(lltype.Signed, 42.5)
+        assert res == 42
     
     def test_rffi_sizeof(self):
         try:
diff --git a/pypy/rpython/memory/gc/minimark.py b/pypy/rpython/memory/gc/minimark.py
--- a/pypy/rpython/memory/gc/minimark.py
+++ b/pypy/rpython/memory/gc/minimark.py
@@ -1461,6 +1461,7 @@
         # We will fix such references to point to the copy of the young
         # objects when we walk 'old_objects_pointing_to_young'.
         self.old_objects_pointing_to_young.append(newobj)
+    _trace_drag_out._always_inline_ = True
 
     def _visit_young_rawmalloced_object(self, obj):
         # 'obj' points to a young, raw-malloced object.
diff --git a/pypy/rpython/memory/gctypelayout.py b/pypy/rpython/memory/gctypelayout.py
--- a/pypy/rpython/memory/gctypelayout.py
+++ b/pypy/rpython/memory/gctypelayout.py
@@ -459,7 +459,7 @@
             if t._hints.get('immutable'):
                 return
             if 'immutable_fields' in t._hints:
-                skip = t._hints['immutable_fields'].fields
+                skip = t._hints['immutable_fields'].all_immutable_fields()
         for n, t2 in t._flds.iteritems():
             if isinstance(t2, lltype.Ptr) and t2.TO._gckind == 'gc':
                 if n not in skip:
diff --git a/pypy/rpython/memory/test/test_gctypelayout.py b/pypy/rpython/memory/test/test_gctypelayout.py
--- a/pypy/rpython/memory/test/test_gctypelayout.py
+++ b/pypy/rpython/memory/test/test_gctypelayout.py
@@ -4,7 +4,7 @@
 from pypy.rpython.memory.gctypelayout import gc_pointers_inside
 from pypy.rpython.lltypesystem import lltype, llmemory, rclass
 from pypy.rpython.test.test_llinterp import get_interpreter
-from pypy.rpython.rclass import IR_IMMUTABLE
+from pypy.rpython.rclass import IR_IMMUTABLE, IR_QUASIIMMUTABLE
 from pypy.objspace.flow.model import Constant
 
 class FakeGC:
@@ -102,7 +102,7 @@
     accessor = rclass.FieldListAccessor()
     S3 = lltype.GcStruct('S', ('x', PT), ('y', PT),
                          hints={'immutable_fields': accessor})
-    accessor.initialize(S3, {'x': IR_IMMUTABLE})
+    accessor.initialize(S3, {'x': IR_IMMUTABLE, 'y': IR_QUASIIMMUTABLE})
     #
     s1 = lltype.malloc(S1)
     adr = llmemory.cast_ptr_to_adr(s1)
diff --git a/pypy/rpython/module/ll_os_stat.py b/pypy/rpython/module/ll_os_stat.py
--- a/pypy/rpython/module/ll_os_stat.py
+++ b/pypy/rpython/module/ll_os_stat.py
@@ -49,19 +49,8 @@
     ]
 N_INDEXABLE_FIELDS = 10
 
-# for now, check the host Python to know which st_xxx fields exist
-STAT_FIELDS = [(_name, _TYPE) for (_name, _TYPE) in ALL_STAT_FIELDS
-                              if hasattr(os.stat_result, _name)]
-
-STAT_FIELD_TYPES = dict(STAT_FIELDS)      # {'st_xxx': TYPE}
-
-STAT_FIELD_NAMES = [_name for (_name, _TYPE) in ALL_STAT_FIELDS
-                          if _name in STAT_FIELD_TYPES]
-
-del _name, _TYPE
-
 # For OO backends, expose only the portable fields (the first 10).
-PORTABLE_STAT_FIELDS = STAT_FIELDS[:N_INDEXABLE_FIELDS]
+PORTABLE_STAT_FIELDS = ALL_STAT_FIELDS[:N_INDEXABLE_FIELDS]
 
 # ____________________________________________________________
 #
@@ -142,17 +131,22 @@
     includes = INCLUDES
 )
 
-if sys.platform != 'win32':
+if TIMESPEC is not None:
+    class CConfig_for_timespec:
+        _compilation_info_ = compilation_info
+        TIMESPEC = TIMESPEC
+    TIMESPEC = lltype.Ptr(
+        platform.configure(CConfig_for_timespec)['TIMESPEC'])
+
+
+def posix_declaration(try_to_add=None):
+    global STAT_STRUCT
 
     LL_STAT_FIELDS = STAT_FIELDS[:]
+    if try_to_add:
+        LL_STAT_FIELDS.append(try_to_add)
 
     if TIMESPEC is not None:
-        class CConfig_for_timespec:
-            _compilation_info_ = compilation_info
-            TIMESPEC = TIMESPEC
-
-        TIMESPEC = lltype.Ptr(
-            platform.configure(CConfig_for_timespec)['TIMESPEC'])
 
         def _expand(lst, originalname, timespecname):
             for i, (_name, _TYPE) in enumerate(lst):
@@ -178,9 +172,34 @@
     class CConfig:
         _compilation_info_ = compilation_info
         STAT_STRUCT = platform.Struct('struct %s' % _name_struct_stat, LL_STAT_FIELDS)
-    config = platform.configure(CConfig)
+    try:
+        config = platform.configure(CConfig)
+    except platform.CompilationError:
+        if try_to_add:
+            return    # failed to add this field, give up
+        raise
 
     STAT_STRUCT = lltype.Ptr(config['STAT_STRUCT'])
+    if try_to_add:
+        STAT_FIELDS.append(try_to_add)
+
+
+# This lists only the fields that have been found on the underlying platform.
+# Initially only the PORTABLE_STAT_FIELDS, but more may be added by the
+# following loop.
+STAT_FIELDS = PORTABLE_STAT_FIELDS[:]
+
+if sys.platform != 'win32':
+    posix_declaration()
+    for _i in range(len(PORTABLE_STAT_FIELDS), len(ALL_STAT_FIELDS)):
+        posix_declaration(ALL_STAT_FIELDS[_i])
+    del _i
+
+# these two global vars only list the fields defined in the underlying platform
+STAT_FIELD_TYPES = dict(STAT_FIELDS)      # {'st_xxx': TYPE}
+STAT_FIELD_NAMES = [_name for (_name, _TYPE) in STAT_FIELDS]
+del _name, _TYPE
+
 
 def build_stat_result(st):
     # only for LL backends
diff --git a/pypy/rpython/module/test/test_ll_os_stat.py b/pypy/rpython/module/test/test_ll_os_stat.py
--- a/pypy/rpython/module/test/test_ll_os_stat.py
+++ b/pypy/rpython/module/test/test_ll_os_stat.py
@@ -2,6 +2,16 @@
 import sys, os
 import py
 
+
+class TestLinuxImplementation:
+    def setup_class(cls):
+        if not sys.platform.startswith('linux'):
+            py.test.skip("linux specific tests")
+
+    def test_has_all_fields(self):
+        assert ll_os_stat.STAT_FIELDS == ll_os_stat.ALL_STAT_FIELDS[:13]
+
+
 class TestWin32Implementation:
     def setup_class(cls):
         if sys.platform != 'win32':
diff --git a/pypy/rpython/rclass.py b/pypy/rpython/rclass.py
--- a/pypy/rpython/rclass.py
+++ b/pypy/rpython/rclass.py
@@ -16,6 +16,13 @@
         for x in fields.itervalues():
             assert isinstance(x, ImmutableRanking)
 
+    def all_immutable_fields(self):
+        result = set()
+        for key, value in self.fields.iteritems():
+            if value in (IR_IMMUTABLE, IR_IMMUTABLE_ARRAY):
+                result.add(key)
+        return result
+
     def __repr__(self):
         return '<FieldListAccessor for %s>' % getattr(self, 'TYPE', '?')
 
diff --git a/pypy/tool/jitlogparser/parser.py b/pypy/tool/jitlogparser/parser.py
--- a/pypy/tool/jitlogparser/parser.py
+++ b/pypy/tool/jitlogparser/parser.py
@@ -8,6 +8,7 @@
     bridge = None
     offset = None
     asm = None
+    failargs = ()
 
     def __init__(self, name, args, res, descr):
         self.name = name
@@ -18,8 +19,8 @@
         if self._is_guard:
             self.guard_no = int(self.descr[len('<Guard'):-1])
 
-    def setfailargs(self, _):
-        pass
+    def setfailargs(self, failargs):
+        self.failargs = failargs
 
     def getarg(self, i):
         return self._getvar(self.args[i])
diff --git a/pypy/tool/py.cleanup b/pypy/tool/py.cleanup
--- a/pypy/tool/py.cleanup
+++ b/pypy/tool/py.cleanup
@@ -1,16 +1,31 @@
 #!/usr/bin/env python
-import py, sys
+import sys, os, stat
 
-def shouldremove(p):
-    return p.ext == '.pyc'
+def clean(path):
+    global count
+    try:
+        content = os.listdir(path)
+    except OSError:
+        print >> sys.stderr, "skipping", path
+        return
+    for fn in content:
+        filename = os.path.join(path, fn)
+        st = os.lstat(filename)
+        if stat.S_ISDIR(st.st_mode):
+            clean(filename)
+            if fn == '__pycache__':
+                try:
+                    os.rmdir(filename)
+                except OSError:
+                    pass
+        elif fn.endswith('.pyc') or fn.endswith('.pyo'):
+            os.unlink(filename)
+            count += 1
 
 count = 0
 
 for arg in sys.argv[1:] or ['.']:
-    path = py.path.local(arg)
-    print "cleaning path", path, "of .pyc files"
-    for x in path.visit(shouldremove, lambda x: x.check(dotfile=0, link=0)):
-        x.remove()
-        count += 1
+    print "cleaning path", arg, "of .pyc/.pyo/__pycache__ files"
+    clean(arg)
 
 print "%d files removed" % (count,)
diff --git a/pypy/tool/release/package.py b/pypy/tool/release/package.py
--- a/pypy/tool/release/package.py
+++ b/pypy/tool/release/package.py
@@ -52,9 +52,14 @@
             pypy_c_dir = basedir.join('pypy', 'translator', 'goal')
         pypy_c = pypy_c_dir.join('pypy-c.exe')
         libpypy_c = pypy_c_dir.join('libpypy-c.dll')
+        libexpat = pypy_c_dir.join('libexpat.dll')
+        if not libexpat.check():
+            libexpat = py.path.local.sysfind('libexpat.dll')
+            assert libexpat, "libexpat.dll not found"
+            print "Picking %s" % libexpat
         binaries = [(pypy_c, pypy_c.basename),
                     (libpypy_c, libpypy_c.basename),
-                    (pypy_c_dir.join('libexpat.dll'), 'libexpat.dll')]
+                    (libexpat, libexpat.basename)]
     else:
         basename = 'pypy-c'
         if override_pypy_c is None:
diff --git a/pypy/translator/c/src/stacklet/stacklet.c b/pypy/translator/c/src/stacklet/stacklet.c
--- a/pypy/translator/c/src/stacklet/stacklet.c
+++ b/pypy/translator/c/src/stacklet/stacklet.c
@@ -319,10 +319,11 @@
 
 char **_stacklet_translate_pointer(stacklet_handle context, char **ptr)
 {
+  char *p = (char *)ptr;
+  long delta;
   if (context == NULL)
     return ptr;
-  char *p = (char *)ptr;
-  long delta = p - context->stack_start;
+  delta = p - context->stack_start;
   if (((unsigned long)delta) < ((unsigned long)context->stack_saved)) {
       /* a pointer to a saved away word */
       char *c = (char *)(context + 1);
diff --git a/pypy/translator/goal/app_main.py b/pypy/translator/goal/app_main.py
--- a/pypy/translator/goal/app_main.py
+++ b/pypy/translator/goal/app_main.py
@@ -260,6 +260,8 @@
     try:
         import _file
     except ImportError:
+        if sys.version_info < (2, 7):
+            return
         import ctypes # HACK: while running on top of CPython
         set_file_encoding = ctypes.pythonapi.PyFile_SetEncodingAndErrors
         set_file_encoding.argtypes = [ctypes.py_object, ctypes.c_char_p, ctypes.c_char_p]
@@ -479,7 +481,8 @@
             print >> sys.stderr, "'import site' failed"
 
     readenv = not ignore_environment
-    io_encoding = readenv and os.getenv("PYTHONIOENCODING")
+    io_encoding = ((readenv and os.getenv("PYTHONIOENCODING"))
+                   or sys.getfilesystemencoding())
     if io_encoding:
         set_io_encoding(io_encoding)
 
diff --git a/pypy/translator/goal/targetpreimportedpypy.py b/pypy/translator/goal/targetpreimportedpypy.py
deleted file mode 100644
--- a/pypy/translator/goal/targetpreimportedpypy.py
+++ /dev/null
@@ -1,239 +0,0 @@
-import py
-
-import os, sys
-sys.setrecursionlimit(17000)
-
-from pypy.interpreter import gateway
-from pypy.interpreter.error import OperationError
-from pypy.translator.goal.ann_override import PyPyAnnotatorPolicy
-from pypy.config.config import Config, to_optparse, make_dict, SUPPRESS_USAGE
-from pypy.config.config import ConflictConfigError
-from pypy.tool.option import make_objspace
-from pypy.translator.goal.nanos import setup_nanos
-
-EXTRA_MODULES = [
-    #"os",
-    #"decimal",
-    #"difflib",
-    #"tarfile",
-    #"cookielib",
-    #"optparse",
-    "inspect",
-    "random",
-]
-
-thisdir = py.path.local(__file__).dirpath()
-
-try:
-    this_dir = os.path.dirname(__file__)
-except NameError:
-    this_dir = os.path.dirname(sys.argv[0])
-
-def debug(msg):
-    os.write(2, "debug: " + msg + '\n')
-
-# __________  Entry point  __________
-
-def create_entry_point(space, w_dict):
-    w_entry_point = space.getitem(w_dict, space.wrap('entry_point'))
-    w_run_toplevel = space.getitem(w_dict, space.wrap('run_toplevel'))
-    w_call_finish_gateway = space.wrap(gateway.interp2app(call_finish))
-    w_call_startup_gateway = space.wrap(gateway.interp2app(call_startup))
-    w_os = setup_nanos(space)
-
-    def entry_point(argv):
-        space.timer.start("Entrypoint")
-        #debug("entry point starting") 
-        #for arg in argv: 
-        #    debug(" argv -> " + arg)
-        if len(argv) > 2 and argv[1] == '--heapsize':
-            # Undocumented option, handled at interp-level.
-            # It has silently no effect with some GCs.
-            # It works in Boehm and in the semispace or generational GCs
-            # (but see comments in semispace.py:set_max_heap_size()).
-            # At the moment this option exists mainly to support sandboxing.
-            from pypy.rlib import rgc
-            rgc.set_max_heap_size(int(argv[2]))
-            argv = argv[:1] + argv[3:]
-        try:
-            try:
-                space.timer.start("space.startup")
-                space.call_function(w_run_toplevel, w_call_startup_gateway)
-                space.timer.stop("space.startup")
-                w_executable = space.wrap(argv[0])
-                w_argv = space.newlist([space.wrap(s) for s in argv[1:]])
-                space.timer.start("w_entry_point")
-                w_exitcode = space.call_function(w_entry_point, w_executable, w_argv, w_os)
-                space.timer.stop("w_entry_point")
-                exitcode = space.int_w(w_exitcode)
-                # try to pull it all in
-            ##    from pypy.interpreter import main, interactive, error
-            ##    con = interactive.PyPyConsole(space)
-            ##    con.interact()
-            except OperationError, e:
-                debug("OperationError:")
-                debug(" operror-type: " + e.w_type.getname(space))
-                debug(" operror-value: " + space.str_w(space.str(e.get_w_value(space))))
-                return 1
-        finally:
-            try:
-                space.timer.start("space.finish")
-                space.call_function(w_run_toplevel, w_call_finish_gateway)
-                space.timer.stop("space.finish")
-            except OperationError, e:
-                debug("OperationError:")
-                debug(" operror-type: " + e.w_type.getname(space))
-                debug(" operror-value: " + space.str_w(space.str(e.get_w_value(space))))
-                return 1
-        space.timer.stop("Entrypoint")
-        space.timer.dump()
-        return exitcode
-    return entry_point
-
-def call_finish(space):


More information about the pypy-commit mailing list