[pypy-svn] pypy jitypes2: merge heads

antocuni commits-noreply at bitbucket.org
Wed Apr 13 18:31:23 CEST 2011


Author: Antonio Cuni <anto.cuni at gmail.com>
Branch: jitypes2
Changeset: r43331:6ebb73be4f72
Date: 2011-04-13 18:28 +0200
http://bitbucket.org/pypy/pypy/changeset/6ebb73be4f72/

Log:	merge heads

diff --git a/pypy/jit/metainterp/optimizeopt/string.py b/pypy/jit/metainterp/optimizeopt/string.py
--- a/pypy/jit/metainterp/optimizeopt/string.py
+++ b/pypy/jit/metainterp/optimizeopt/string.py
@@ -47,7 +47,7 @@
 class __extend__(optimizer.OptValue):
     """New methods added to the base class OptValue for this file."""
 
-    def getstrlen(self, newoperations, mode):
+    def getstrlen(self, optimization, mode):
         if mode is mode_string:
             s = self.get_constant_string_spec(mode_string)
             if s is not None:
@@ -56,12 +56,12 @@
             s = self.get_constant_string_spec(mode_unicode)
             if s is not None:
                 return ConstInt(len(s))
-        if newoperations is None:
+        if optimization is None:
             return None
         self.ensure_nonnull()
         box = self.force_box()
         lengthbox = BoxInt()
-        newoperations.append(ResOperation(mode.STRLEN, [box], lengthbox))
+        optimization.emit_operation(ResOperation(mode.STRLEN, [box], lengthbox))
         return lengthbox
 
     @specialize.arg(1)
@@ -72,13 +72,13 @@
         else:
             return None
 
-    def string_copy_parts(self, newoperations, targetbox, offsetbox, mode):
+    def string_copy_parts(self, optimization, targetbox, offsetbox, mode):
         # Copies the pointer-to-string 'self' into the target string
         # given by 'targetbox', at the specified offset.  Returns the offset
         # at the end of the copy.
-        lengthbox = self.getstrlen(newoperations, mode)
+        lengthbox = self.getstrlen(optimization, mode)
         srcbox = self.force_box()
-        return copy_str_content(newoperations, srcbox, targetbox,
+        return copy_str_content(optimization, srcbox, targetbox,
                                 CONST_0, offsetbox, lengthbox, mode)
 
 
@@ -105,13 +105,12 @@
                 return
         assert self.source_op is not None
         self.box = box = self.source_op.result
-        newoperations = self.optimizer.newoperations
-        lengthbox = self.getstrlen(newoperations, self.mode)
+        lengthbox = self.getstrlen(self.optimizer, self.mode)
         op = ResOperation(self.mode.NEWSTR, [lengthbox], box)
         if not we_are_translated():
             op.name = 'FORCE'
-        newoperations.append(op)
-        self.string_copy_parts(newoperations, box, CONST_0, self.mode)
+        self.optimizer.emit_operation(op)
+        self.string_copy_parts(self.optimizer, box, CONST_0, self.mode)
 
 
 class VStringPlainValue(VAbstractStringValue):
@@ -145,14 +144,14 @@
         return mode.emptystr.join([mode.chr(c.box.getint())
                                    for c in self._chars])
 
-    def string_copy_parts(self, newoperations, targetbox, offsetbox, mode):
+    def string_copy_parts(self, optimizer, targetbox, offsetbox, mode):
         for i in range(len(self._chars)):
             charbox = self._chars[i].force_box()
-            newoperations.append(ResOperation(mode.STRSETITEM, [targetbox,
+            optimizer.emit_operation(ResOperation(mode.STRSETITEM, [targetbox,
                                                                 offsetbox,
                                                                 charbox],
                                               None))
-            offsetbox = _int_add(newoperations, offsetbox, CONST_1)
+            offsetbox = _int_add(optimizer, offsetbox, CONST_1)
         return offsetbox
 
     def get_args_for_fail(self, modifier):
@@ -186,16 +185,16 @@
         self.left = left
         self.right = right
 
-    def getstrlen(self, newoperations, mode):
+    def getstrlen(self, optimizer, mode):
         if self.lengthbox is None:
-            len1box = self.left.getstrlen(newoperations, mode)
+            len1box = self.left.getstrlen(optimizer, mode)
             if len1box is None:
                 return None
-            len2box = self.right.getstrlen(newoperations, mode)
+            len2box = self.right.getstrlen(optimizer, mode)
             if len2box is None:
                 return None
-            self.lengthbox = _int_add(newoperations, len1box, len2box)
-            # ^^^ may still be None, if newoperations is None
+            self.lengthbox = _int_add(optimizer, len1box, len2box)
+            # ^^^ may still be None, if optimizer is None
         return self.lengthbox
 
     @specialize.arg(1)
@@ -208,10 +207,10 @@
             return None
         return s1 + s2
 
-    def string_copy_parts(self, newoperations, targetbox, offsetbox, mode):
-        offsetbox = self.left.string_copy_parts(newoperations, targetbox,
+    def string_copy_parts(self, optimizer, targetbox, offsetbox, mode):
+        offsetbox = self.left.string_copy_parts(optimizer, targetbox,
                                                 offsetbox, mode)
-        offsetbox = self.right.string_copy_parts(newoperations, targetbox,
+        offsetbox = self.right.string_copy_parts(optimizer, targetbox,
                                                  offsetbox, mode)
         return offsetbox
 
@@ -266,9 +265,9 @@
             return s1[start : start + length]
         return None
 
-    def string_copy_parts(self, newoperations, targetbox, offsetbox, mode):
-        lengthbox = self.getstrlen(newoperations, mode)
-        return copy_str_content(newoperations,
+    def string_copy_parts(self, optimizer, targetbox, offsetbox, mode):
+        lengthbox = self.getstrlen(optimizer, mode)
+        return copy_str_content(optimizer,
                                 self.vstr.force_box(), targetbox,
                                 self.vstart.force_box(), offsetbox,
                                 lengthbox, mode)
@@ -299,7 +298,7 @@
         return modifier.make_vstrslice(self.mode is mode_unicode)
 
 
-def copy_str_content(newoperations, srcbox, targetbox,
+def copy_str_content(optimizer, srcbox, targetbox,
                      srcoffsetbox, offsetbox, lengthbox, mode):
     if isinstance(srcbox, ConstPtr) and isinstance(srcoffsetbox, Const):
         M = 5
@@ -309,23 +308,23 @@
         # up to M characters are done "inline", i.e. with STRGETITEM/STRSETITEM
         # instead of just a COPYSTRCONTENT.
         for i in range(lengthbox.value):
-            charbox = _strgetitem(newoperations, srcbox, srcoffsetbox, mode)
-            srcoffsetbox = _int_add(newoperations, srcoffsetbox, CONST_1)
-            newoperations.append(ResOperation(mode.STRSETITEM, [targetbox,
+            charbox = _strgetitem(optimizer, srcbox, srcoffsetbox, mode)
+            srcoffsetbox = _int_add(optimizer, srcoffsetbox, CONST_1)
+            optimizer.emit_operation(ResOperation(mode.STRSETITEM, [targetbox,
                                                                 offsetbox,
                                                                 charbox],
                                               None))
-            offsetbox = _int_add(newoperations, offsetbox, CONST_1)
+            offsetbox = _int_add(optimizer, offsetbox, CONST_1)
     else:
-        nextoffsetbox = _int_add(newoperations, offsetbox, lengthbox)
+        nextoffsetbox = _int_add(optimizer, offsetbox, lengthbox)
         op = ResOperation(mode.COPYSTRCONTENT, [srcbox, targetbox,
                                                 srcoffsetbox, offsetbox,
                                                 lengthbox], None)
-        newoperations.append(op)
+        optimizer.emit_operation(op)
         offsetbox = nextoffsetbox
     return offsetbox
 
-def _int_add(newoperations, box1, box2):
+def _int_add(optimizer, box1, box2):
     if isinstance(box1, ConstInt):
         if box1.value == 0:
             return box2
@@ -333,23 +332,23 @@
             return ConstInt(box1.value + box2.value)
     elif isinstance(box2, ConstInt) and box2.value == 0:
         return box1
-    if newoperations is None:
+    if optimizer is None:
         return None
     resbox = BoxInt()
-    newoperations.append(ResOperation(rop.INT_ADD, [box1, box2], resbox))
+    optimizer.emit_operation(ResOperation(rop.INT_ADD, [box1, box2], resbox))
     return resbox
 
-def _int_sub(newoperations, box1, box2):
+def _int_sub(optimizer, box1, box2):
     if isinstance(box2, ConstInt):
         if box2.value == 0:
             return box1
         if isinstance(box1, ConstInt):
             return ConstInt(box1.value - box2.value)
     resbox = BoxInt()
-    newoperations.append(ResOperation(rop.INT_SUB, [box1, box2], resbox))
+    optimizer.emit_operation(ResOperation(rop.INT_SUB, [box1, box2], resbox))
     return resbox
 
-def _strgetitem(newoperations, strbox, indexbox, mode):
+def _strgetitem(optimizer, strbox, indexbox, mode):
     if isinstance(strbox, ConstPtr) and isinstance(indexbox, ConstInt):
         if mode is mode_string:
             s = strbox.getref(lltype.Ptr(rstr.STR))
@@ -358,7 +357,7 @@
             s = strbox.getref(lltype.Ptr(rstr.UNICODE))
             return ConstInt(ord(s.chars[indexbox.getint()]))
     resbox = BoxInt()
-    newoperations.append(ResOperation(mode.STRGETITEM, [strbox, indexbox],
+    optimizer.emit_operation(ResOperation(mode.STRGETITEM, [strbox, indexbox],
                                       resbox))
     return resbox
 
@@ -370,7 +369,7 @@
     def reconstruct_for_next_iteration(self, optimizer, valuemap):
         self.enabled = True
         return self
-    
+
     def make_vstring_plain(self, box, source_op, mode):
         vvalue = VStringPlainValue(self.optimizer, box, source_op, mode)
         self.make_equal_to(box, vvalue)
@@ -431,7 +430,7 @@
         value.ensure_nonnull()
         #
         if value.is_virtual() and isinstance(value, VStringSliceValue):
-            fullindexbox = _int_add(self.optimizer.newoperations,
+            fullindexbox = _int_add(self.optimizer,
                                     value.vstart.force_box(),
                                     vindex.force_box())
             value = value.vstr
@@ -441,7 +440,7 @@
             if vindex.is_constant():
                 return value.getitem(vindex.box.getint())
         #
-        resbox = _strgetitem(self.optimizer.newoperations,
+        resbox = _strgetitem(self.optimizer,
                              value.force_box(),vindex.force_box(), mode)
         return self.getvalue(resbox)
 
@@ -452,7 +451,7 @@
 
     def _optimize_STRLEN(self, op, mode):
         value = self.getvalue(op.getarg(0))
-        lengthbox = value.getstrlen(self.optimizer.newoperations, mode)
+        lengthbox = value.getstrlen(self, mode)
         self.make_equal_to(op.result, self.getvalue(lengthbox))
 
     def optimize_CALL(self, op):
@@ -498,13 +497,11 @@
         vright = self.getvalue(op.getarg(2))
         vleft.ensure_nonnull()
         vright.ensure_nonnull()
-        newoperations = self.optimizer.newoperations
         value = self.make_vstring_concat(op.result, op, mode)
         value.setup(vleft, vright)
         return True
 
     def opt_call_stroruni_STR_SLICE(self, op, mode):
-        newoperations = self.optimizer.newoperations
         vstr = self.getvalue(op.getarg(1))
         vstart = self.getvalue(op.getarg(2))
         vstop = self.getvalue(op.getarg(3))
@@ -518,14 +515,14 @@
             return True
         #
         vstr.ensure_nonnull()
-        lengthbox = _int_sub(newoperations, vstop.force_box(),
+        lengthbox = _int_sub(self.optimizer, vstop.force_box(),
                                             vstart.force_box())
         #
         if isinstance(vstr, VStringSliceValue):
             # double slicing  s[i:j][k:l]
             vintermediate = vstr
             vstr = vintermediate.vstr
-            startbox = _int_add(newoperations,
+            startbox = _int_add(self.optimizer,
                                 vintermediate.vstart.force_box(),
                                 vstart.force_box())
             vstart = self.getvalue(startbox)
@@ -574,7 +571,7 @@
         l2box = v2.getstrlen(None, mode)
         if isinstance(l2box, ConstInt):
             if l2box.value == 0:
-                lengthbox = v1.getstrlen(self.optimizer.newoperations, mode)
+                lengthbox = v1.getstrlen(self.optimizer, mode)
                 seo = self.optimizer.send_extra_operation
                 seo(ResOperation(rop.INT_EQ, [lengthbox, CONST_0], resultbox))
                 return True
@@ -609,7 +606,7 @@
             op = ResOperation(rop.PTR_EQ, [v1.force_box(),
                                            llhelper.CONST_NULL],
                               resultbox)
-            self.optimizer.newoperations.append(op)
+            self.optimizer.emit_operation(op)
             return True
         #
         return False
@@ -646,7 +643,7 @@
         calldescr, func = cic.callinfo_for_oopspec(oopspecindex)
         op = ResOperation(rop.CALL, [ConstInt(func)] + args, result,
                           descr=calldescr)
-        self.optimizer.newoperations.append(op)
+        self.optimizer.emit_operation(op)
 
     def propagate_forward(self, op):
         if not self.enabled:


diff --git a/pypy/jit/tl/pypyjit_child.py b/pypy/jit/tl/pypyjit_child.py
--- a/pypy/jit/tl/pypyjit_child.py
+++ b/pypy/jit/tl/pypyjit_child.py
@@ -2,7 +2,6 @@
 from pypy.rpython.lltypesystem import lltype
 from pypy.jit.metainterp import warmspot
 from pypy.module.pypyjit.policy import PyPyJitPolicy
-from pypy.rlib.jit import OPTIMIZER_FULL, OPTIMIZER_NO_UNROLL
 
 
 def run_child(glob, loc):
@@ -34,6 +33,5 @@
     option.view = True
     warmspot.jittify_and_run(interp, graph, [], policy=policy,
                              listops=True, CPUClass=CPUClass,
-                             backendopt=True, inline=True,
-                             optimizer=OPTIMIZER_FULL)
+                             backendopt=True, inline=True)
 

diff --git a/pypy/jit/metainterp/history.py b/pypy/jit/metainterp/history.py
--- a/pypy/jit/metainterp/history.py
+++ b/pypy/jit/metainterp/history.py
@@ -179,6 +179,9 @@
         """
         raise NotImplementedError
 
+    def count_fields_if_immutable(self):
+        return -1
+
     def _clone_if_mutable(self):
         return self
     def clone_if_mutable(self):

diff --git a/pypy/module/cpyext/include/abstract.h b/pypy/module/cpyext/include/abstract.h
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/include/abstract.h
@@ -0,0 +1,1 @@
+/* empty */

diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -108,6 +108,7 @@
     Anders Qvist
     Alan McIntyre
     Bert Freudenberg
+    Tav
 
     Heinrich-Heine University, Germany 
     Open End AB (formerly AB Strakt), Sweden
@@ -118,6 +119,9 @@
     Impara, Germany
     Change Maker, Sweden 
 
+The PyPy Logo as used by http://speed.pypy.org and others was created
+by Samuel Reis and is distributed on terms of Creative Commons Share Alike
+License.
  
 License for 'lib-python/2.5.2' and 'lib-python/2.5.2-modified'
 ============================================================== 

diff --git a/pypy/module/cpyext/pyerrors.py b/pypy/module/cpyext/pyerrors.py
--- a/pypy/module/cpyext/pyerrors.py
+++ b/pypy/module/cpyext/pyerrors.py
@@ -39,6 +39,10 @@
     state = space.fromcache(State)
     state.clear_exception()
 
+ at cpython_api([PyObject], PyObject)
+def PyExceptionInstance_Class(space, w_obj):
+    return space.type(w_obj)
+
 @cpython_api([PyObjectP, PyObjectP, PyObjectP], lltype.Void)
 def PyErr_Fetch(space, ptype, pvalue, ptraceback):
     """Retrieve the error indicator into three variables whose addresses are passed.
@@ -75,6 +79,9 @@
     error indicator temporarily; use PyErr_Fetch() to save the current
     exception state."""
     state = space.fromcache(State)
+    if w_type is None:
+        state.clear_exception()
+        return
     state.set_exception(OperationError(w_type, w_value))
     Py_DecRef(space, w_type)
     Py_DecRef(space, w_value)
@@ -300,3 +307,11 @@
     operror = state.clear_exception()
     if operror:
         operror.write_unraisable(space, space.str_w(space.repr(w_where)))
+
+ at cpython_api([], lltype.Void)
+def PyErr_SetInterrupt(space):
+    """This function simulates the effect of a SIGINT signal arriving --- the
+    next time PyErr_CheckSignals() is called, KeyboardInterrupt will be raised.
+    It may be called without holding the interpreter lock."""
+    space.check_signal_action.set_interrupt()
+

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
@@ -91,19 +91,22 @@
 class AppTestDistributedTasklets(object):
     spaceconfig = {"objspace.std.withtproxy": True,
                    "objspace.usemodules._stackless": 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,)
         """)
-        cls.reclimit = sys.getrecursionlimit()
         sys.setrecursionlimit(100000)
 
     def teardown_class(cls):
         sys.setrecursionlimit(cls.reclimit)
-    
+
     def test_remote_protocol_call(self):
         def f(x, y):
             return x + y

diff --git a/pypy/interpreter/typedef.py b/pypy/interpreter/typedef.py
--- a/pypy/interpreter/typedef.py
+++ b/pypy/interpreter/typedef.py
@@ -103,6 +103,7 @@
     except KeyError:
         subcls = _getusercls(config, cls, hasdict, wants_slots, needsdel,
                              weakrefable)
+        assert key not in _subclass_cache
         _subclass_cache[key] = subcls
         return subcls
 get_unique_interplevel_subclass._annspecialcase_ = "specialize:memo"

diff --git a/pypy/module/sys/interp_encoding.py b/pypy/module/sys/interp_encoding.py
--- a/pypy/module/sys/interp_encoding.py
+++ b/pypy/module/sys/interp_encoding.py
@@ -37,6 +37,10 @@
     base_encoding = None
 
 def _getfilesystemencoding(space):
+    if (space.config.translation.type_system == 'ootype'):
+        # XXX: fix this for ootype
+        return base_encoding
+    #
     encoding = base_encoding
     if rlocale.HAVE_LANGINFO and rlocale.CODESET:
         oldlocale = rlocale.setlocale(rlocale.LC_CTYPE, None)

diff --git a/pypy/translator/jvm/database.py b/pypy/translator/jvm/database.py
--- a/pypy/translator/jvm/database.py
+++ b/pypy/translator/jvm/database.py
@@ -4,7 +4,7 @@
 """
 
 from cStringIO import StringIO
-from pypy.rpython.lltypesystem import lltype
+from pypy.rpython.lltypesystem import lltype, rffi
 from pypy.rpython.ootypesystem import ootype, rclass
 from pypy.rpython.ootypesystem.module import ll_os
 from pypy.translator.jvm import node, methods
@@ -229,9 +229,15 @@
                 if not ootype.isSubclass(OOTYPE, SELF): continue
                 mobj = self._function_for_graph(
                     clsobj, mname, False, mimpl.graph)
-                graphs = OOTYPE._lookup_graphs(mname)
-                if len(graphs) == 1:
-                    mobj.is_final = True
+                # XXX: this logic is broken: it might happen that there are
+                # ootype.Instance which contains a meth whose graph is exactly
+                # the same as the meth in the superclass: in this case,
+                # len(graphs) == 1 but we cannot just mark the method as final
+                # (or we can, but we should avoid to emit the method in the
+                # subclass, then)
+                ## graphs = OOTYPE._lookup_graphs(mname)
+                ## if len(graphs) == 1:
+                ##     mobj.is_final = True
                 clsobj.add_method(mobj)
 
         # currently, we always include a special "dump" method for debugging
@@ -359,6 +365,7 @@
         ootype.UniChar:jvm.PYPYESCAPEDUNICHAR,
         ootype.String:jvm.PYPYESCAPEDSTRING,
         ootype.Unicode:jvm.PYPYESCAPEDUNICODE,
+        rffi.SHORT:jvm.SHORTTOSTRINGS,
         }
 
     def toString_method_for_ootype(self, OOTYPE):
@@ -406,6 +413,7 @@
         ootype.UniChar:          jvm.jChar,
         ootype.Class:            jvm.jClass,
         ootype.ROOT:             jvm.jObject,  # treat like a scalar
+        rffi.SHORT:              jvm.jShort,
     }
 
     # Dictionary for non-scalar types; in this case, if we see the key, we

diff --git a/pypy/jit/backend/model.py b/pypy/jit/backend/model.py
--- a/pypy/jit/backend/model.py
+++ b/pypy/jit/backend/model.py
@@ -23,18 +23,22 @@
         self.fail_descr_list = []
         self.fail_descr_free_list = []
 
+    def reserve_some_free_fail_descr_number(self):
+        lst = self.fail_descr_list
+        if len(self.fail_descr_free_list) > 0:
+            n = self.fail_descr_free_list.pop()
+            assert lst[n] is None
+        else:
+            n = len(lst)
+            lst.append(None)
+        return n
+
     def get_fail_descr_number(self, descr):
         assert isinstance(descr, history.AbstractFailDescr)
         n = descr.index
         if n < 0:
-            lst = self.fail_descr_list
-            if len(self.fail_descr_free_list) > 0:
-                n = self.fail_descr_free_list.pop()
-                assert lst[n] is None
-                lst[n] = descr
-            else:
-                n = len(lst)
-                lst.append(descr)
+            n = self.reserve_some_free_fail_descr_number()
+            self.fail_descr_list[n] = descr
             descr.index = n
         return n
 
@@ -294,6 +298,13 @@
     def record_faildescr_index(self, n):
         self.faildescr_indices.append(n)
 
+    def reserve_and_record_some_faildescr_index(self):
+        # like record_faildescr_index(), but invent and return a new,
+        # unused faildescr index
+        n = self.cpu.reserve_some_free_fail_descr_number()
+        self.record_faildescr_index(n)
+        return n
+
     def compiling_a_bridge(self):
         self.cpu.total_compiled_bridges += 1
         self.bridges_count += 1

diff --git a/lib-python/TODO b/lib-python/TODO
--- a/lib-python/TODO
+++ b/lib-python/TODO
@@ -2,7 +2,7 @@
 ===================
 
 You can find the results of the most recent buildbot run at:
-http://buildbot.pypy.org/summary?branch=fast-forward
+http://buildbot.pypy.org/
 
 
 Probably easy tasks
@@ -39,18 +39,8 @@
 Medium tasks
 ------------
 
-- Ast objects should be picklable, see in pypy/module/_ast/test/test_ast.py:
-  test_pickle()
-
 - socket module has a couple of changes (including AF_TIPC packet range)
 
-- (test_lib2to3) When a "for" loop runs a generator function, if the loop is
-  exited before the end, the "finally" clause of the generator is not called
-  until the next gc collection.  In our case, in lib2to3/pytree.py,
-  WildcardPattern.match_seq() does not exhaust the generate_matches() generator,
-  and stderr is not restored.
-
-
 Longer tasks
 ------------
 

diff --git a/pypy/module/imp/test/test_import.py b/pypy/module/imp/test/test_import.py
--- a/pypy/module/imp/test/test_import.py
+++ b/pypy/module/imp/test/test_import.py
@@ -6,6 +6,7 @@
 from pypy.tool.udir import udir
 from pypy.rlib import streamio
 from pypy.conftest import gettestobjspace
+import pytest
 import sys, os
 import tempfile, marshal
 
@@ -109,6 +110,14 @@
             p.join('lone.pyc').write(p.join('x.pyc').read(mode='rb'),
                                      mode='wb')
 
+    # create a .pyw file
+    p = setuppkg("windows", x = "x = 78")
+    try:
+        p.join('x.pyw').remove()
+    except py.error.ENOENT:
+        pass
+    p.join('x.py').rename(p.join('x.pyw'))
+
     return str(root)
 
 
@@ -177,6 +186,14 @@
         import a
         assert a == a0
 
+    def test_trailing_slash(self):
+        import sys
+        try:
+            sys.path[0] += '/'
+            import a
+        finally:
+            sys.path[0] = sys.path[0].rstrip('/')
+
     def test_import_pkg(self):
         import sys
         import pkg
@@ -325,6 +342,11 @@
         import compiled.x
         assert compiled.x == sys.modules.get('compiled.x')
 
+    @pytest.mark.skipif("sys.platform != 'win32'")
+    def test_pyw(self):
+        import windows.x
+        assert windows.x.__file__.endswith('x.pyw')
+
     def test_cannot_write_pyc(self):
         import sys, os
         p = os.path.join(sys.path[-1], 'readonly')
@@ -985,7 +1007,8 @@
 
 class AppTestPyPyExtension(object):
     def setup_class(cls):
-        cls.space = gettestobjspace(usemodules=['imp', 'zipimport'])
+        cls.space = gettestobjspace(usemodules=['imp', 'zipimport',
+                                                '__pypy__'])
         cls.w_udir = cls.space.wrap(str(udir))
 
     def test_run_compiled_module(self):

diff --git a/lib_pypy/pyrepl/unicodedata_.py b/lib_pypy/pyrepl/unicodedata_.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/unicodedata_.py
@@ -0,0 +1,59 @@
+try:
+    from unicodedata import *
+except ImportError:
+
+    def category(ch):
+        """
+        ASCII only implementation
+        """
+        if type(ch) is not unicode:
+            raise TypeError
+        if len(ch) != 1:
+            raise TypeError
+        return _categories.get(ord(ch), 'Co') # "Other, private use"
+
+    _categories = {
+        0: 'Cc', 1: 'Cc', 2: 'Cc', 3: 'Cc', 4: 'Cc', 5: 'Cc',
+        6: 'Cc', 7: 'Cc', 8: 'Cc', 9: 'Cc', 10: 'Cc', 11: 'Cc',
+        12: 'Cc', 13: 'Cc', 14: 'Cc', 15: 'Cc', 16: 'Cc', 17: 'Cc',
+        18: 'Cc', 19: 'Cc', 20: 'Cc', 21: 'Cc', 22: 'Cc', 23: 'Cc',
+        24: 'Cc', 25: 'Cc', 26: 'Cc', 27: 'Cc', 28: 'Cc', 29: 'Cc',
+        30: 'Cc', 31: 'Cc', 32: 'Zs', 33: 'Po', 34: 'Po', 35: 'Po',
+        36: 'Sc', 37: 'Po', 38: 'Po', 39: 'Po', 40: 'Ps', 41: 'Pe',
+        42: 'Po', 43: 'Sm', 44: 'Po', 45: 'Pd', 46: 'Po', 47: 'Po',
+        48: 'Nd', 49: 'Nd', 50: 'Nd', 51: 'Nd', 52: 'Nd', 53: 'Nd',
+        54: 'Nd', 55: 'Nd', 56: 'Nd', 57: 'Nd', 58: 'Po', 59: 'Po',
+        60: 'Sm', 61: 'Sm', 62: 'Sm', 63: 'Po', 64: 'Po', 65: 'Lu',
+        66: 'Lu', 67: 'Lu', 68: 'Lu', 69: 'Lu', 70: 'Lu', 71: 'Lu',
+        72: 'Lu', 73: 'Lu', 74: 'Lu', 75: 'Lu', 76: 'Lu', 77: 'Lu',
+        78: 'Lu', 79: 'Lu', 80: 'Lu', 81: 'Lu', 82: 'Lu', 83: 'Lu',
+        84: 'Lu', 85: 'Lu', 86: 'Lu', 87: 'Lu', 88: 'Lu', 89: 'Lu',
+        90: 'Lu', 91: 'Ps', 92: 'Po', 93: 'Pe', 94: 'Sk', 95: 'Pc',
+        96: 'Sk', 97: 'Ll', 98: 'Ll', 99: 'Ll', 100: 'Ll', 101: 'Ll',
+        102: 'Ll', 103: 'Ll', 104: 'Ll', 105: 'Ll', 106: 'Ll', 107: 'Ll',
+        108: 'Ll', 109: 'Ll', 110: 'Ll', 111: 'Ll', 112: 'Ll', 113: 'Ll',
+        114: 'Ll', 115: 'Ll', 116: 'Ll', 117: 'Ll', 118: 'Ll', 119: 'Ll',
+        120: 'Ll', 121: 'Ll', 122: 'Ll', 123: 'Ps', 124: 'Sm', 125: 'Pe',
+        126: 'Sm', 127: 'Cc', 128: 'Cc', 129: 'Cc', 130: 'Cc', 131: 'Cc',
+        132: 'Cc', 133: 'Cc', 134: 'Cc', 135: 'Cc', 136: 'Cc', 137: 'Cc',
+        138: 'Cc', 139: 'Cc', 140: 'Cc', 141: 'Cc', 142: 'Cc', 143: 'Cc',
+        144: 'Cc', 145: 'Cc', 146: 'Cc', 147: 'Cc', 148: 'Cc', 149: 'Cc',
+        150: 'Cc', 151: 'Cc', 152: 'Cc', 153: 'Cc', 154: 'Cc', 155: 'Cc',
+        156: 'Cc', 157: 'Cc', 158: 'Cc', 159: 'Cc', 160: 'Zs', 161: 'Po',
+        162: 'Sc', 163: 'Sc', 164: 'Sc', 165: 'Sc', 166: 'So', 167: 'So',
+        168: 'Sk', 169: 'So', 170: 'Ll', 171: 'Pi', 172: 'Sm', 173: 'Cf',
+        174: 'So', 175: 'Sk', 176: 'So', 177: 'Sm', 178: 'No', 179: 'No',
+        180: 'Sk', 181: 'Ll', 182: 'So', 183: 'Po', 184: 'Sk', 185: 'No',
+        186: 'Ll', 187: 'Pf', 188: 'No', 189: 'No', 190: 'No', 191: 'Po',
+        192: 'Lu', 193: 'Lu', 194: 'Lu', 195: 'Lu', 196: 'Lu', 197: 'Lu',
+        198: 'Lu', 199: 'Lu', 200: 'Lu', 201: 'Lu', 202: 'Lu', 203: 'Lu',
+        204: 'Lu', 205: 'Lu', 206: 'Lu', 207: 'Lu', 208: 'Lu', 209: 'Lu',
+        210: 'Lu', 211: 'Lu', 212: 'Lu', 213: 'Lu', 214: 'Lu', 215: 'Sm',
+        216: 'Lu', 217: 'Lu', 218: 'Lu', 219: 'Lu', 220: 'Lu', 221: 'Lu',
+        222: 'Lu', 223: 'Ll', 224: 'Ll', 225: 'Ll', 226: 'Ll', 227: 'Ll',
+        228: 'Ll', 229: 'Ll', 230: 'Ll', 231: 'Ll', 232: 'Ll', 233: 'Ll',
+        234: 'Ll', 235: 'Ll', 236: 'Ll', 237: 'Ll', 238: 'Ll', 239: 'Ll',
+        240: 'Ll', 241: 'Ll', 242: 'Ll', 243: 'Ll', 244: 'Ll', 245: 'Ll',
+        246: 'Ll', 247: 'Sm', 248: 'Ll', 249: 'Ll', 250: 'Ll', 251: 'Ll',
+        252: 'Ll', 253: 'Ll', 254: 'Ll'
+        }

diff --git a/pypy/rlib/jit.py b/pypy/rlib/jit.py
--- a/pypy/rlib/jit.py
+++ b/pypy/rlib/jit.py
@@ -457,6 +457,12 @@
             args_s.append(s_arg)
         bk.emulate_pbc_call(uniquekey, s_func, args_s)
 
+    def get_getfield_op(self, rtyper):
+        if rtyper.type_system.name == 'ootypesystem':
+            return 'oogetfield'
+        else:
+            return 'getfield'
+
     def specialize_call(self, hop, **kwds_i):
         # XXX to be complete, this could also check that the concretetype
         # of the variables are the same for each of the calls.
@@ -471,8 +477,8 @@
                 r_green = hop.args_r[i]
                 v_green = hop.inputarg(r_green, arg=i)
             else:
-                if hop.rtyper.type_system.name == 'ootypesystem':
-                    py.test.skip("lltype only")
+                #if hop.rtyper.type_system.name == 'ootypesystem':
+                    #py.test.skip("lltype only")
                 objname, fieldname = name.split('.')   # see test_green_field
                 assert objname in driver.reds
                 i = kwds_i['i_' + objname]
@@ -488,7 +494,10 @@
                         "field %r not found in %r" % (name,
                                                       r_red.lowleveltype.TO))
                     r_red = r_red.rbase
-                GTYPE = r_red.lowleveltype.TO
+                if hop.rtyper.type_system.name == 'ootypesystem':
+                    GTYPE = r_red.lowleveltype
+                else:
+                    GTYPE = r_red.lowleveltype.TO
                 assert GTYPE._immutable_field(mangled_name), (
                     "field %r must be declared as immutable" % name)
                 if not hasattr(driver, 'll_greenfields'):
@@ -497,7 +506,8 @@
                 #
                 v_red = hop.inputarg(r_red, arg=i)
                 c_llname = hop.inputconst(lltype.Void, mangled_name)
-                v_green = hop.genop('getfield', [v_red, c_llname],
+                getfield_op = self.get_getfield_op(hop.rtyper)
+                v_green = hop.genop(getfield_op, [v_red, c_llname],
                                     resulttype = r_field)
                 s_green = s_red.classdef.about_attribute(fieldname)
                 assert s_green is not None

diff --git a/lib_pypy/pyrepl/keymaps.py b/lib_pypy/pyrepl/keymaps.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/keymaps.py
@@ -0,0 +1,140 @@
+#   Copyright 2000-2004 Michael Hudson-Doyle <micahel at gmail.com>
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+reader_emacs_keymap = tuple(
+    [(r'\C-a', 'beginning-of-line'),
+     (r'\C-b', 'left'),
+     (r'\C-c', 'interrupt'),
+     (r'\C-d', 'delete'),
+     (r'\C-e', 'end-of-line'),
+     (r'\C-f', 'right'),
+     (r'\C-g', 'cancel'),
+     (r'\C-h', 'backspace'),
+     (r'\C-j', 'self-insert'),
+     (r'\<return>', 'accept'),
+     (r'\C-k', 'kill-line'),
+     (r'\C-l', 'clear-screen'),
+#     (r'\C-m', 'accept'),
+     (r'\C-q', 'quoted-insert'),
+     (r'\C-t', 'transpose-characters'),
+     (r'\C-u', 'unix-line-discard'),
+     (r'\C-v', 'quoted-insert'),
+     (r'\C-w', 'unix-word-rubout'),
+     (r'\C-x\C-u', 'upcase-region'),
+     (r'\C-y', 'yank'),
+     (r'\C-z', 'suspend'),
+     
+     (r'\M-b', 'backward-word'),
+     (r'\M-c', 'capitalize-word'),
+     (r'\M-d', 'kill-word'),
+     (r'\M-f', 'forward-word'),
+     (r'\M-l', 'downcase-word'),
+     (r'\M-t', 'transpose-words'),
+     (r'\M-u', 'upcase-word'),
+     (r'\M-y', 'yank-pop'),
+     (r'\M--', 'digit-arg'),
+     (r'\M-0', 'digit-arg'),
+     (r'\M-1', 'digit-arg'),
+     (r'\M-2', 'digit-arg'),
+     (r'\M-3', 'digit-arg'),
+     (r'\M-4', 'digit-arg'),
+     (r'\M-5', 'digit-arg'),
+     (r'\M-6', 'digit-arg'),
+     (r'\M-7', 'digit-arg'),
+     (r'\M-8', 'digit-arg'),
+     (r'\M-9', 'digit-arg'),
+     (r'\M-\n', 'self-insert'),
+     (r'\<backslash>', 'self-insert')] + \
+    [(c, 'self-insert')
+     for c in map(chr, range(32, 127)) if c <> '\\'] + \
+    [(c, 'self-insert')
+     for c in map(chr, range(128, 256)) if c.isalpha()] + \
+    [(r'\<up>', 'up'),
+     (r'\<down>', 'down'),
+     (r'\<left>', 'left'),
+     (r'\<right>', 'right'),
+     (r'\<insert>', 'quoted-insert'),
+     (r'\<delete>', 'delete'),
+     (r'\<backspace>', 'backspace'),
+     (r'\M-\<backspace>', 'backward-kill-word'),
+     (r'\<end>', 'end'),
+     (r'\<home>', 'home'),
+     (r'\<f1>', 'help'),
+     (r'\EOF', 'end'),  # the entries in the terminfo database for xterms
+     (r'\EOH', 'home'), # seem to be wrong.  this is a less than ideal
+                        # workaround
+     ])
+
+hist_emacs_keymap = reader_emacs_keymap + (
+    (r'\C-n', 'next-history'),
+    (r'\C-p', 'previous-history'),
+    (r'\C-o', 'operate-and-get-next'),
+    (r'\C-r', 'reverse-history-isearch'),
+    (r'\C-s', 'forward-history-isearch'),
+    (r'\M-r', 'restore-history'),
+    (r'\M-.', 'yank-arg'),
+    (r'\<page down>', 'last-history'),
+    (r'\<page up>', 'first-history'))
+
+comp_emacs_keymap = hist_emacs_keymap + (
+    (r'\t', 'complete'),)
+
+python_emacs_keymap = comp_emacs_keymap + (
+    (r'\n', 'maybe-accept'),
+    (r'\M-\n', 'self-insert'))
+    
+reader_vi_insert_keymap = tuple(
+    [(c, 'self-insert')
+     for c in map(chr, range(32, 127)) if c <> '\\'] + \
+    [(c, 'self-insert')
+     for c in map(chr, range(128, 256)) if c.isalpha()] + \
+    [(r'\C-d', 'delete'),
+     (r'\<backspace>', 'backspace'),
+     ('')])
+
+reader_vi_command_keymap = tuple(
+    [
+    ('E', 'enter-emacs-mode'),
+    ('R', 'enter-replace-mode'),
+    ('dw', 'delete-word'),
+    ('dd', 'delete-line'),
+    
+    ('h', 'left'),
+    ('i', 'enter-insert-mode'),
+    ('j', 'down'),
+    ('k', 'up'),
+    ('l', 'right'),
+    ('r', 'replace-char'),
+    ('w', 'forward-word'),
+    ('x', 'delete'),
+    ('.', 'repeat-edit'), # argh!
+    (r'\<insert>', 'enter-insert-mode'),
+     ] + 
+    [(c, 'digit-arg') for c in '01234567689'] +
+    [])
+   
+
+reader_keymaps = {
+    'emacs' : reader_emacs_keymap,
+    'vi-insert' : reader_vi_insert_keymap,
+    'vi-command' : reader_vi_command_keymap
+    }
+
+del c # from the listcomps
+

diff --git a/pypy/jit/metainterp/test/test_dict.py b/pypy/jit/metainterp/test/test_dict.py
--- a/pypy/jit/metainterp/test/test_dict.py
+++ b/pypy/jit/metainterp/test/test_dict.py
@@ -1,6 +1,7 @@
 import py
 from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
 from pypy.rlib.jit import JitDriver
+from pypy.rlib import objectmodel
 
 class DictTests:
 
@@ -69,6 +70,66 @@
             res = self.meta_interp(f, [10], listops=True)
             assert res == expected
 
+    def test_dict_trace_hash(self):
+        myjitdriver = JitDriver(greens = [], reds = ['total', 'dct'])
+        def key(x):
+            return x % 2
+        def eq(x, y):
+            return (x % 2) == (y % 2)
+
+        def f(n):
+            dct = objectmodel.r_dict(eq, key)
+            total = n
+            while total:
+                myjitdriver.jit_merge_point(total=total, dct=dct)
+                if total not in dct:
+                    dct[total] = []
+                dct[total].append(total)
+                total -= 1
+            return len(dct[0])
+
+        res1 = f(100)
+        res2 = self.meta_interp(f, [100], listops=True)
+        assert res1 == res2
+        self.check_loops(int_mod=1) # the hash was traced
+
+    def test_dict_setdefault(self):
+        myjitdriver = JitDriver(greens = [], reds = ['total', 'dct'])
+        def f(n):
+            dct = {}
+            total = n
+            while total:
+                myjitdriver.jit_merge_point(total=total, dct=dct)
+                dct.setdefault(total % 2, []).append(total)
+                total -= 1
+            return len(dct[0])
+
+        assert f(100) == 50
+        res = self.meta_interp(f, [100], listops=True)
+        assert res == 50
+        self.check_loops(new=0, new_with_vtable=0)
+
+    def test_dict_as_counter(self):
+        myjitdriver = JitDriver(greens = [], reds = ['total', 'dct'])
+        def key(x):
+            return x % 2
+        def eq(x, y):
+            return (x % 2) == (y % 2)
+
+        def f(n):
+            dct = objectmodel.r_dict(eq, key)
+            total = n
+            while total:
+                myjitdriver.jit_merge_point(total=total, dct=dct)
+                dct[total] = dct.get(total, 0) + 1
+                total -= 1
+            return dct[0]
+
+        assert f(100) == 50
+        res = self.meta_interp(f, [100], listops=True)
+        assert res == 50
+        self.check_loops(int_mod=1)
+
 
 class TestOOtype(DictTests, OOJitMixin):
     pass

diff --git a/pypy/rpython/memory/test/test_transformed_gc.py b/pypy/rpython/memory/test/test_transformed_gc.py
--- a/pypy/rpython/memory/test/test_transformed_gc.py
+++ b/pypy/rpython/memory/test/test_transformed_gc.py
@@ -13,7 +13,6 @@
 from pypy.rlib import rgc
 from pypy import conftest
 from pypy.rlib.rstring import StringBuilder
-from pypy.rlib.objectmodel import keepalive_until_here
 from pypy.rlib.rarithmetic import LONG_BIT
 
 WORD = LONG_BIT // 8

diff --git a/pypy/translator/backendopt/test/test_support.py b/pypy/translator/backendopt/test/test_support.py
--- a/pypy/translator/backendopt/test/test_support.py
+++ b/pypy/translator/backendopt/test/test_support.py
@@ -1,94 +1,7 @@
-from pypy.translator.unsimplify import varoftype
 from pypy.translator.translator import TranslationContext, graphof
 from pypy.translator.backendopt.support import \
-     needs_conservative_livevar_calculation, split_block_with_keepalive, \
      find_loop_blocks, find_backedges, compute_reachability
 
-from pypy.rpython.rtyper import LowLevelOpList
-from pypy.rpython.lltypesystem import lltype
-from pypy.objspace.flow import model
-
-NonGcB = lltype.Struct("B", ('x', lltype.Signed))
-GcA = lltype.GcStruct("A", ('b', NonGcB), ('c', lltype.Ptr(lltype.FuncType([], lltype.Void))))
-
-def test_nclc_should_be_true():
-    # this is testing a block like:
-    # +--- inputargs: pointer_to_gc
-    # | v0 <- op_getsubstruct pointer_to_gc 'b'
-    # +--- exitargs: v0 (i.e. pointer to non-gc)
-    llops = LowLevelOpList()
-    ptr_a = varoftype(lltype.Ptr(GcA))
-    v_res = llops.genop("getsubstruct", [ptr_a, model.Constant('b', lltype.Void)],
-                        resulttype=lltype.Ptr(NonGcB))
-    block = model.Block([ptr_a])
-    block.operations.extend(llops)
-    block.closeblock(model.Link([v_res], None))
-    assert needs_conservative_livevar_calculation(block)
-
-def test_nclc_nongc_not_passed_on():
-    # +--- inputargs: pointer_to_gc
-    # | v0 <- op_getsubstruct pointer_to_gc 'b'
-    # +--- exitargs: pointer_to_gc (i.e. the pointer to non-gc doesn't leave the block)
-    llops = LowLevelOpList()
-    ptr_a = varoftype(lltype.Ptr(GcA))
-    v_res = llops.genop("getsubstruct", [ptr_a, model.Constant('b', lltype.Void)],
-                        resulttype=lltype.Ptr(NonGcB))
-    block = model.Block([ptr_a])
-    block.operations.extend(llops)
-    block.closeblock(model.Link([ptr_a], None))
-    assert not needs_conservative_livevar_calculation(block)
-
-def test_nclc_ignore_functype():
-    # +--- inputargs: pointer_to_gc
-    # | v0 <- op_getfield pointer_to_gc 'c'
-    # +--- exitargs: v0 (i.e. a pointer to function)
-    # pointers to functions are 'not gc' but functions are also
-    # immortal so you don't need to muck around inserting keepalives
-    # so *they* don't die!
-    llops = LowLevelOpList()
-    ptr_a = varoftype(lltype.Ptr(GcA))
-    v_res = llops.genop("getfield", [ptr_a, model.Constant('c', lltype.Void)],
-                        resulttype=GcA.c)
-    block = model.Block([ptr_a])
-    block.operations.extend(llops)
-    block.closeblock(model.Link([v_res], None))
-    assert not needs_conservative_livevar_calculation(block)
-
-def test_sbwk_should_insert_keepalives():
-    # this is testing something like:
-    # v0 <- op_producing_non_gc
-    # v1 <- op_using_v0        <- split here
-    llops = LowLevelOpList()
-    ptr_a = varoftype(lltype.Ptr(GcA))
-    v_res = llops.genop("getfield", [ptr_a, model.Constant('b', lltype.Void)],
-                        resulttype=lltype.Ptr(NonGcB))
-    llops.genop("direct_call", [model.Constant(None, lltype.Void), v_res],
-                resulttype=lltype.Void)
-    block = model.Block([ptr_a])
-    block.operations.extend(llops)
-    block.closeblock(model.Link([], None))
-    link = split_block_with_keepalive(block, 1)
-    assert 'keepalive' in [op.opname for op in link.target.operations]
-
-def test_sbwk_should_insert_keepalives_2():
-    # this is testing something like:
-    # v0 <- op_producing_non_gc
-    # v1 <- op_not_using_v0        <- split here
-    # v2 <- op_using_v0
-    llops = LowLevelOpList()
-    ptr_a = varoftype(lltype.Ptr(GcA))
-    v_res = llops.genop("getfield", [ptr_a, model.Constant('b', lltype.Void)],
-                        resulttype=lltype.Ptr(NonGcB))
-    llops.genop("direct_call", [model.Constant(None, lltype.Void)],
-                resulttype=lltype.Void)
-    llops.genop("direct_call", [model.Constant(None, lltype.Void), v_res],
-                resulttype=lltype.Void)
-    block = model.Block([ptr_a])
-    block.operations.extend(llops)
-    block.closeblock(model.Link([], None))
-    link = split_block_with_keepalive(block, 1)
-    assert 'keepalive' in [op.opname for op in link.target.operations]
-
 #__________________________________________________________
 # test compute_reachability
 

diff --git a/pypy/jit/metainterp/test/test_optimizeutil.py b/pypy/jit/metainterp/test/test_optimizeutil.py
--- a/pypy/jit/metainterp/test/test_optimizeutil.py
+++ b/pypy/jit/metainterp/test/test_optimizeutil.py
@@ -68,6 +68,16 @@
     nodeobjvalue = lltype.cast_opaque_ptr(llmemory.GCREF, nodeobj)
     refdescr = cpu.fielddescrof(NODEOBJ, 'ref')
 
+    INTOBJ_NOIMMUT = lltype.GcStruct('INTOBJ_NOIMMUT', ('parent', OBJECT),
+                                                ('intval', lltype.Signed))
+    INTOBJ_IMMUT = lltype.GcStruct('INTOBJ_IMMUT', ('parent', OBJECT),
+                                            ('intval', lltype.Signed),
+                                            hints={'immutable': True})
+    intobj_noimmut_vtable = lltype.malloc(OBJECT_VTABLE, immortal=True)
+    intobj_immut_vtable = lltype.malloc(OBJECT_VTABLE, immortal=True)
+    noimmut_intval = cpu.fielddescrof(INTOBJ_NOIMMUT, 'intval')
+    immut_intval = cpu.fielddescrof(INTOBJ_IMMUT, 'intval')
+
     arraydescr = cpu.arraydescrof(lltype.GcArray(lltype.Signed))
     floatarraydescr = cpu.arraydescrof(lltype.GcArray(lltype.Float))
 
@@ -147,7 +157,6 @@
     FakeWarmRunnerDesc.cpu = cpu
     vrefinfo = VirtualRefInfo(FakeWarmRunnerDesc)
     virtualtokendescr = vrefinfo.descr_virtual_token
-    virtualrefindexdescr = vrefinfo.descr_virtualref_index
     virtualforceddescr = vrefinfo.descr_forced
     jit_virtual_ref_vtable = vrefinfo.jit_virtual_ref_vtable
     jvr_vtable_adr = llmemory.cast_ptr_to_adr(jit_virtual_ref_vtable)
@@ -156,6 +165,8 @@
     register_known_gctype(cpu, node_vtable2, NODE2)
     register_known_gctype(cpu, u_vtable,     U)
     register_known_gctype(cpu, jit_virtual_ref_vtable,vrefinfo.JIT_VIRTUAL_REF)
+    register_known_gctype(cpu, intobj_noimmut_vtable, INTOBJ_NOIMMUT)
+    register_known_gctype(cpu, intobj_immut_vtable,   INTOBJ_IMMUT)
 
     namespace = locals()
 

diff --git a/pypy/jit/backend/llsupport/gc.py b/pypy/jit/backend/llsupport/gc.py
--- a/pypy/jit/backend/llsupport/gc.py
+++ b/pypy/jit/backend/llsupport/gc.py
@@ -1,6 +1,8 @@
+import os
 from pypy.rlib import rgc
 from pypy.rlib.objectmodel import we_are_translated
 from pypy.rlib.debug import fatalerror
+from pypy.rlib.rarithmetic import ovfcheck
 from pypy.rpython.lltypesystem import lltype, llmemory, rffi, rclass, rstr
 from pypy.rpython.lltypesystem import llgroup
 from pypy.rpython.lltypesystem.lloperation import llop
@@ -15,12 +17,13 @@
 from pypy.jit.backend.llsupport.descr import GcCache, get_field_descr
 from pypy.jit.backend.llsupport.descr import GcPtrFieldDescr
 from pypy.jit.backend.llsupport.descr import get_call_descr
-from pypy.rpython.memory.gctransform import asmgcroot
 
 # ____________________________________________________________
 
 class GcLLDescription(GcCache):
     minimal_size_in_nursery = 0
+    get_malloc_slowpath_addr = None
+
     def __init__(self, gcdescr, translator=None, rtyper=None):
         GcCache.__init__(self, translator is not None, rtyper)
         self.gcdescr = gcdescr
@@ -34,6 +37,8 @@
         pass
     def can_inline_malloc(self, descr):
         return False
+    def can_inline_malloc_varsize(self, descr, num_elem):
+        return False
     def has_write_barrier_class(self):
         return None
     def freeing_block(self, start, stop):
@@ -212,10 +217,12 @@
         return addr_ref
 
 
-class GcRootMap_asmgcc:
+class GcRootMap_asmgcc(object):
     """Handles locating the stack roots in the assembler.
     This is the class supporting --gcrootfinder=asmgcc.
     """
+    is_shadow_stack = False
+
     LOC_REG       = 0
     LOC_ESP_PLUS  = 1
     LOC_EBP_PLUS  = 2
@@ -224,7 +231,7 @@
     GCMAP_ARRAY = rffi.CArray(lltype.Signed)
     CALLSHAPE_ARRAY_PTR = rffi.CArrayPtr(rffi.UCHAR)
 
-    def __init__(self):
+    def __init__(self, gcdescr=None):
         # '_gcmap' is an array of length '_gcmap_maxlength' of addresses.
         # '_gcmap_curlength' tells how full the array really is.
         # The addresses are actually grouped in pairs:
@@ -237,6 +244,13 @@
         self._gcmap_deadentries = 0
         self._gcmap_sorted = True
 
+    def add_jit2gc_hooks(self, jit2gc):
+        jit2gc.update({
+            'gcmapstart': lambda: self.gcmapstart(),
+            'gcmapend': lambda: self.gcmapend(),
+            'gcmarksorted': lambda: self.gcmarksorted(),
+            })
+
     def initialize(self):
         # hack hack hack.  Remove these lines and see MissingRTypeAttribute
         # when the rtyper tries to annotate these methods only when GC-ing...
@@ -309,6 +323,7 @@
 
     @rgc.no_collect
     def freeing_block(self, start, stop):
+        from pypy.rpython.memory.gctransform import asmgcroot
         # if [start:stop] is a raw block of assembler, then look up the
         # corresponding gcroot markers, and mark them as freed now in
         # self._gcmap by setting the 2nd address of every entry to NULL.
@@ -365,7 +380,7 @@
             number >>= 7
         shape.append(chr(number | flag))
 
-    def add_ebp_offset(self, shape, offset):
+    def add_frame_offset(self, shape, offset):
         assert (offset & 3) == 0
         if offset >= 0:
             num = self.LOC_EBP_PLUS | offset
@@ -388,6 +403,126 @@
         return rawaddr
 
 
+class GcRootMap_shadowstack(object):
+    """Handles locating the stack roots in the assembler.
+    This is the class supporting --gcrootfinder=shadowstack.
+    """
+    is_shadow_stack = True
+    MARKER = 8
+
+    # The "shadowstack" is a portable way in which the GC finds the
+    # roots that live in the stack.  Normally it is just a list of
+    # pointers to GC objects.  The pointers may be moved around by a GC
+    # collection.  But with the JIT, an entry can also be MARKER, in
+    # which case the next entry points to an assembler stack frame.
+    # During a residual CALL from the assembler (which may indirectly
+    # call the GC), we use the force_index stored in the assembler
+    # stack frame to identify the call: we can go from the force_index
+    # to a list of where the GC pointers are in the frame (this is the
+    # purpose of the present class).
+    #
+    # Note that across CALL_MAY_FORCE or CALL_ASSEMBLER, we can also go
+    # from the force_index to a ResumeGuardForcedDescr instance, which
+    # is used if the virtualizable or the virtualrefs need to be forced
+    # (see pypy.jit.backend.model).  The force_index number in the stack
+    # frame is initially set to a non-negative value x, but it is
+    # occasionally turned into (~x) in case of forcing.
+
+    INTARRAYPTR = rffi.CArrayPtr(rffi.INT)
+    CALLSHAPES_ARRAY = rffi.CArray(INTARRAYPTR)
+
+    def __init__(self, gcdescr):
+        self._callshapes = lltype.nullptr(self.CALLSHAPES_ARRAY)
+        self._callshapes_maxlength = 0
+        self.force_index_ofs = gcdescr.force_index_ofs
+
+    def add_jit2gc_hooks(self, jit2gc):
+        #
+        def collect_jit_stack_root(callback, gc, addr):
+            if addr.signed[0] != GcRootMap_shadowstack.MARKER:
+                # common case
+                if gc.points_to_valid_gc_object(addr):
+                    callback(gc, addr)
+                return WORD
+            else:
+                # case of a MARKER followed by an assembler stack frame
+                follow_stack_frame_of_assembler(callback, gc, addr)
+                return 2 * WORD
+        #
+        def follow_stack_frame_of_assembler(callback, gc, addr):
+            frame_addr = addr.signed[1]
+            addr = llmemory.cast_int_to_adr(frame_addr + self.force_index_ofs)
+            force_index = addr.signed[0]
+            if force_index < 0:
+                force_index = ~force_index
+            callshape = self._callshapes[force_index]
+            n = 0
+            while True:
+                offset = rffi.cast(lltype.Signed, callshape[n])
+                if offset == 0:
+                    break
+                addr = llmemory.cast_int_to_adr(frame_addr + offset)
+                if gc.points_to_valid_gc_object(addr):
+                    callback(gc, addr)
+                n += 1
+        #
+        jit2gc.update({
+            'rootstackhook': collect_jit_stack_root,
+            })
+
+    def initialize(self):
+        pass
+
+    def get_basic_shape(self, is_64_bit=False):
+        return []
+
+    def add_frame_offset(self, shape, offset):
+        assert offset != 0
+        shape.append(offset)
+
+    def add_callee_save_reg(self, shape, register):
+        msg = "GC pointer in %s was not spilled" % register
+        os.write(2, '[llsupport/gc] %s\n' % msg)
+        raise AssertionError(msg)
+
+    def compress_callshape(self, shape, datablockwrapper):
+        length = len(shape)
+        SZINT = rffi.sizeof(rffi.INT)
+        rawaddr = datablockwrapper.malloc_aligned((length + 1) * SZINT, SZINT)
+        p = rffi.cast(self.INTARRAYPTR, rawaddr)
+        for i in range(length):
+            p[i] = rffi.cast(rffi.INT, shape[i])
+        p[length] = rffi.cast(rffi.INT, 0)
+        return p
+
+    def write_callshape(self, p, force_index):
+        if force_index >= self._callshapes_maxlength:
+            self._enlarge_callshape_list(force_index + 1)
+        self._callshapes[force_index] = p
+
+    def _enlarge_callshape_list(self, minsize):
+        newlength = 250 + (self._callshapes_maxlength // 3) * 4
+        if newlength < minsize:
+            newlength = minsize
+        newarray = lltype.malloc(self.CALLSHAPES_ARRAY, newlength,
+                                 flavor='raw', track_allocation=False)
+        if self._callshapes:
+            i = self._callshapes_maxlength - 1
+            while i >= 0:
+                newarray[i] = self._callshapes[i]
+                i -= 1
+            lltype.free(self._callshapes, flavor='raw')
+        self._callshapes = newarray
+        self._callshapes_maxlength = newlength
+
+    def freeing_block(self, start, stop):
+        pass     # nothing needed here
+
+    def get_root_stack_top_addr(self):
+        rst_addr = llop.gc_adr_of_root_stack_top(llmemory.Address)
+        return rffi.cast(lltype.Signed, rst_addr)
+
+
 class WriteBarrierDescr(AbstractDescr):
     def __init__(self, gc_ll_descr):
         self.llop1 = gc_ll_descr.llop1
@@ -437,7 +572,7 @@
         except KeyError:
             raise NotImplementedError("--gcrootfinder=%s not implemented"
                                       " with the JIT" % (name,))
-        gcrootmap = cls()
+        gcrootmap = cls(gcdescr)
         self.gcrootmap = gcrootmap
         self.gcrefs = GcRefList()
         self.single_gcref_descr = GcPtrFieldDescr('', 0)
@@ -446,12 +581,9 @@
         # where it can be fished and reused by the FrameworkGCTransformer
         self.layoutbuilder = framework.TransformerLayoutBuilder(translator)
         self.layoutbuilder.delay_encoding()
-        self.translator._jit2gc = {
-            'layoutbuilder': self.layoutbuilder,
-            'gcmapstart': lambda: gcrootmap.gcmapstart(),
-            'gcmapend': lambda: gcrootmap.gcmapend(),
-            'gcmarksorted': lambda: gcrootmap.gcmarksorted(),
-            }
+        self.translator._jit2gc = {'layoutbuilder': self.layoutbuilder}
+        gcrootmap.add_jit2gc_hooks(self.translator._jit2gc)
+
         self.GCClass = self.layoutbuilder.GCClass
         self.moving_gc = self.GCClass.moving_gc
         self.HDRPTR = lltype.Ptr(self.GCClass.HDR)
@@ -461,6 +593,10 @@
         self.max_size_of_young_obj = self.GCClass.JIT_max_size_of_young_obj()
         self.minimal_size_in_nursery=self.GCClass.JIT_minimal_size_in_nursery()
 
+        # for the fast path of mallocs, the following must be true, at least
+        assert self.GCClass.inline_simple_malloc
+        assert self.GCClass.inline_simple_malloc_varsize
+
         # make a malloc function, with three arguments
         def malloc_basic(size, tid):
             type_id = llop.extract_ushort(llgroup.HALFWORD, tid)
@@ -539,20 +675,23 @@
             x3 = x0 * 0.3
             for_test_only.x = x0 + x1 + x2 + x3
         #
-        def malloc_fixedsize_slowpath(size):
+        def malloc_slowpath(size):
             if self.DEBUG:
                 random_usage_of_xmm_registers()
             assert size >= self.minimal_size_in_nursery
             try:
+                # NB. although we call do_malloc_fixedsize_clear() here,
+                # it's a bit of a hack because we set tid to 0 and may
+                # also use it to allocate varsized objects.  The tid
+                # and possibly the length are both set afterward.
                 gcref = llop1.do_malloc_fixedsize_clear(llmemory.GCREF,
                                             0, size, True, False, False)
             except MemoryError:
                 fatalerror("out of memory (from JITted code)")
                 return 0
             return rffi.cast(lltype.Signed, gcref)
-        self.malloc_fixedsize_slowpath = malloc_fixedsize_slowpath
-        self.MALLOC_FIXEDSIZE_SLOWPATH = lltype.FuncType([lltype.Signed],
-                                                         lltype.Signed)
+        self.malloc_slowpath = malloc_slowpath
+        self.MALLOC_SLOWPATH = lltype.FuncType([lltype.Signed], lltype.Signed)
 
     def get_nursery_free_addr(self):
         nurs_addr = llop.gc_adr_of_nursery_free(llmemory.Address)
@@ -562,9 +701,8 @@
         nurs_top_addr = llop.gc_adr_of_nursery_top(llmemory.Address)
         return rffi.cast(lltype.Signed, nurs_top_addr)
 
-    def get_malloc_fixedsize_slowpath_addr(self):
-        fptr = llhelper(lltype.Ptr(self.MALLOC_FIXEDSIZE_SLOWPATH),
-                        self.malloc_fixedsize_slowpath)
+    def get_malloc_slowpath_addr(self):
+        fptr = llhelper(lltype.Ptr(self.MALLOC_SLOWPATH), self.malloc_slowpath)
         return rffi.cast(lltype.Signed, fptr)
 
     def initialize(self):
@@ -710,6 +848,16 @@
             return True
         return False
 
+    def can_inline_malloc_varsize(self, arraydescr, num_elem):
+        assert isinstance(arraydescr, BaseArrayDescr)
+        basesize = arraydescr.get_base_size(self.translate_support_code)
+        itemsize = arraydescr.get_item_size(self.translate_support_code)
+        try:
+            size = ovfcheck(basesize + ovfcheck(itemsize * num_elem))
+            return size < self.max_size_of_young_obj
+        except OverflowError:
+            return False
+
     def has_write_barrier_class(self):
         return WriteBarrierDescr
 

diff --git a/pypy/doc/getting-started-python.rst b/pypy/doc/getting-started-python.rst
--- a/pypy/doc/getting-started-python.rst
+++ b/pypy/doc/getting-started-python.rst
@@ -39,13 +39,15 @@
 
      [user at debian-box ~]$ sudo apt-get install \
      gcc make python-dev libffi-dev pkg-config \
-     libz-dev libbz2-dev libncurses-dev libexpat1-dev libssl-dev libgc-dev python-sphinx
+     libz-dev libbz2-dev libncurses-dev libexpat1-dev \
+     libssl-dev libgc-dev python-sphinx python-greenlet
 
    On a Fedora box these are::
 
      [user at fedora-or-rh-box ~]$ sudo yum install \
      gcc make python-devel libffi-devel pkg-config \
-     zlib-devel bzip2-devel ncurses-devel expat-devel openssl-devel gc-devel python-sphinx
+     zlib-devel bzip2-devel ncurses-devel expat-devel \
+     openssl-devel gc-devel python-sphinx python-greenlet
 
    The above command lines are split with continuation characters, giving the necessary dependencies first, then the optional ones.
 
@@ -57,6 +59,7 @@
    * ``libssl-dev`` (for the optional ``_ssl`` module)
    * ``libgc-dev`` (for the Boehm garbage collector: only needed when translating with `--opt=0, 1` or `size`)
    * ``python-sphinx`` (for the optional documentation build)
+   * ``python-greenlet`` (for the optional stackless support in interpreted mode/testing)
 
 2. Translation is somewhat time-consuming (30 min to
    over one hour) and RAM-hungry.  If you have less than 1.5 GB of
@@ -76,7 +79,8 @@
 
    possibly replacing ``--opt=jit`` with another `optimization level`_
    of your choice like ``--opt=2`` if you do not want the included JIT
-   compiler.  As of March 2011, Intel **32-bit** environment needs ``4GB``.
+   compiler.  As of March 2011, Intel 32-bit environment needs **at
+   least** 2GB, and 64-bit needs 4GB.
 
 .. _`optimization level`: config/opt.html
 
@@ -229,6 +233,12 @@
     ../../..
     etc.
 
+If the executable fails to find suitable libraries, it will report
+``debug: WARNING: library path not found, using compiled-in sys.path``
+and then attempt to continue normally.  If the default path is usable,
+most code will be fine.  However, the ``sys.prefix`` will be unset
+and some existing libraries assume that this is never the case.
+
 In order to use ``distutils`` or ``setuptools`` a directory ``PREFIX/site-packages`` needs to be created. Here's an example session setting up and using ``easy_install``::
 
     $ cd PREFIX

diff --git a/pypy/rlib/rlocale.py b/pypy/rlib/rlocale.py
--- a/pypy/rlib/rlocale.py
+++ b/pypy/rlib/rlocale.py
@@ -7,6 +7,7 @@
 from pypy.rpython.lltypesystem import rffi, lltype
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
 from pypy.rpython.tool import rffi_platform as platform
+from pypy.rpython.extfunc import register_external
 
 class LocaleError(Exception):
     def __init__(self, message):
@@ -156,23 +157,35 @@
 
 HAVE_BIND_TEXTDOMAIN_CODESET = cConfig.HAVE_BIND_TEXTDOMAIN_CODESET
 
-def external(name, args, result, calling_conv='c'):
+def external(name, args, result, calling_conv='c', **kwds):
     return rffi.llexternal(name, args, result,
                            compilation_info=CConfig._compilation_info_,
                            calling_conv=calling_conv,
-                           sandboxsafe=True)
+                           sandboxsafe=True, **kwds)
 
 _lconv = lltype.Ptr(cConfig.lconv)
 localeconv = external('localeconv', [], _lconv)
 
 def numeric_formatting():
     """Specialized function to get formatting for numbers"""
+    return numeric_formatting_impl()
+
+def numeric_formatting_impl():
     conv = localeconv()
     decimal_point = rffi.charp2str(conv.c_decimal_point)
     thousands_sep = rffi.charp2str(conv.c_thousands_sep)
     grouping = rffi.charp2str(conv.c_grouping)
     return decimal_point, thousands_sep, grouping
 
+def oo_numeric_formatting():
+    return '.', '', ''
+
+register_external(numeric_formatting, [], (str, str, str),
+                  llimpl=numeric_formatting_impl,
+                  ooimpl=oo_numeric_formatting,
+                  sandboxsafe=True)
+
+
 _setlocale = external('setlocale', [rffi.INT, rffi.CCHARP], rffi.CCHARP)
 
 def setlocale(category, locale):
@@ -184,11 +197,11 @@
         raise LocaleError("unsupported locale setting")
     return rffi.charp2str(ll_result)
 
-isalpha = external('isalpha', [rffi.INT], rffi.INT)
-isupper = external('isupper', [rffi.INT], rffi.INT)
-islower = external('islower', [rffi.INT], rffi.INT)
-tolower = external('tolower', [rffi.INT], rffi.INT)
-isalnum = external('isalnum', [rffi.INT], rffi.INT)
+isalpha = external('isalpha', [rffi.INT], rffi.INT, oo_primitive='locale_isalpha')
+isupper = external('isupper', [rffi.INT], rffi.INT, oo_primitive='locale_isupper')
+islower = external('islower', [rffi.INT], rffi.INT, oo_primitive='locale_islower')
+tolower = external('tolower', [rffi.INT], rffi.INT, oo_primitive='locale_tolower')
+isalnum = external('isalnum', [rffi.INT], rffi.INT, oo_primitive='locale_isalnum')
 
 if HAVE_LANGINFO:
     _nl_langinfo = external('nl_langinfo', [rffi.INT], rffi.CCHARP)

diff --git a/pypy/translator/backendopt/test/test_constfold.py b/pypy/translator/backendopt/test/test_constfold.py
--- a/pypy/translator/backendopt/test/test_constfold.py
+++ b/pypy/translator/backendopt/test/test_constfold.py
@@ -185,27 +185,6 @@
     check_graph(graph, [0], 61, t)
 
 
-def test_keepalive_const_substruct():
-    py.test.skip("do we want partial folding of getinteriorfield?")
-    S2 = lltype.Struct('S2', ('x', lltype.Signed))
-    S1 = lltype.GcStruct('S1', ('sub', S2))
-    s1 = lltype.malloc(S1)
-    s1.sub.x = 1234
-    def fn():
-        return s1.sub.x
-    graph, t = get_graph(fn, [])
-    assert summary(graph) == {'getinteriorfield': 1}
-    constant_fold_graph(graph)
-
-    # kill all references to 's1'
-    s1 = fn = None
-    del graph.func
-    import gc; gc.collect()
-
-    assert summary(graph) == {'getfield': 1}
-    check_graph(graph, [], 1234, t)
-
-
 def test_keepalive_const_fieldptr():
     S1 = lltype.GcStruct('S1', ('x', lltype.Signed))
     s1 = lltype.malloc(S1)

diff --git a/pypy/interpreter/test/test_typedef.py b/pypy/interpreter/test/test_typedef.py
--- a/pypy/interpreter/test/test_typedef.py
+++ b/pypy/interpreter/test/test_typedef.py
@@ -127,12 +127,15 @@
                                checks[2], checks[3]))
         subclasses = {}
         for key, subcls in typedef._subclass_cache.items():
+            if key[0] is not space.config:
+                continue
             cls = key[1]
             subclasses.setdefault(cls, {})
-            subclasses[cls][subcls] = True
+            prevsubcls = subclasses[cls].setdefault(subcls.__name__, subcls)
+            assert subcls is prevsubcls
         for cls, set in subclasses.items():
             assert len(set) <= 6, "%s has %d subclasses:\n%r" % (
-                cls, len(set), [subcls.__name__ for subcls in set])
+                cls, len(set), list(set))
 
     def test_getsetproperty(self):
         class W_SomeType(Wrappable):

diff --git a/.gitignore b/.gitignore
--- a/.gitignore
+++ b/.gitignore
@@ -12,6 +12,8 @@
 pypy/doc/*.html
 pypy/doc/config/*.html
 pypy/doc/discussion/*.html
+pypy/module/cpyext/src/*.o
+pypy/module/cpyext/test/*.o
 pypy/module/test_lib_pypy/ctypes_tests/*.o
 pypy/translator/c/src/dtoa.o
 pypy/translator/goal/pypy-c

diff --git a/_pytest/resultlog.py b/_pytest/resultlog.py
--- a/_pytest/resultlog.py
+++ b/_pytest/resultlog.py
@@ -74,7 +74,7 @@
         elif report.failed:
             longrepr = str(report.longrepr)
         elif report.skipped:
-            longrepr = str(report.longrepr[2])
+            longrepr = str(report.longrepr)
         self.log_outcome(report, code, longrepr)
 
     def pytest_collectreport(self, report):

diff --git a/lib_pypy/pyrepl/completing_reader.py b/lib_pypy/pyrepl/completing_reader.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/completing_reader.py
@@ -0,0 +1,280 @@
+#   Copyright 2000-2010 Michael Hudson-Doyle <micahel at gmail.com>
+#                       Antonio Cuni
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+from pyrepl import commands, reader
+from pyrepl.reader import Reader
+
+def uniqify(l):
+    d = {}
+    for i in l:
+        d[i] = 1
+    r = d.keys()
+    r.sort()
+    return r
+
+def prefix(wordlist, j = 0):
+    d = {}
+    i = j
+    try:
+        while 1:
+            for word in wordlist:
+                d[word[i]] = 1
+            if len(d) > 1:
+                return wordlist[0][j:i]
+            i += 1
+            d = {}
+    except IndexError:
+        return wordlist[0][j:i]
+
+import re
+def stripcolor(s):
+    return stripcolor.regexp.sub('', s)
+stripcolor.regexp = re.compile(r"\x1B\[([0-9]{1,3}(;[0-9]{1,2})?)?[m|K]")
+
+def real_len(s):
+    return len(stripcolor(s))
+
+def left_align(s, maxlen):
+    stripped = stripcolor(s)
+    if len(stripped) > maxlen:
+        # too bad, we remove the color
+        return stripped[:maxlen]
+    padding = maxlen - len(stripped)
+    return s + ' '*padding
+
+def build_menu(cons, wordlist, start, use_brackets, sort_in_column):
+    if use_brackets:
+        item = "[ %s ]"
+        padding = 4
+    else:
+        item = "%s  "
+        padding = 2
+    maxlen = min(max(map(real_len, wordlist)), cons.width - padding)
+    cols = cons.width / (maxlen + padding)
+    rows = (len(wordlist) - 1)/cols + 1
+
+    if sort_in_column:
+        # sort_in_column=False (default)     sort_in_column=True
+        #          A B C                       A D G
+        #          D E F                       B E 
+        #          G                           C F
+        #
+        # "fill" the table with empty words, so we always have the same amout
+        # of rows for each column
+        missing = cols*rows - len(wordlist)
+        wordlist = wordlist + ['']*missing
+        indexes = [(i%cols)*rows + i//cols for i in range(len(wordlist))]
+        wordlist = [wordlist[i] for i in indexes]
+    menu = []
+    i = start
+    for r in range(rows):
+        row = []
+        for col in range(cols):
+            row.append(item % left_align(wordlist[i], maxlen))
+            i += 1
+            if i >= len(wordlist):
+                break
+        menu.append( ''.join(row) )
+        if i >= len(wordlist):
+            i = 0
+            break
+        if r + 5 > cons.height:
+            menu.append("   %d more... "%(len(wordlist) - i))
+            break
+    return menu, i    
+
+# this gets somewhat user interface-y, and as a result the logic gets
+# very convoluted.
+#
+#  To summarise the summary of the summary:- people are a problem.
+#                  -- The Hitch-Hikers Guide to the Galaxy, Episode 12
+
+#### Desired behaviour of the completions commands.
+# the considerations are:
+# (1) how many completions are possible
+# (2) whether the last command was a completion
+# (3) if we can assume that the completer is going to return the same set of
+#     completions: this is controlled by the ``assume_immutable_completions``
+#     variable on the reader, which is True by default to match the historical
+#     behaviour of pyrepl, but e.g. False in the ReadlineAlikeReader to match
+#     more closely readline's semantics (this is needed e.g. by
+#     fancycompleter)
+#
+# if there's no possible completion, beep at the user and point this out.
+# this is easy.
+#
+# if there's only one possible completion, stick it in.  if the last thing
+# user did was a completion, point out that he isn't getting anywhere, but
+# only if the ``assume_immutable_completions`` is True.
+#
+# now it gets complicated.
+# 
+# for the first press of a completion key:
+#  if there's a common prefix, stick it in.
+
+#  irrespective of whether anything got stuck in, if the word is now
+#  complete, show the "complete but not unique" message
+
+#  if there's no common prefix and if the word is not now complete,
+#  beep.
+
+#        common prefix ->    yes          no
+#        word complete \/
+#            yes           "cbnu"      "cbnu"
+#            no              -          beep
+
+# for the second bang on the completion key
+#  there will necessarily be no common prefix
+#  show a menu of the choices.
+
+# for subsequent bangs, rotate the menu around (if there are sufficient
+# choices).
+
+class complete(commands.Command):
+    def do(self):
+        r = self.reader
+        stem = r.get_stem()
+        if r.assume_immutable_completions and \
+                r.last_command_is(self.__class__):
+            completions = r.cmpltn_menu_choices
+        else:
+            r.cmpltn_menu_choices = completions = \
+                                        r.get_completions(stem)
+        if len(completions) == 0:
+            r.error("no matches")
+        elif len(completions) == 1:
+            if r.assume_immutable_completions and \
+                   len(completions[0]) == len(stem) and \
+                   r.last_command_is(self.__class__):
+                r.msg = "[ sole completion ]"
+                r.dirty = 1
+            r.insert(completions[0][len(stem):])
+        else:
+            p = prefix(completions, len(stem))
+            if p <> '':
+                r.insert(p)
+            if r.last_command_is(self.__class__):
+                if not r.cmpltn_menu_vis:
+                    r.cmpltn_menu_vis = 1
+                r.cmpltn_menu, r.cmpltn_menu_end = build_menu(
+                    r.console, completions, r.cmpltn_menu_end,
+                    r.use_brackets, r.sort_in_column)
+                r.dirty = 1
+            elif stem + p in completions:
+                r.msg = "[ complete but not unique ]"
+                r.dirty = 1
+            else:
+                r.msg = "[ not unique ]"
+                r.dirty = 1
+
+class self_insert(commands.self_insert):
+    def do(self):
+        commands.self_insert.do(self)
+        r = self.reader
+        if r.cmpltn_menu_vis:
+            stem = r.get_stem()
+            if len(stem) < 1:
+                r.cmpltn_reset()
+            else:
+                completions = [w for w in r.cmpltn_menu_choices
+                               if w.startswith(stem)]
+                if completions:
+                    r.cmpltn_menu, r.cmpltn_menu_end = build_menu(
+                        r.console, completions, 0,
+                        r.use_brackets, r.sort_in_column)
+                else:
+                    r.cmpltn_reset()
+
+class CompletingReader(Reader):
+    """Adds completion support
+
+    Adds instance variables:
+      * cmpltn_menu, cmpltn_menu_vis, cmpltn_menu_end, cmpltn_choices:
+      *
+    """
+    # see the comment for the complete command
+    assume_immutable_completions = True
+    use_brackets = True # display completions inside []
+    sort_in_column = False
+    
+    def collect_keymap(self):
+        return super(CompletingReader, self).collect_keymap() + (
+            (r'\t', 'complete'),)
+    
+    def __init__(self, console):
+        super(CompletingReader, self).__init__(console)
+        self.cmpltn_menu = ["[ menu 1 ]", "[ menu 2 ]"]
+        self.cmpltn_menu_vis = 0
+        self.cmpltn_menu_end = 0
+        for c in [complete, self_insert]:
+            self.commands[c.__name__] = c
+            self.commands[c.__name__.replace('_', '-')] = c        
+
+    def after_command(self, cmd):
+        super(CompletingReader, self).after_command(cmd)
+        if not isinstance(cmd, complete) and not isinstance(cmd, self_insert):
+            self.cmpltn_reset()
+
+    def calc_screen(self):
+        screen = super(CompletingReader, self).calc_screen()
+        if self.cmpltn_menu_vis:
+            ly = self.lxy[1]
+            screen[ly:ly] = self.cmpltn_menu
+            self.screeninfo[ly:ly] = [(0, [])]*len(self.cmpltn_menu)
+            self.cxy = self.cxy[0], self.cxy[1] + len(self.cmpltn_menu)
+        return screen
+
+    def finish(self):
+        super(CompletingReader, self).finish()
+        self.cmpltn_reset()
+
+    def cmpltn_reset(self):
+        self.cmpltn_menu = []
+        self.cmpltn_menu_vis = 0
+        self.cmpltn_menu_end = 0
+        self.cmpltn_menu_choices = []        
+
+    def get_stem(self):
+        st = self.syntax_table
+        SW = reader.SYNTAX_WORD
+        b = self.buffer
+        p = self.pos - 1
+        while p >= 0 and st.get(b[p], SW) == SW:
+            p -= 1
+        return u''.join(b[p+1:self.pos])
+
+    def get_completions(self, stem):
+        return []
+
+def test():
+    class TestReader(CompletingReader):
+        def get_completions(self, stem):
+            return [s for l in map(lambda x:x.split(),self.history)
+                    for s in l if s and s.startswith(stem)]
+    reader = TestReader()
+    reader.ps1 = "c**> "
+    reader.ps2 = "c/*> "
+    reader.ps3 = "c|*> "
+    reader.ps4 = "c\*> "
+    while reader.readline():
+        pass
+
+if __name__=='__main__':
+    test()

diff --git a/.hgsubstate b/.hgsubstate
deleted file mode 100644
--- a/.hgsubstate
+++ /dev/null
@@ -1,2 +0,0 @@
-80037 greenlet
-80409 lib_pypy/pyrepl

diff --git a/pypy/translator/c/test/test_lltyped.py b/pypy/translator/c/test/test_lltyped.py
--- a/pypy/translator/c/test/test_lltyped.py
+++ b/pypy/translator/c/test/test_lltyped.py
@@ -895,3 +895,10 @@
         fn = self.getcompiled(llf)
         assert fn() == 45
 
+    def test_rstring_to_float(self):
+        from pypy.rlib.rfloat import rstring_to_float
+        def llf(i):
+            s = ['42.3', '123.4'][i]
+            return rstring_to_float(s)
+        fn = self.getcompiled(llf, [int])
+        assert fn(0) == 42.3

diff --git a/pypy/jit/backend/test/test_random.py b/pypy/jit/backend/test/test_random.py
--- a/pypy/jit/backend/test/test_random.py
+++ b/pypy/jit/backend/test/test_random.py
@@ -717,6 +717,7 @@
 def test_random_function(BuilderClass=OperationBuilder):
     r = Random()
     cpu = get_cpu()
+    cpu.setup_once()
     if pytest.config.option.repeat == -1:
         while 1:
             check_random_function(cpu, BuilderClass, r)

diff --git a/pypy/jit/backend/llsupport/test/test_gc.py b/pypy/jit/backend/llsupport/test/test_gc.py
--- a/pypy/jit/backend/llsupport/test/test_gc.py
+++ b/pypy/jit/backend/llsupport/test/test_gc.py
@@ -9,7 +9,6 @@
 from pypy.jit.tool.oparser import parse
 from pypy.rpython.lltypesystem.rclass import OBJECT, OBJECT_VTABLE
 from pypy.jit.metainterp.test.test_optimizeopt import equaloplists
-from pypy.rpython.memory.gctransform import asmgcroot
 
 def test_boehm():
     gc_ll_descr = GcLLDescr_boehm(None, None, None)
@@ -75,8 +74,8 @@
         num2a = ((-num2|3) >> 7) | 128
         num2b = (-num2|3) & 127
         shape = gcrootmap.get_basic_shape()
-        gcrootmap.add_ebp_offset(shape, num1)
-        gcrootmap.add_ebp_offset(shape, num2)
+        gcrootmap.add_frame_offset(shape, num1)
+        gcrootmap.add_frame_offset(shape, num2)
         assert shape == map(chr, [6, 7, 11, 15, 2, 0, num1a, num2b, num2a])
         gcrootmap.add_callee_save_reg(shape, 1)
         assert shape == map(chr, [6, 7, 11, 15, 2, 0, num1a, num2b, num2a,
@@ -228,6 +227,33 @@
             gc.asmgcroot = saved
 
 
+class TestGcRootMapShadowStack:
+    class FakeGcDescr:
+        force_index_ofs = 92
+
+    def test_make_shapes(self):
+        gcrootmap = GcRootMap_shadowstack(self.FakeGcDescr())
+        shape = gcrootmap.get_basic_shape()
+        gcrootmap.add_frame_offset(shape, 16)
+        gcrootmap.add_frame_offset(shape, -24)
+        assert shape == [16, -24]
+
+    def test_compress_callshape(self):
+        class FakeDataBlockWrapper:
+            def malloc_aligned(self, size, alignment):
+                assert alignment == 4    # even on 64-bits
+                assert size == 12        # 4*3, even on 64-bits
+                return rffi.cast(lltype.Signed, p)
+        datablockwrapper = FakeDataBlockWrapper()
+        p = lltype.malloc(rffi.CArray(rffi.INT), 3, immortal=True)
+        gcrootmap = GcRootMap_shadowstack(self.FakeGcDescr())
+        shape = [16, -24]
+        gcrootmap.compress_callshape(shape, datablockwrapper)
+        assert rffi.cast(lltype.Signed, p[0]) == 16
+        assert rffi.cast(lltype.Signed, p[1]) == -24
+        assert rffi.cast(lltype.Signed, p[2]) == 0
+
+
 class FakeLLOp(object):
     def __init__(self):
         self.record = []

diff --git a/pypy/rlib/rdtoa.py b/pypy/rlib/rdtoa.py
--- a/pypy/rlib/rdtoa.py
+++ b/pypy/rlib/rdtoa.py
@@ -5,16 +5,33 @@
 from pypy.rpython.lltypesystem import lltype, rffi
 from pypy.rlib import jit
 from pypy.rlib.rstring import StringBuilder
-import py
+import py, sys
 
 cdir = py.path.local(pypydir) / 'translator' / 'c'
 include_dirs = [cdir]
 
+# set the word endianness based on the host's endianness
+# and the C double's endianness (which should be equal)
+if hasattr(float, '__getformat__'):
+    assert float.__getformat__('double') == 'IEEE, %s-endian' % sys.byteorder
+if sys.byteorder == 'little':
+    source_file = ['#define DOUBLE_IS_LITTLE_ENDIAN_IEEE754']
+elif sys.byteorder == 'big':
+    source_file = ['#define WORDS_BIGENDIAN',
+                   '#define DOUBLE_IS_BIG_ENDIAN_IEEE754']
+else:
+    raise AssertionError(sys.byteorder)
+
+source_file.append('#include "src/dtoa.c"')
+source_file = '\n\n'.join(source_file)
+
+# ____________________________________________________________
+
 eci = ExternalCompilationInfo(
     include_dirs = [cdir],
     includes = ['src/dtoa.h'],
     libraries = [],
-    separate_module_files = [cdir / 'src' / 'dtoa.c'],
+    separate_module_sources = [source_file],
     export_symbols = ['_PyPy_dg_strtod',
                       '_PyPy_dg_dtoa',
                       '_PyPy_dg_freedtoa',

diff --git a/pypy/translator/goal/targetpypystandalone.py b/pypy/translator/goal/targetpypystandalone.py
--- a/pypy/translator/goal/targetpypystandalone.py
+++ b/pypy/translator/goal/targetpypystandalone.py
@@ -105,13 +105,6 @@
         return parser
 
     def handle_config(self, config, translateconfig):
-        if config.translation.type_system == 'ootype':
-            print
-            print 'Translation to cli and jvm is known to be broken at the moment'
-            print 'Please try the "cli-jit" branch at:'
-            print 'http://codespeak.net/svn/pypy/branch/cli-jit/'
-            sys.exit(1)
-
         self.translateconfig = translateconfig
         # set up the objspace optimizations based on the --opt argument
         from pypy.config.pypyoption import set_pypy_opt_level
@@ -159,8 +152,8 @@
             from pypy.config.pypyoption import enable_translationmodules
             enable_translationmodules(config)
 
-        if config.translation.type_system == 'ootype':
-            config.objspace.usemodules.suggest(rbench=True)
+        ## if config.translation.type_system == 'ootype':
+        ##     config.objspace.usemodules.suggest(rbench=True)
 
         if config.translation.thread:
             config.objspace.usemodules.thread = True

diff --git a/lib_pypy/_pypy_wait.py b/lib_pypy/_pypy_wait.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/_pypy_wait.py
@@ -0,0 +1,51 @@
+from ctypes import CDLL, c_int, POINTER, byref
+from ctypes.util import find_library
+from resource import _struct_rusage, struct_rusage
+
+__all__ = ["wait3", "wait4"]
+
+libc = CDLL(find_library("c"))
+c_wait3 = libc.wait3
+
+c_wait3.argtypes = [POINTER(c_int), c_int, POINTER(_struct_rusage)]
+
+c_wait4 = libc.wait4
+
+c_wait4.argtypes = [c_int, POINTER(c_int), c_int, POINTER(_struct_rusage)]
+
+def create_struct_rusage(c_struct):
+    return struct_rusage((
+        float(c_struct.ru_utime),
+        float(c_struct.ru_stime),
+        c_struct.ru_maxrss,
+        c_struct.ru_ixrss,
+        c_struct.ru_idrss,
+        c_struct.ru_isrss,
+        c_struct.ru_minflt,
+        c_struct.ru_majflt,
+        c_struct.ru_nswap,
+        c_struct.ru_inblock,
+        c_struct.ru_oublock,
+        c_struct.ru_msgsnd,
+        c_struct.ru_msgrcv,
+        c_struct.ru_nsignals,
+        c_struct.ru_nvcsw,
+        c_struct.ru_nivcsw))
+
+def wait3(options):
+    status = c_int()
+    _rusage = _struct_rusage()
+    pid = c_wait3(byref(status), c_int(options), byref(_rusage))
+
+    rusage = create_struct_rusage(_rusage)
+
+    return pid, status.value, rusage
+
+def wait4(pid, options):
+    status = c_int()
+    _rusage = _struct_rusage()
+    pid = c_wait4(c_int(pid), byref(status), c_int(options), byref(_rusage))
+
+    rusage = create_struct_rusage(_rusage)
+
+    return pid, status.value, rusage

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
@@ -34,11 +34,7 @@
 
     @jit.purefunction
     def _getcell_makenew(self, key):
-        res = self.content.get(key, None)
-        if res is not None:
-            return res
-        result = self.content[key] = ModuleCell()
-        return result
+        return self.content.setdefault(key, ModuleCell())
 
     def impl_setitem(self, w_key, w_value):
         space = self.space
@@ -50,6 +46,16 @@
     def impl_setitem_str(self, name, w_value):
         self.getcell(name, True).w_value = w_value
 
+    def impl_setdefault(self, w_key, w_default):
+        space = self.space
+        if space.is_w(space.type(w_key), space.w_str):
+            cell = self.getcell(space.str_w(w_key), True)
+            if cell.w_value is None:
+                cell.w_value = w_default
+            return cell.w_value
+        else:
+            return self._as_rdict().impl_fallback_setdefault(w_key, w_default)
+
     def impl_delitem(self, w_key):
         space = self.space
         w_key_type = space.type(w_key)

diff --git a/pypy/module/cpyext/pyobject.py b/pypy/module/cpyext/pyobject.py
--- a/pypy/module/cpyext/pyobject.py
+++ b/pypy/module/cpyext/pyobject.py
@@ -7,6 +7,7 @@
     CANNOT_FAIL, Py_TPFLAGS_HEAPTYPE, PyTypeObjectPtr)
 from pypy.module.cpyext.state import State
 from pypy.objspace.std.typeobject import W_TypeObject
+from pypy.objspace.std.objectobject import W_ObjectObject
 from pypy.rlib.objectmodel import specialize, we_are_translated
 from pypy.rlib.rweakref import RWeakKeyDictionary
 from pypy.rpython.annlowlevel import llhelper
@@ -370,6 +371,15 @@
 @cpython_api([PyObject], lltype.Void)
 def _Py_NewReference(space, obj):
     obj.c_ob_refcnt = 1
+    w_type = from_ref(space, rffi.cast(PyObject, obj.c_ob_type))
+    assert isinstance(w_type, W_TypeObject)
+    if w_type.is_cpytype():
+        w_obj = space.allocate_instance(W_ObjectObject, w_type)
+        track_reference(space, obj, w_obj)
+        state = space.fromcache(RefcountState)
+        state.set_lifeline(w_obj, obj)
+    else:
+        assert False, "Please add more cases in _Py_NewReference()"
 
 def _Py_Dealloc(space, obj):
     from pypy.module.cpyext.api import generic_cpy_call_dont_decref

diff --git a/lib_pypy/pyrepl/unix_console.py b/lib_pypy/pyrepl/unix_console.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/unix_console.py
@@ -0,0 +1,567 @@
+#   Copyright 2000-2010 Michael Hudson-Doyle <micahel at gmail.com>
+#                       Antonio Cuni
+#                       Armin Rigo
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+import termios, select, os, struct, errno
+import signal, re, time, sys
+from fcntl import ioctl
+from pyrepl import curses
+from pyrepl.fancy_termios import tcgetattr, tcsetattr
+from pyrepl.console import Console, Event
+from pyrepl import unix_eventqueue
+
+class InvalidTerminal(RuntimeError):
+    pass
+
+_error = (termios.error, curses.error, InvalidTerminal)
+
+# there are arguments for changing this to "refresh"
+SIGWINCH_EVENT = 'repaint'
+
+FIONREAD = getattr(termios, "FIONREAD", None)
+TIOCGWINSZ = getattr(termios, "TIOCGWINSZ", None)
+
+def _my_getstr(cap, optional=0):
+    r = curses.tigetstr(cap)
+    if not optional and r is None:
+        raise InvalidTerminal, \
+              "terminal doesn't have the required '%s' capability"%cap
+    return r
+
+# at this point, can we say: AAAAAAAAAAAAAAAAAAAAAARGH!
+def maybe_add_baudrate(dict, rate):
+    name = 'B%d'%rate
+    if hasattr(termios, name):
+        dict[getattr(termios, name)] = rate
+
+ratedict = {}
+for r in [0, 110, 115200, 1200, 134, 150, 1800, 19200, 200, 230400,
+          2400, 300, 38400, 460800, 4800, 50, 57600, 600, 75, 9600]:
+    maybe_add_baudrate(ratedict, r)
+
+del r, maybe_add_baudrate
+
+delayprog = re.compile("\\$<([0-9]+)((?:/|\\*){0,2})>")
+
+try:
+    poll = select.poll
+except AttributeError:
+    # this is exactly the minumum necessary to support what we
+    # do with poll objects
+    class poll:
+        def __init__(self):
+            pass
+        def register(self, fd, flag):
+            self.fd = fd
+        def poll(self, timeout=None):
+            r,w,e = select.select([self.fd],[],[],timeout)
+            return r
+
+POLLIN = getattr(select, "POLLIN", None)
+
+class UnixConsole(Console):
+    def __init__(self, f_in=0, f_out=1, term=None, encoding=None):
+        if encoding is None:
+            encoding = sys.getdefaultencoding()
+            
+        self.encoding = encoding
+
+        if isinstance(f_in, int):
+            self.input_fd = f_in
+        else:
+            self.input_fd = f_in.fileno()
+
+        if isinstance(f_out, int):
+            self.output_fd = f_out
+        else:
+            self.output_fd = f_out.fileno()
+        
+        self.pollob = poll()
+        self.pollob.register(self.input_fd, POLLIN)
+        curses.setupterm(term, self.output_fd)
+        self.term = term
+        
+        self._bel   = _my_getstr("bel")
+        self._civis = _my_getstr("civis", optional=1)
+        self._clear = _my_getstr("clear")
+        self._cnorm = _my_getstr("cnorm", optional=1)
+        self._cub   = _my_getstr("cub",   optional=1)
+        self._cub1  = _my_getstr("cub1",  1)
+        self._cud   = _my_getstr("cud",   1)
+        self._cud1  = _my_getstr("cud1",  1)
+        self._cuf   = _my_getstr("cuf",   1)
+        self._cuf1  = _my_getstr("cuf1",  1)
+        self._cup   = _my_getstr("cup")
+        self._cuu   = _my_getstr("cuu",   1)
+        self._cuu1  = _my_getstr("cuu1",  1)
+        self._dch1  = _my_getstr("dch1",  1)
+        self._dch   = _my_getstr("dch",   1)
+        self._el    = _my_getstr("el")
+        self._hpa   = _my_getstr("hpa",   1)
+        self._ich   = _my_getstr("ich",   1)
+        self._ich1  = _my_getstr("ich1",  1)
+        self._ind   = _my_getstr("ind",   1)
+        self._pad   = _my_getstr("pad",   1)
+        self._ri    = _my_getstr("ri",    1)
+        self._rmkx  = _my_getstr("rmkx",  1)
+        self._smkx  = _my_getstr("smkx",  1)
+        
+        ## work out how we're going to sling the cursor around
+        if 0 and self._hpa: # hpa don't work in windows telnet :-(
+            self.__move_x = self.__move_x_hpa
+        elif self._cub and self._cuf:
+            self.__move_x = self.__move_x_cub_cuf
+        elif self._cub1 and self._cuf1:
+            self.__move_x = self.__move_x_cub1_cuf1
+        else:
+            raise RuntimeError, "insufficient terminal (horizontal)"
+
+        if self._cuu and self._cud:
+            self.__move_y = self.__move_y_cuu_cud
+        elif self._cuu1 and self._cud1:
+            self.__move_y = self.__move_y_cuu1_cud1
+        else:
+            raise RuntimeError, "insufficient terminal (vertical)"
+
+        if self._dch1:
+            self.dch1 = self._dch1
+        elif self._dch:
+            self.dch1 = curses.tparm(self._dch, 1)
+        else:
+            self.dch1 = None
+
+        if self._ich1:
+            self.ich1 = self._ich1
+        elif self._ich:
+            self.ich1 = curses.tparm(self._ich, 1)
+        else:
+            self.ich1 = None
+
+        self.__move = self.__move_short
+
+        self.event_queue = unix_eventqueue.EventQueue(self.input_fd)
+        self.partial_char = ''
+        self.cursor_visible = 1
+
+    def change_encoding(self, encoding):
+        self.encoding = encoding
+    
+    def refresh(self, screen, (cx, cy)):
+        # this function is still too long (over 90 lines)
+
+        if not self.__gone_tall:
+            while len(self.screen) < min(len(screen), self.height):
+                self.__hide_cursor()
+                self.__move(0, len(self.screen) - 1)
+                self.__write("\n")
+                self.__posxy = 0, len(self.screen)
+                self.screen.append("")
+        else:
+            while len(self.screen) < len(screen):
+                self.screen.append("")            
+
+        if len(screen) > self.height:
+            self.__gone_tall = 1
+            self.__move = self.__move_tall
+
+        px, py = self.__posxy
+        old_offset = offset = self.__offset
+        height = self.height
+
+        if 0:
+            global counter
+            try:
+                counter
+            except NameError:
+                counter = 0
+            self.__write_code(curses.tigetstr("setaf"), counter)
+            counter += 1
+            if counter > 8:
+                counter = 0
+
+        # we make sure the cursor is on the screen, and that we're
+        # using all of the screen if we can
+        if cy < offset:
+            offset = cy
+        elif cy >= offset + height:
+            offset = cy - height + 1
+        elif offset > 0 and len(screen) < offset + height:
+            offset = max(len(screen) - height, 0)
+            screen.append("")
+
+        oldscr = self.screen[old_offset:old_offset + height]
+        newscr = screen[offset:offset + height]
+
+        # use hardware scrolling if we have it.
+        if old_offset > offset and self._ri:
+            self.__hide_cursor()
+            self.__write_code(self._cup, 0, 0)
+            self.__posxy = 0, old_offset
+            for i in range(old_offset - offset):
+                self.__write_code(self._ri)
+                oldscr.pop(-1)
+                oldscr.insert(0, "")
+        elif old_offset < offset and self._ind:
+            self.__hide_cursor()
+            self.__write_code(self._cup, self.height - 1, 0)
+            self.__posxy = 0, old_offset + self.height - 1
+            for i in range(offset - old_offset):
+                self.__write_code(self._ind)
+                oldscr.pop(0)
+                oldscr.append("")
+
+        self.__offset = offset
+
+        for y, oldline, newline, in zip(range(offset, offset + height),
+                                        oldscr,
+                                        newscr):
+            if oldline != newline:
+                self.__write_changed_line(y, oldline, newline, px)
+                
+        y = len(newscr)
+        while y < len(oldscr):
+            self.__hide_cursor()
+            self.__move(0, y)
+            self.__posxy = 0, y
+            self.__write_code(self._el)
+            y += 1
+
+        self.__show_cursor()
+        
+        self.screen = screen
+        self.move_cursor(cx, cy)
+        self.flushoutput()
+
+    def __write_changed_line(self, y, oldline, newline, px):
+        # this is frustrating; there's no reason to test (say)
+        # self.dch1 inside the loop -- but alternative ways of
+        # structuring this function are equally painful (I'm trying to
+        # avoid writing code generators these days...)
+        x = 0
+        minlen = min(len(oldline), len(newline))
+        #
+        # reuse the oldline as much as possible, but stop as soon as we
+        # encounter an ESCAPE, because it might be the start of an escape
+        # sequene
+        while x < minlen and oldline[x] == newline[x] and newline[x] != '\x1b':
+            x += 1
+        if oldline[x:] == newline[x+1:] and self.ich1:
+            if ( y == self.__posxy[1] and x > self.__posxy[0]
+                 and oldline[px:x] == newline[px+1:x+1] ):
+                x = px
+            self.__move(x, y)
+            self.__write_code(self.ich1)
+            self.__write(newline[x])
+            self.__posxy = x + 1, y
+        elif x < minlen and oldline[x + 1:] == newline[x + 1:]:
+            self.__move(x, y)
+            self.__write(newline[x])
+            self.__posxy = x + 1, y
+        elif (self.dch1 and self.ich1 and len(newline) == self.width
+              and x < len(newline) - 2
+              and newline[x+1:-1] == oldline[x:-2]):
+            self.__hide_cursor()
+            self.__move(self.width - 2, y)
+            self.__posxy = self.width - 2, y
+            self.__write_code(self.dch1)
+            self.__move(x, y)
+            self.__write_code(self.ich1)
+            self.__write(newline[x])
+            self.__posxy = x + 1, y
+        else:
+            self.__hide_cursor()
+            self.__move(x, y)
+            if len(oldline) > len(newline):
+                self.__write_code(self._el)
+            self.__write(newline[x:])
+            self.__posxy = len(newline), y
+        
+        if '\x1b' in newline:
+            # ANSI escape characters are present, so we can't assume
+            # anything about the position of the cursor.  Moving the cursor
+            # to the left margin should work to get to a known position.
+            self.move_cursor(0, y)
+
+    def __write(self, text):
+        self.__buffer.append((text, 0))
+
+    def __write_code(self, fmt, *args):
+        self.__buffer.append((curses.tparm(fmt, *args), 1))
+
+    def __maybe_write_code(self, fmt, *args):
+        if fmt:
+            self.__write_code(fmt, *args)
+
+    def __move_y_cuu1_cud1(self, y):
+        dy = y - self.__posxy[1]
+        if dy > 0:
+            self.__write_code(dy*self._cud1)
+        elif dy < 0:
+            self.__write_code((-dy)*self._cuu1)
+
+    def __move_y_cuu_cud(self, y):
+        dy = y - self.__posxy[1]
+        if dy > 0:
+            self.__write_code(self._cud, dy)
+        elif dy < 0:
+            self.__write_code(self._cuu, -dy)
+
+    def __move_x_hpa(self, x):
+        if x != self.__posxy[0]:
+            self.__write_code(self._hpa, x)
+
+    def __move_x_cub1_cuf1(self, x):
+        dx = x - self.__posxy[0]
+        if dx > 0:
+            self.__write_code(self._cuf1*dx)
+        elif dx < 0:
+            self.__write_code(self._cub1*(-dx))
+
+    def __move_x_cub_cuf(self, x):
+        dx = x - self.__posxy[0]
+        if dx > 0:
+            self.__write_code(self._cuf, dx)
+        elif dx < 0:
+            self.__write_code(self._cub, -dx)
+
+    def __move_short(self, x, y):
+        self.__move_x(x)
+        self.__move_y(y)
+
+    def __move_tall(self, x, y):
+        assert 0 <= y - self.__offset < self.height, y - self.__offset
+        self.__write_code(self._cup, y - self.__offset, x)
+
+    def move_cursor(self, x, y):
+        if y < self.__offset or y >= self.__offset + self.height:
+            self.event_queue.insert(Event('scroll', None))
+        else:
+            self.__move(x, y)
+            self.__posxy = x, y
+            self.flushoutput()
+
+    def prepare(self):
+        # per-readline preparations:
+        self.__svtermstate = tcgetattr(self.input_fd)
+        raw = self.__svtermstate.copy()
+        raw.iflag &=~ (termios.BRKINT | termios.INPCK |
+                       termios.ISTRIP | termios.IXON)
+        raw.oflag &=~ (termios.OPOST)
+        raw.cflag &=~ (termios.CSIZE|termios.PARENB)
+        raw.cflag |=  (termios.CS8)
+        raw.lflag &=~ (termios.ICANON|termios.ECHO|
+                       termios.IEXTEN|(termios.ISIG*1))
+        raw.cc[termios.VMIN] = 1
+        raw.cc[termios.VTIME] = 0
+        tcsetattr(self.input_fd, termios.TCSADRAIN, raw)
+
+        self.screen = []
+        self.height, self.width = self.getheightwidth()
+
+        self.__buffer = []
+        
+        self.__posxy = 0, 0
+        self.__gone_tall = 0
+        self.__move = self.__move_short
+        self.__offset = 0
+
+        self.__maybe_write_code(self._smkx)
+
+        self.old_sigwinch = signal.signal(
+            signal.SIGWINCH, self.__sigwinch)
+
+    def restore(self):
+        self.__maybe_write_code(self._rmkx)
+        self.flushoutput()
+        tcsetattr(self.input_fd, termios.TCSADRAIN, self.__svtermstate)
+
+        signal.signal(signal.SIGWINCH, self.old_sigwinch)
+
+    def __sigwinch(self, signum, frame):
+        self.height, self.width = self.getheightwidth()
+        self.event_queue.insert(Event('resize', None))
+
+    def push_char(self, char):
+        self.partial_char += char
+        try:
+            c = unicode(self.partial_char, self.encoding)
+        except UnicodeError, e:
+            if len(e.args) > 4 and \
+                   e.args[4] == 'unexpected end of data':
+                pass
+            else:
+                raise
+        else:
+            self.partial_char = ''
+            self.event_queue.push(c)
+        
+    def get_event(self, block=1):
+        while self.event_queue.empty():
+            while 1: # All hail Unix!
+                try:
+                    self.push_char(os.read(self.input_fd, 1))
+                except (IOError, OSError), err:
+                    if err.errno == errno.EINTR:
+                        if not self.event_queue.empty():
+                            return self.event_queue.get()
+                        else:
+                            continue
+                    else:
+                        raise
+                else:
+                    break
+            if not block:
+                break
+        return self.event_queue.get()
+
+    def wait(self):
+        self.pollob.poll()
+
+    def set_cursor_vis(self, vis):
+        if vis:
+            self.__show_cursor()
+        else:
+            self.__hide_cursor()
+
+    def __hide_cursor(self):
+        if self.cursor_visible:
+            self.__maybe_write_code(self._civis)
+            self.cursor_visible = 0
+
+    def __show_cursor(self):
+        if not self.cursor_visible:
+            self.__maybe_write_code(self._cnorm)
+            self.cursor_visible = 1
+
+    def repaint_prep(self):
+        if not self.__gone_tall:
+            self.__posxy = 0, self.__posxy[1]
+            self.__write("\r")
+            ns = len(self.screen)*['\000'*self.width]
+            self.screen = ns
+        else:
+            self.__posxy = 0, self.__offset
+            self.__move(0, self.__offset)
+            ns = self.height*['\000'*self.width]
+            self.screen = ns
+
+    if TIOCGWINSZ:
+        def getheightwidth(self):
+            try:
+                return int(os.environ["LINES"]), int(os.environ["COLUMNS"])
+            except KeyError:
+                height, width = struct.unpack(
+                    "hhhh", ioctl(self.input_fd, TIOCGWINSZ, "\000"*8))[0:2]
+                if not height: return 25, 80
+                return height, width
+    else:
+        def getheightwidth(self):
+            try:
+                return int(os.environ["LINES"]), int(os.environ["COLUMNS"])
+            except KeyError:
+                return 25, 80
+
+    def forgetinput(self):
+        termios.tcflush(self.input_fd, termios.TCIFLUSH)
+
+    def flushoutput(self):
+        for text, iscode in self.__buffer:
+            if iscode:
+                self.__tputs(text)
+            else:
+                os.write(self.output_fd, text.encode(self.encoding))
+        del self.__buffer[:]
+
+    def __tputs(self, fmt, prog=delayprog):
+        """A Python implementation of the curses tputs function; the
+        curses one can't really be wrapped in a sane manner.
+
+        I have the strong suspicion that this is complexity that
+        will never do anyone any good."""
+        # using .get() means that things will blow up
+        # only if the bps is actually needed (which I'm
+        # betting is pretty unlkely)
+        bps = ratedict.get(self.__svtermstate.ospeed)
+        while 1:
+            m = prog.search(fmt)
+            if not m:
+                os.write(self.output_fd, fmt)
+                break
+            x, y = m.span()
+            os.write(self.output_fd, fmt[:x])
+            fmt = fmt[y:]
+            delay = int(m.group(1))
+            if '*' in m.group(2):
+                delay *= self.height
+            if self._pad:
+                nchars = (bps*delay)/1000
+                os.write(self.output_fd, self._pad*nchars)
+            else:
+                time.sleep(float(delay)/1000.0)
+
+    def finish(self):
+        y = len(self.screen) - 1
+        while y >= 0 and not self.screen[y]:
+            y -= 1
+        self.__move(0, min(y, self.height + self.__offset - 1))
+        self.__write("\n\r")
+        self.flushoutput()
+
+    def beep(self):
+        self.__maybe_write_code(self._bel)
+        self.flushoutput()
+
+    if FIONREAD:
+        def getpending(self):
+            e = Event('key', '', '')
+
+            while not self.event_queue.empty():
+                e2 = self.event_queue.get()
+                e.data += e2.data
+                e.raw += e.raw
+                
+            amount = struct.unpack(
+                "i", ioctl(self.input_fd, FIONREAD, "\0\0\0\0"))[0]
+            raw = unicode(os.read(self.input_fd, amount), self.encoding, 'replace')
+            e.data += raw
+            e.raw += raw
+            return e
+    else:
+        def getpending(self):
+            e = Event('key', '', '')
+
+            while not self.event_queue.empty():
+                e2 = self.event_queue.get()
+                e.data += e2.data
+                e.raw += e.raw
+                
+            amount = 10000
+            raw = unicode(os.read(self.input_fd, amount), self.encoding, 'replace')
+            e.data += raw
+            e.raw += raw
+            return e
+
+    def clear(self):
+        self.__write_code(self._clear)
+        self.__gone_tall = 1
+        self.__move = self.__move_tall
+        self.__posxy = 0, 0
+        self.screen = []
+


diff --git a/pypy/module/cpyext/test/test_object.py b/pypy/module/cpyext/test/test_object.py
--- a/pypy/module/cpyext/test/test_object.py
+++ b/pypy/module/cpyext/test/test_object.py
@@ -3,9 +3,8 @@
 from pypy.module.cpyext.test.test_api import BaseApiTest
 from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
 from pypy.rpython.lltypesystem import rffi, lltype
-from pypy.module.cpyext.api import Py_LT, Py_LE, Py_NE, Py_EQ,\
-    Py_GE, Py_GT, fopen, fclose, fwrite
-from pypy.tool.udir import udir
+from pypy.module.cpyext.api import (
+    Py_LT, Py_LE, Py_NE, Py_EQ, Py_GE, Py_GT)
 
 class TestObject(BaseApiTest):
     def test_IsTrue(self, space, api):
@@ -175,58 +174,23 @@
         assert api.PyObject_Compare(space.wrap(72), space.wrap(42)) == 1
         assert api.PyObject_Compare(space.wrap("a"), space.wrap("a")) == 0
 
+    def test_cmp(self, space, api):
+        w = space.wrap
+        with lltype.scoped_alloc(rffi.INTP.TO, 1) as ptr:
+            assert api.PyObject_Cmp(w(42), w(72), ptr) == 0
+            assert ptr[0] == -1
+            assert api.PyObject_Cmp(w("a"), w("a"), ptr) == 0
+            assert ptr[0] == 0
+            assert api.PyObject_Cmp(w(u"\xe9"), w("\xe9"), ptr) < 0
+            assert api.PyErr_Occurred()
+            api.PyErr_Clear()
+
     def test_unicode(self, space, api):
         assert space.unwrap(api.PyObject_Unicode(space.wrap([]))) == u"[]"
         assert space.unwrap(api.PyObject_Unicode(space.wrap("e"))) == u"e"
         assert api.PyObject_Unicode(space.wrap("\xe9")) is None
         api.PyErr_Clear()
 
-    def test_file_fromstring(self, space, api):
-        filename = rffi.str2charp(str(udir / "_test_file"))
-        mode = rffi.str2charp("wb")
-        w_file = api.PyFile_FromString(filename, mode)
-        rffi.free_charp(filename)
-        rffi.free_charp(mode)
-
-        assert api.PyFile_Check(w_file)
-        assert api.PyFile_CheckExact(w_file)
-        assert not api.PyFile_Check(space.wrap("text"))
-
-        space.call_method(w_file, "write", space.wrap("text"))
-        space.call_method(w_file, "close")
-        assert (udir / "_test_file").read() == "text"
-
-    def test_file_getline(self, space, api):
-        filename = rffi.str2charp(str(udir / "_test_file"))
-
-        mode = rffi.str2charp("w")
-        w_file = api.PyFile_FromString(filename, mode)
-        space.call_method(w_file, "write",
-                          space.wrap("line1\nline2\nline3\nline4"))
-        space.call_method(w_file, "close")
-
-        rffi.free_charp(mode)
-        mode = rffi.str2charp("r")
-        w_file = api.PyFile_FromString(filename, mode)
-        rffi.free_charp(filename)
-        rffi.free_charp(mode)
-
-        w_line = api.PyFile_GetLine(w_file, 0)
-        assert space.str_w(w_line) == "line1\n"
-
-        w_line = api.PyFile_GetLine(w_file, 4)
-        assert space.str_w(w_line) == "line"
-
-        w_line = api.PyFile_GetLine(w_file, 0)
-        assert space.str_w(w_line) == "2\n"
-
-        # XXX We ought to raise an EOFError here, but don't
-        w_line = api.PyFile_GetLine(w_file, -1)
-        # assert api.PyErr_Occurred() is space.w_EOFError
-        assert space.str_w(w_line) == "line3\n"
-
-        space.call_method(w_file, "close")
-
 class AppTestObject(AppTestCpythonExtensionBase):
     def setup_class(cls):
         AppTestCpythonExtensionBase.setup_class.im_func(cls)

diff --git a/lib_pypy/pyrepl/tests/wishes.py b/lib_pypy/pyrepl/tests/wishes.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/tests/wishes.py
@@ -0,0 +1,38 @@
+#   Copyright 2000-2004 Michael Hudson-Doyle <micahel at gmail.com>
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+from pyrepl.console import Event
+from pyrepl.tests.infrastructure import ReaderTestCase, EA, run_testcase
+
+# this test case should contain as-verbatim-as-possible versions of
+# (applicable) feature requests
+
+class WishesTestCase(ReaderTestCase):
+
+    def test_quoted_insert_repeat(self):
+        self.run_test([(('digit-arg', '3'),      ['']),
+                       ( 'quoted-insert',        ['']),
+                       (('self-insert', '\033'), ['^[^[^[']),
+                       ( 'accept',               None)])
+
+def test():
+    run_testcase(WishesTestCase)
+
+if __name__ == '__main__':
+    test()

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
@@ -278,6 +278,22 @@
             rex_mem_reg_plus_scaled_reg_plus_const)
 
 # ____________________________________________________________
+# Emit a mod/rm referencing an immediate address that fits in 32-bit
+# (the immediate address itself must be explicitely encoded as well,
+# with immediate(argnum)).
+
+def encode_abs(mc, _1, _2, orbyte):
+    # expands to either '\x05' on 32-bit, or '\x04\x25' or 64-bit
+    if mc.WORD == 8:
+        mc.writechar(chr(0x04 | orbyte))
+        mc.writechar(chr(0x25))
+    else:
+        mc.writechar(chr(0x05 | orbyte))
+    return 0
+
+abs_ = encode_abs, 0, None, None
+
+# ____________________________________________________________
 # For 64-bits mode: the REX.W, REX.R, REX.X, REG.B prefixes
 
 REX_W = 8
@@ -348,7 +364,9 @@
     INSN_br = insn(rex_w, chr(base+1), register(2,8), stack_bp(1))
     INSN_rb = insn(rex_w, chr(base+3), register(1,8), stack_bp(2))
     INSN_rm = insn(rex_w, chr(base+3), register(1,8), mem_reg_plus_const(2))
-    INSN_rj = insn(rex_w, chr(base+3), register(1,8), '\x05', immediate(2))
+    INSN_rj = insn(rex_w, chr(base+3), register(1,8), abs_, immediate(2))
+    INSN_ji8 = insn(rex_w, '\x83', orbyte(base), abs_, immediate(1),
+                    immediate(2,'b'))
     INSN_bi8 = insn(rex_w, '\x83', orbyte(base), stack_bp(1), immediate(2,'b'))
     INSN_bi32= insn(rex_w, '\x81', orbyte(base), stack_bp(1), immediate(2))
 
@@ -366,7 +384,8 @@
             INSN_bi32(mc, offset, immed)
     INSN_bi._always_inline_ = True      # try to constant-fold single_byte()
 
-    return INSN_ri, INSN_rr, INSN_rb, INSN_bi, INSN_br, INSN_rm, INSN_rj
+    return (INSN_ri, INSN_rr, INSN_rb, INSN_bi, INSN_br, INSN_rm, INSN_rj,
+            INSN_ji8)
 
 def select_8_or_32_bit_immed(insn_8, insn_32):
     def INSN(*args):
@@ -444,23 +463,25 @@
 
     # ------------------------------ Arithmetic ------------------------------
 
-    ADD_ri, ADD_rr, ADD_rb, _, _, ADD_rm, ADD_rj = common_modes(0)
-    OR_ri,  OR_rr,  OR_rb,  _, _, OR_rm,  OR_rj  = common_modes(1)
-    AND_ri, AND_rr, AND_rb, _, _, AND_rm, AND_rj = common_modes(4)
-    SUB_ri, SUB_rr, SUB_rb, _, _, SUB_rm, SUB_rj = common_modes(5)
-    SBB_ri, SBB_rr, SBB_rb, _, _, SBB_rm, SBB_rj = common_modes(3)
-    XOR_ri, XOR_rr, XOR_rb, _, _, XOR_rm, XOR_rj = common_modes(6)
-    CMP_ri, CMP_rr, CMP_rb, CMP_bi, CMP_br, CMP_rm, CMP_rj = common_modes(7)
+    ADD_ri, ADD_rr, ADD_rb, _, _, ADD_rm, ADD_rj, _ = common_modes(0)
+    OR_ri,  OR_rr,  OR_rb,  _, _, OR_rm,  OR_rj,  _ = common_modes(1)
+    AND_ri, AND_rr, AND_rb, _, _, AND_rm, AND_rj, _ = common_modes(4)
+    SUB_ri, SUB_rr, SUB_rb, _, _, SUB_rm, SUB_rj, SUB_ji8 = common_modes(5)
+    SBB_ri, SBB_rr, SBB_rb, _, _, SBB_rm, SBB_rj, _ = common_modes(3)
+    XOR_ri, XOR_rr, XOR_rb, _, _, XOR_rm, XOR_rj, _ = common_modes(6)
+    CMP_ri, CMP_rr, CMP_rb, CMP_bi, CMP_br, CMP_rm, CMP_rj, _ = common_modes(7)
 
     CMP_mi8 = insn(rex_w, '\x83', orbyte(7<<3), mem_reg_plus_const(1), immediate(2, 'b'))
     CMP_mi32 = insn(rex_w, '\x81', orbyte(7<<3), mem_reg_plus_const(1), immediate(2))
     CMP_mi = select_8_or_32_bit_immed(CMP_mi8, CMP_mi32)
     CMP_mr = insn(rex_w, '\x39', register(2, 8), mem_reg_plus_const(1))
 
-    CMP_ji8 = insn(rex_w, '\x83', '\x3D', immediate(1), immediate(2, 'b'))
-    CMP_ji32 = insn(rex_w, '\x81', '\x3D', immediate(1), immediate(2))
+    CMP_ji8 = insn(rex_w, '\x83', orbyte(7<<3), abs_,
+                   immediate(1), immediate(2, 'b'))
+    CMP_ji32 = insn(rex_w, '\x81', orbyte(7<<3), abs_,
+                    immediate(1), immediate(2))
     CMP_ji = select_8_or_32_bit_immed(CMP_ji8, CMP_ji32)
-    CMP_jr = insn(rex_w, '\x39', register(2, 8), '\x05', immediate(1))
+    CMP_jr = insn(rex_w, '\x39', register(2, 8), abs_, immediate(1))
 
     CMP32_mi = insn(rex_nw, '\x81', orbyte(7<<3), mem_reg_plus_const(1), immediate(2))
 
@@ -505,10 +526,11 @@
     POP_b = insn(rex_nw, '\x8F', orbyte(0<<3), stack_bp(1))
 
     LEA_rb = insn(rex_w, '\x8D', register(1,8), stack_bp(2))
+    LEA_rs = insn(rex_w, '\x8D', register(1,8), stack_sp(2))
     LEA32_rb = insn(rex_w, '\x8D', register(1,8),stack_bp(2,force_32bits=True))
     LEA_ra = insn(rex_w, '\x8D', register(1, 8), mem_reg_plus_scaled_reg_plus_const(2))
     LEA_rm = insn(rex_w, '\x8D', register(1, 8), mem_reg_plus_const(2))
-    LEA_rj = insn(rex_w, '\x8D', register(1, 8), '\x05', immediate(2))
+    LEA_rj = insn(rex_w, '\x8D', register(1, 8), abs_, immediate(2))
 
     CALL_l = insn('\xE8', relative(1))
     CALL_r = insn(rex_nw, '\xFF', register(1), chr(0xC0 | (2<<3)))
@@ -534,12 +556,15 @@
     CDQ = insn(rex_nw, '\x99')
 
     TEST8_mi = insn(rex_nw, '\xF6', orbyte(0<<3), mem_reg_plus_const(1), immediate(2, 'b'))
-    TEST8_ji = insn(rex_nw, '\xF6', orbyte(0<<3), '\x05', immediate(1), immediate(2, 'b'))
+    TEST8_ji = insn(rex_nw, '\xF6', orbyte(0<<3), abs_, immediate(1), immediate(2, 'b'))
     TEST_rr = insn(rex_w, '\x85', register(2,8), register(1), '\xC0')
 
     # x87 instructions
     FSTP_b = insn('\xDD', orbyte(3<<3), stack_bp(1))
 
+    # reserved as an illegal instruction
+    UD2 = insn('\x0F\x0B')
+
     # ------------------------------ SSE2 ------------------------------
 
     # Conversion
@@ -639,7 +664,7 @@
     add_insn('s', stack_sp(modrm_argnum))
     add_insn('m', mem_reg_plus_const(modrm_argnum))
     add_insn('a', mem_reg_plus_scaled_reg_plus_const(modrm_argnum))
-    add_insn('j', '\x05', immediate(modrm_argnum))
+    add_insn('j', abs_, immediate(modrm_argnum))
 
 # Define a regular MOV, and a variant MOV32 that only uses the low 4 bytes of a
 # register
@@ -680,7 +705,7 @@
     #
     assert insnname_template.count('*') == 1
     add_insn('x', register(2), '\xC0')
-    add_insn('j', '\x05', immediate(2))
+    add_insn('j', abs_, immediate(2))
 
 define_pxmm_insn('PADDQ_x*',     '\xD4')
 define_pxmm_insn('PSUBQ_x*',     '\xFB')

diff --git a/pypy/jit/metainterp/virtualref.py b/pypy/jit/metainterp/virtualref.py
--- a/pypy/jit/metainterp/virtualref.py
+++ b/pypy/jit/metainterp/virtualref.py
@@ -13,7 +13,6 @@
         self.JIT_VIRTUAL_REF = lltype.GcStruct('JitVirtualRef',
             ('super', rclass.OBJECT),
             ('virtual_token', lltype.Signed),
-            ('virtualref_index', lltype.Signed),
             ('forced', rclass.OBJECTPTR))
         self.jit_virtual_ref_vtable = lltype.malloc(rclass.OBJECT_VTABLE,
                                                     zero=True, flavor='raw',
@@ -27,8 +26,6 @@
         fielddescrof = self.cpu.fielddescrof
         self.descr_virtual_token = fielddescrof(self.JIT_VIRTUAL_REF,
                                                 'virtual_token')
-        self.descr_virtualref_index = fielddescrof(self.JIT_VIRTUAL_REF,
-                                                   'virtualref_index')
         self.descr_forced = fielddescrof(self.JIT_VIRTUAL_REF, 'forced')
         #
         # record the type JIT_VIRTUAL_REF explicitly in the rtyper, too

diff --git a/pypy/interpreter/executioncontext.py b/pypy/interpreter/executioncontext.py
--- a/pypy/interpreter/executioncontext.py
+++ b/pypy/interpreter/executioncontext.py
@@ -519,7 +519,7 @@
             return
         code = frame.pycode
         if frame.instr_lb <= frame.last_instr < frame.instr_ub:
-            if frame.last_instr <= frame.instr_prev:
+            if frame.last_instr < frame.instr_prev_plus_one:
                 # We jumped backwards in the same line.
                 executioncontext._trace(frame, 'line', self.space.w_None)
         else:
@@ -557,5 +557,5 @@
                 frame.f_lineno = line
                 executioncontext._trace(frame, 'line', self.space.w_None)
 
-        frame.instr_prev = frame.last_instr
+        frame.instr_prev_plus_one = frame.last_instr + 1
         self.space.frame_trace_action.fire()     # continue tracing

diff --git a/pypy/translator/backendopt/test/test_merge_if_blocks.py b/pypy/translator/backendopt/test/test_merge_if_blocks.py
--- a/pypy/translator/backendopt/test/test_merge_if_blocks.py
+++ b/pypy/translator/backendopt/test/test_merge_if_blocks.py
@@ -2,7 +2,7 @@
 from pypy.translator.backendopt.merge_if_blocks import merge_if_blocks
 from pypy.translator.backendopt.all import backend_optimizations
 from pypy.translator.translator import TranslationContext, graphof as tgraphof
-from pypy.objspace.flow.model import flatten, Block
+from pypy.objspace.flow.model import Block
 from pypy.translator.backendopt.removenoops import remove_same_as
 from pypy.rpython.llinterp import LLInterpreter
 from pypy.rlib.rarithmetic import r_uint, r_ulonglong, r_longlong, r_int

diff --git a/pypy/translator/backendopt/constfold.py b/pypy/translator/backendopt/constfold.py
--- a/pypy/translator/backendopt/constfold.py
+++ b/pypy/translator/backendopt/constfold.py
@@ -1,19 +1,16 @@
 from pypy.objspace.flow.model import Constant, Variable, SpaceOperation
 from pypy.objspace.flow.model import c_last_exception
 from pypy.objspace.flow.model import mkentrymap
-from pypy.translator.backendopt.support import split_block_with_keepalive
 from pypy.translator.backendopt.support import log
 from pypy.translator.simplify import eliminate_empty_blocks
-from pypy.translator.unsimplify import insert_empty_block
+from pypy.translator.unsimplify import insert_empty_block, split_block
 from pypy.rpython.lltypesystem.lloperation import llop
 from pypy.rpython.lltypesystem import lltype
 
 
 def fold_op_list(operations, constants, exit_early=False, exc_catch=False):
     newops = []
-    keepalives = []
     folded_count = 0
-    first_sideeffect_index = None
     for spaceop in operations:
         vargsmodif = False
         vargs = []
@@ -29,10 +26,9 @@
         try:
             op = getattr(llop, spaceop.opname)
         except AttributeError:
-            sideeffects = True
+            pass
         else:
-            sideeffects = op.sideeffects
-            if not sideeffects and len(args) == len(vargs):
+            if not op.sideeffects and len(args) == len(vargs):
                 RESTYPE = spaceop.result.concretetype
                 try:
                     result = op(RESTYPE, *args)
@@ -53,10 +49,6 @@
         # failed to fold an operation, exit early if requested
         if exit_early:
             return folded_count
-        if spaceop.opname == 'keepalive' and first_sideeffect_index is None:
-            if vargsmodif:
-                continue    # keepalive(constant) is not useful
-            keepalives.append(spaceop)
         else:
             if vargsmodif:
                 if (spaceop.opname == 'indirect_call'
@@ -66,20 +58,11 @@
                 else:
                     spaceop = SpaceOperation(spaceop.opname, vargs,
                                              spaceop.result)
-            if sideeffects and first_sideeffect_index is None:
-                first_sideeffect_index = len(newops)
             newops.append(spaceop)
     # end
     if exit_early:
         return folded_count
     else:
-        # move the keepalives to the end of the block, which makes the life
-        # of prepare_constant_fold_link() easier.  Don't put them past the
-        # exception-raising operation, though.  There is also no point in
-        # moving them past the first sideeffect-ing operation.
-        if first_sideeffect_index is None:
-            first_sideeffect_index = len(newops) - exc_catch
-        newops[first_sideeffect_index:first_sideeffect_index] = keepalives
         return newops
 
 def constant_fold_block(block):
@@ -177,33 +160,23 @@
     if block.exitswitch == c_last_exception:
         n -= 1
     # is the next, non-folded operation an indirect_call?
-    m = folded_count
-    while m < n and block.operations[m].opname == 'keepalive':
-        m += 1
-    if m < n:
-        nextop = block.operations[m]
+    if folded_count < n:
+        nextop = block.operations[folded_count]
         if nextop.opname == 'indirect_call' and nextop.args[0] in constants:
             # indirect_call -> direct_call
             callargs = [constants[nextop.args[0]]]
             constants1 = constants.copy()
             complete_constants(link, constants1)
-            newkeepalives = []
-            for i in range(folded_count, m):
-                [v] = block.operations[i].args
-                v = constants1.get(v, v)
-                v_void = Variable()
-                v_void.concretetype = lltype.Void
-                newkeepalives.append(SpaceOperation('keepalive', [v], v_void))
             for v in nextop.args[1:-1]:
                 callargs.append(constants1.get(v, v))
             v_result = Variable(nextop.result)
             v_result.concretetype = nextop.result.concretetype
             constants[nextop.result] = v_result
             callop = SpaceOperation('direct_call', callargs, v_result)
-            newblock = insert_empty_block(None, link, newkeepalives + [callop])
+            newblock = insert_empty_block(None, link, [callop])
             [link] = newblock.exits
             assert link.target is block
-            folded_count = m+1
+            folded_count += 1
 
     if folded_count > 0:
         splits = splitblocks.setdefault(block, [])
@@ -226,7 +199,7 @@
                 splitlink = block.exits[0]
             else:
                 # split the block at the given position
-                splitlink = split_block_with_keepalive(block, position)
+                splitlink = split_block(None, block, position)
                 assert list(block.exits) == [splitlink]
             assert link.target is block
             assert splitlink.prevblock is block

diff --git a/pypy/translator/test/test_simplify.py b/pypy/translator/test/test_simplify.py
--- a/pypy/translator/test/test_simplify.py
+++ b/pypy/translator/test/test_simplify.py
@@ -3,7 +3,7 @@
 from pypy.translator.backendopt.all import backend_optimizations
 from pypy.translator.simplify import (get_graph, transform_dead_op_vars,
                                       desugar_isinstance)
-from pypy.objspace.flow.model import traverse, Block, Constant, summary
+from pypy.objspace.flow.model import Block, Constant, summary
 from pypy import conftest
 
 def translate(func, argtypes, backend_optimize=True):
@@ -156,36 +156,6 @@
     assert graph.startblock.operations[-1].opname == 'direct_call'
 
 
-def test_remove_pointless_keepalive():
-    from pypy.rlib import objectmodel
-    class C:
-        y = None
-        z1 = None
-        z2 = None
-
-    def g():
-        return C()
-
-    def f(i):
-        c = g()
-        c.y
-        if i:
-            n = c.z1
-        else:
-            n = c.z2
-        objectmodel.keepalive_until_here(c, n)
-
-    graph, t = translate(f, [bool])
-
-    #t.view()
-
-    for block in graph.iterblocks():
-        for op in block.operations:
-            assert op.opname != 'getfield'
-            if op.opname == 'keepalive':
-                assert op.args[0] in graph.getargs()
-
-
 def test_remove_identical_variables():
     def g(code):
         pc = 0

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
@@ -107,7 +107,8 @@
                 self.bytecode_no = int(bytecode_no)
         self.operations = operations
         self.storage = storage
-        self.code = storage.disassemble_code(self.filename, self.startlineno)
+        self.code = storage.disassemble_code(self.filename, self.startlineno,
+                                             self.name)
 
     def repr(self):
         if self.filename is None:

diff --git a/pypy/module/posix/app_posix.py b/pypy/module/posix/app_posix.py
--- a/pypy/module/posix/app_posix.py
+++ b/pypy/module/posix/app_posix.py
@@ -190,14 +190,30 @@
 
     def wait():
         """ wait() -> (pid, status)
-    
+
         Wait for completion of a child process.
         """
         return posix.waitpid(-1, 0)
 
+    def wait3(options):
+        """ wait3(options) -> (pid, status, rusage)
+
+        Wait for completion of a child process and provides resource usage informations
+        """
+        from _pypy_wait import wait3
+        return wait3(options)
+
+    def wait4(pid, options):
+        """ wait4(pid, options) -> (pid, status, rusage)
+
+        Wait for completion of the child process "pid" and provides resource usage informations
+        """
+        from _pypy_wait import wait4
+        return wait4(pid, options)
+
 else:
     # Windows implementations
-    
+
     # Supply os.popen() based on subprocess
     def popen(cmd, mode="r", bufsize=-1):
         """popen(command [, mode='r' [, bufsize]]) -> pipe
@@ -285,7 +301,7 @@
             raise TypeError("invalid cmd type (%s, expected string)" %
                             (type(cmd),))
         return cmd
-        
+
     # A proxy for a file whose close waits for the process
     class _wrap_close(object):
         def __init__(self, stream, proc):

diff --git a/lib_pypy/pypy_test/test_os_wait.py b/lib_pypy/pypy_test/test_os_wait.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pypy_test/test_os_wait.py
@@ -0,0 +1,44 @@
+# Generates the resource cache
+from __future__ import absolute_import
+from lib_pypy.ctypes_config_cache import rebuild
+rebuild.rebuild_one('resource.ctc.py')
+
+import os
+
+from lib_pypy._pypy_wait import wait3, wait4
+
+if hasattr(os, 'wait3'):
+    def test_os_wait3():
+        exit_status = 0x33
+
+        if not hasattr(os, "fork"):
+            skip("Need fork() to test wait3()")
+
+        child = os.fork()
+        if child == 0: # in child
+            os._exit(exit_status)
+        else:
+            pid, status, rusage = wait3(0)
+            assert child == pid
+            assert os.WIFEXITED(status)
+            assert os.WEXITSTATUS(status) == exit_status
+            assert isinstance(rusage.ru_utime, float)
+            assert isinstance(rusage.ru_maxrss, int)
+
+if hasattr(os, 'wait4'):
+    def test_os_wait4():
+        exit_status = 0x33
+
+        if not hasattr(os, "fork"):
+            skip("Need fork() to test wait4()")
+
+        child = os.fork()
+        if child == 0: # in child
+            os._exit(exit_status)
+        else:
+            pid, status, rusage = wait4(child, 0)
+            assert child == pid
+            assert os.WIFEXITED(status)
+            assert os.WEXITSTATUS(status) == exit_status
+            assert isinstance(rusage.ru_utime, float)
+            assert isinstance(rusage.ru_maxrss, int)

diff --git a/pypy/doc/config/confrest.py b/pypy/doc/config/confrest.py
--- a/pypy/doc/config/confrest.py
+++ b/pypy/doc/config/confrest.py
@@ -7,7 +7,6 @@
 all_optiondescrs = [pypyoption.pypy_optiondescription,
                     translationoption.translation_optiondescription,
                    ]
-
 start_to_descr = dict([(descr._name, descr) for descr in all_optiondescrs])
 
 class PyPyPage(PyPyPage): 
@@ -29,7 +28,7 @@
     Page = PyPyPage 
 
     def get_content(self, txtpath, encoding):
-        if txtpath.basename == "commandline.txt":
+        if txtpath.basename == "commandline.rst":
             result = []
             for line in txtpath.read().splitlines():
                 if line.startswith('.. GENERATE:'):

diff --git a/pypy/module/thread/__init__.py b/pypy/module/thread/__init__.py
--- a/pypy/module/thread/__init__.py
+++ b/pypy/module/thread/__init__.py
@@ -12,12 +12,13 @@
         'get_ident':              'os_thread.get_ident',
         'exit':                   'os_thread.exit',
         'exit_thread':            'os_thread.exit', # obsolete synonym
+        'interrupt_main':         'os_thread.interrupt_main',
         'stack_size':             'os_thread.stack_size',
         '_count':                 'os_thread._count',
         'allocate_lock':          'os_lock.allocate_lock',
         'allocate':               'os_lock.allocate_lock',  # obsolete synonym
-        'LockType':               'os_lock.getlocktype(space)',
-        '_local':                 'os_local.getlocaltype(space)',
+        'LockType':               'os_lock.Lock',
+        '_local':                 'os_local.Local',
         'error':                  'space.fromcache(error.Cache).w_error',
     }
 

diff --git a/pypy/jit/metainterp/compile.py b/pypy/jit/metainterp/compile.py
--- a/pypy/jit/metainterp/compile.py
+++ b/pypy/jit/metainterp/compile.py
@@ -382,7 +382,7 @@
         send_bridge_to_backend(metainterp.staticdata, self, inputargs,
                                new_loop.operations, new_loop.token)
 
-    def copy_all_attrbutes_into(self, res):
+    def copy_all_attributes_into(self, res):
         # XXX a bit ugly to have to list them all here
         res.rd_snapshot = self.rd_snapshot
         res.rd_frame_info_list = self.rd_frame_info_list
@@ -393,13 +393,13 @@
 
     def _clone_if_mutable(self):
         res = ResumeGuardDescr()
-        self.copy_all_attrbutes_into(res)
+        self.copy_all_attributes_into(res)
         return res
 
 class ResumeAtPositionDescr(ResumeGuardDescr):
     def _clone_if_mutable(self):
         res = ResumeAtPositionDescr()
-        self.copy_all_attrbutes_into(res)
+        self.copy_all_attributes_into(res)
         return res
 
 class ResumeGuardForcedDescr(ResumeGuardDescr):
@@ -473,7 +473,7 @@
     def _clone_if_mutable(self):
         res = ResumeGuardForcedDescr(self.metainterp_sd,
                                      self.jitdriver_sd)
-        self.copy_all_attrbutes_into(res)
+        self.copy_all_attributes_into(res)
         return res
 
 

diff --git a/pypy/jit/metainterp/test/test_optimizebasic.py b/pypy/jit/metainterp/test/test_optimizebasic.py
--- a/pypy/jit/metainterp/test/test_optimizebasic.py
+++ b/pypy/jit/metainterp/test/test_optimizebasic.py
@@ -256,7 +256,7 @@
         loop.call_pure_results = args_dict()
         if call_pure_results is not None:
             for k, v in call_pure_results.items():
-                loop.call_pure_results[list(k)] = v        
+                loop.call_pure_results[list(k)] = v
         metainterp_sd = FakeMetaInterpStaticData(self.cpu)
         if hasattr(self, 'vrefinfo'):
             metainterp_sd.virtualref_info = self.vrefinfo
@@ -2889,7 +2889,7 @@
         # the result of the call, recorded as the first arg), or turned into
         # a regular CALL.
         arg_consts = [ConstInt(i) for i in (123456, 4, 5, 6)]
-        call_pure_results = {tuple(arg_consts): ConstInt(42)}        
+        call_pure_results = {tuple(arg_consts): ConstInt(42)}
         ops = '''
         [i0, i1, i2]
         escape(i1)
@@ -2934,7 +2934,6 @@
         i0 = force_token()
         p2 = new_with_vtable(ConstClass(jit_virtual_ref_vtable))
         setfield_gc(p2, i0, descr=virtualtokendescr)
-        setfield_gc(p2, 5, descr=virtualrefindexdescr)
         escape(p2)
         setfield_gc(p2, p1, descr=virtualforceddescr)
         setfield_gc(p2, -3, descr=virtualtokendescr)
@@ -2967,7 +2966,6 @@
         #
         p2 = new_with_vtable(ConstClass(jit_virtual_ref_vtable))
         setfield_gc(p2, i3, descr=virtualtokendescr)
-        setfield_gc(p2, 3, descr=virtualrefindexdescr)
         setfield_gc(p0, p2, descr=nextdescr)
         #
         call_may_force(i1, descr=mayforcevirtdescr)
@@ -3008,7 +3006,6 @@
         #
         p2 = new_with_vtable(ConstClass(jit_virtual_ref_vtable))
         setfield_gc(p2, i3, descr=virtualtokendescr)
-        setfield_gc(p2, 2, descr=virtualrefindexdescr)
         setfield_gc(p0, p2, descr=nextdescr)
         #
         call_may_force(i1, descr=mayforcevirtdescr)
@@ -3065,7 +3062,7 @@
         self.loop.inputargs[0].value = self.nodeobjvalue
         self.check_expanded_fail_descr('''p2, p1
             p0.refdescr = p2
-            where p2 is a jit_virtual_ref_vtable, virtualtokendescr=i3, virtualrefindexdescr=2
+            where p2 is a jit_virtual_ref_vtable, virtualtokendescr=i3
             where p1 is a node_vtable, nextdescr=p1b
             where p1b is a node_vtable, valuedescr=i1
             ''', rop.GUARD_NO_EXCEPTION)
@@ -3087,7 +3084,6 @@
         i3 = force_token()
         p2 = new_with_vtable(ConstClass(jit_virtual_ref_vtable))
         setfield_gc(p2, i3, descr=virtualtokendescr)
-        setfield_gc(p2, 7, descr=virtualrefindexdescr)
         escape(p2)
         p1 = new_with_vtable(ConstClass(node_vtable))
         setfield_gc(p2, p1, descr=virtualforceddescr)
@@ -3114,7 +3110,6 @@
         i3 = force_token()
         p2 = new_with_vtable(ConstClass(jit_virtual_ref_vtable))
         setfield_gc(p2, i3, descr=virtualtokendescr)
-        setfield_gc(p2, 23, descr=virtualrefindexdescr)
         escape(p2)
         setfield_gc(p2, p1, descr=virtualforceddescr)
         setfield_gc(p2, -3, descr=virtualtokendescr)
@@ -3363,7 +3358,7 @@
         i1 = int_lt(i0, 4)
         guard_true(i1) []
         i1p = int_gt(i0, -4)
-        guard_true(i1p) []        
+        guard_true(i1p) []
         i2 = int_sub(i0, 10)
         i3 = int_lt(i2, -5)
         guard_true(i3) []
@@ -3374,7 +3369,7 @@
         i1 = int_lt(i0, 4)
         guard_true(i1) []
         i1p = int_gt(i0, -4)
-        guard_true(i1p) []        
+        guard_true(i1p) []
         i2 = int_sub(i0, 10)
         jump(i0)
         """

diff --git a/pypy/module/cpyext/test/test_arraymodule.py b/pypy/module/cpyext/test/test_arraymodule.py
--- a/pypy/module/cpyext/test/test_arraymodule.py
+++ b/pypy/module/cpyext/test/test_arraymodule.py
@@ -42,3 +42,13 @@
         assert arr[1:].tolist() == [2,3,4]
         assert arr[:2].tolist() == [1,2]
         assert arr[1:3].tolist() == [2,3]
+
+    def test_buffer(self):
+        module = self.import_module(name='array')
+        arr = module.array('i', [1,2,3,4])
+        # XXX big-endian
+        assert str(buffer(arr)) == ('\x01\0\0\0'
+                                    '\x02\0\0\0'
+                                    '\x03\0\0\0'
+                                    '\x04\0\0\0')
+

diff --git a/pypy/rpython/lltypesystem/rdict.py b/pypy/rpython/lltypesystem/rdict.py
--- a/pypy/rpython/lltypesystem/rdict.py
+++ b/pypy/rpython/lltypesystem/rdict.py
@@ -4,12 +4,15 @@
 from pypy.rpython.rdict import AbstractDictRepr, AbstractDictIteratorRepr,\
      rtype_newdict
 from pypy.rpython.lltypesystem import lltype
-from pypy.rlib.rarithmetic import r_uint, intmask
+from pypy.rlib.rarithmetic import r_uint, intmask, LONG_BIT
 from pypy.rlib.objectmodel import hlinvoke
 from pypy.rpython import robject
-from pypy.rlib import objectmodel
+from pypy.rlib import objectmodel, jit
 from pypy.rpython import rmodel
 
+HIGHEST_BIT = intmask(1 << (LONG_BIT - 1))
+MASK = intmask(HIGHEST_BIT - 1)
+
 # ____________________________________________________________
 #
 #  generic implementation of RPython dictionary, with parametric DICTKEY and
@@ -405,6 +408,10 @@
     ENTRIES = lltype.typeOf(entries).TO
     return ENTRIES.fasthashfn(entries[i].key)
 
+ at jit.dont_look_inside
+def ll_get_value(d, i):
+    return d.entries[i].value
+
 def ll_keyhash_custom(d, key):
     DICT = lltype.typeOf(d).TO
     return hlinvoke(DICT.r_rdict_hashfn, d.fnkeyhash, key)
@@ -422,18 +429,21 @@
 
 def ll_dict_getitem(d, key):
     i = ll_dict_lookup(d, key, d.keyhash(key))
-    entries = d.entries
-    if entries.valid(i):
-        return entries[i].value 
-    else: 
-        raise KeyError 
-ll_dict_getitem.oopspec = 'dict.getitem(d, key)'
+    if not i & HIGHEST_BIT:
+        return ll_get_value(d, i)
+    else:
+        raise KeyError
 
 def ll_dict_setitem(d, key, value):
     hash = d.keyhash(key)
     i = ll_dict_lookup(d, key, hash)
+    return _ll_dict_setitem_lookup_done(d, key, value, hash, i)
+
+ at jit.dont_look_inside
+def _ll_dict_setitem_lookup_done(d, key, value, hash, i):
+    valid = (i & HIGHEST_BIT) == 0
+    i = i & MASK
     everused = d.entries.everused(i)
-    valid    = d.entries.valid(i)
     # set up the new entry
     ENTRY = lltype.typeOf(d.entries).TO.OF
     entry = d.entries[i]
@@ -449,7 +459,6 @@
         d.num_pristine_entries -= 1
         if d.num_pristine_entries <= len(d.entries) / 3:
             ll_dict_resize(d)
-ll_dict_setitem.oopspec = 'dict.setitem(d, key, value)'
 
 def ll_dict_insertclean(d, key, value, hash):
     # Internal routine used by ll_dict_resize() to insert an item which is
@@ -470,7 +479,7 @@
 
 def ll_dict_delitem(d, key):
     i = ll_dict_lookup(d, key, d.keyhash(key))
-    if not d.entries.valid(i):
+    if i & HIGHEST_BIT:
         raise KeyError
     _ll_dict_del(d, i)
 ll_dict_delitem.oopspec = 'dict.delitem(d, key)'
@@ -542,7 +551,7 @@
     elif entries.everused(i):
         freeslot = i
     else:
-        return i    # pristine entry -- lookup failed
+        return i | HIGHEST_BIT # pristine entry -- lookup failed
 
     # In the loop, a deleted entry (everused and not valid) is by far
     # (factor of 100s) the least likely outcome, so test for that last.
@@ -557,7 +566,7 @@
         if not entries.everused(i):
             if freeslot == -1:
                 freeslot = i
-            return freeslot
+            return freeslot | HIGHEST_BIT
         elif entries.valid(i):
             checkingkey = entries[i].key
             if direct_compare and checkingkey == key:
@@ -711,22 +720,19 @@
 
 def ll_get(dict, key, default):
     i = ll_dict_lookup(dict, key, dict.keyhash(key))
-    entries = dict.entries
-    if entries.valid(i):
-        return entries[i].value
-    else: 
+    if not i & HIGHEST_BIT:
+        return ll_get_value(dict, i)
+    else:
         return default
-ll_get.oopspec = 'dict.get(dict, key, default)'
 
 def ll_setdefault(dict, key, default):
-    i = ll_dict_lookup(dict, key, dict.keyhash(key))
-    entries = dict.entries
-    if entries.valid(i):
-        return entries[i].value
+    hash = dict.keyhash(key)
+    i = ll_dict_lookup(dict, key, hash)
+    if not i & HIGHEST_BIT:
+        return ll_get_value(dict, i)
     else:
-        ll_dict_setitem(dict, key, default)
+        _ll_dict_setitem_lookup_done(dict, key, default, hash, i)
         return default
-ll_setdefault.oopspec = 'dict.setdefault(dict, key, default)'
 
 def ll_copy(dict):
     DICT = lltype.typeOf(dict).TO
@@ -768,7 +774,10 @@
     while i < d2len:
         if entries.valid(i):
             entry = entries[i]
-            ll_dict_setitem(dic1, entry.key, entry.value)
+            hash = entries.hash(i)
+            key = entry.key
+            j = ll_dict_lookup(dic1, key, hash)
+            _ll_dict_setitem_lookup_done(dic1, key, entry.value, hash, j)
         i += 1
 ll_update.oopspec = 'dict.update(dic1, dic2)'
 
@@ -818,8 +827,7 @@
 
 def ll_contains(d, key):
     i = ll_dict_lookup(d, key, d.keyhash(key))
-    return d.entries.valid(i)
-ll_contains.oopspec = 'dict.contains(d, key)'
+    return not i & HIGHEST_BIT
 
 POPITEMINDEX = lltype.Struct('PopItemIndex', ('nextindex', lltype.Signed))
 global_popitem_index = lltype.malloc(POPITEMINDEX, zero=True, immortal=True)

diff --git a/pypy/rpython/lltypesystem/module/test/test_ll_math.py b/pypy/rpython/lltypesystem/module/test/test_ll_math.py
--- a/pypy/rpython/lltypesystem/module/test/test_ll_math.py
+++ b/pypy/rpython/lltypesystem/module/test/test_ll_math.py
@@ -11,6 +11,7 @@
         nan = inf / inf
         assert not ll_math.ll_math_isinf(0)
         assert ll_math.ll_math_isinf(inf)
+        assert ll_math.ll_math_isinf(-inf)
         assert not ll_math.ll_math_isinf(nan)
 
     def test_isnan(self):

diff --git a/pypy/module/cpyext/stringobject.py b/pypy/module/cpyext/stringobject.py
--- a/pypy/module/cpyext/stringobject.py
+++ b/pypy/module/cpyext/stringobject.py
@@ -15,7 +15,7 @@
 ## The problem
 ## -----------
 ##
-## PyString_AsString() must returns a (non-movable) pointer to the underlying
+## PyString_AsString() must return a (non-movable) pointer to the underlying
 ## buffer, whereas pypy strings are movable.  C code may temporarily store
 ## this address and use it, as long as it owns a reference to the PyObject.
 ## There is no "release" function to specify that the pointer is not needed

diff --git a/lib_pypy/pyrepl/copy_code.py b/lib_pypy/pyrepl/copy_code.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/copy_code.py
@@ -0,0 +1,73 @@
+#   Copyright 2000-2004 Michael Hudson-Doyle <micahel at gmail.com>
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+import new
+
+def copy_code_with_changes(codeobject,
+                           argcount=None,
+                           nlocals=None,
+                           stacksize=None,
+                           flags=None,
+                           code=None,
+                           consts=None,
+                           names=None,
+                           varnames=None,
+                           filename=None,
+                           name=None,
+                           firstlineno=None,
+                           lnotab=None):
+    if argcount    is None: argcount    = codeobject.co_argcount
+    if nlocals     is None: nlocals     = codeobject.co_nlocals
+    if stacksize   is None: stacksize   = codeobject.co_stacksize
+    if flags       is None: flags       = codeobject.co_flags
+    if code        is None: code        = codeobject.co_code
+    if consts      is None: consts      = codeobject.co_consts
+    if names       is None: names       = codeobject.co_names
+    if varnames    is None: varnames    = codeobject.co_varnames
+    if filename    is None: filename    = codeobject.co_filename
+    if name        is None: name        = codeobject.co_name
+    if firstlineno is None: firstlineno = codeobject.co_firstlineno
+    if lnotab      is None: lnotab      = codeobject.co_lnotab
+    return new.code(argcount,
+                    nlocals,
+                    stacksize,
+                    flags,
+                    code,
+                    consts,
+                    names,
+                    varnames,
+                    filename,
+                    name,
+                    firstlineno,
+                    lnotab)
+
+code_attrs=['argcount',
+            'nlocals',
+            'stacksize',
+            'flags',
+            'code',
+            'consts',
+            'names',
+            'varnames',
+            'filename',
+            'name',
+            'firstlineno',
+            'lnotab']
+
+

diff --git a/pypy/jit/backend/x86/test/test_gc_integration.py b/pypy/jit/backend/x86/test/test_gc_integration.py
--- a/pypy/jit/backend/x86/test/test_gc_integration.py
+++ b/pypy/jit/backend/x86/test/test_gc_integration.py
@@ -26,9 +26,10 @@
 CPU = getcpuclass()
 
 class MockGcRootMap(object):
+    is_shadow_stack = False
     def get_basic_shape(self, is_64_bit):
         return ['shape']
-    def add_ebp_offset(self, shape, offset):
+    def add_frame_offset(self, shape, offset):
         shape.append(offset)
     def add_callee_save_reg(self, shape, reg_index):
         index_to_name = { 1: 'ebx', 2: 'esi', 3: 'edi' }
@@ -44,7 +45,8 @@
     get_funcptr_for_newarray = get_funcptr_for_new
     get_funcptr_for_newstr = get_funcptr_for_new
     get_funcptr_for_newunicode = get_funcptr_for_new
-    
+    get_malloc_slowpath_addr = None
+
     moving_gc = True
     gcrootmap = MockGcRootMap()
 
@@ -166,26 +168,29 @@
 
 class GCDescrFastpathMalloc(GcLLDescription):
     gcrootmap = None
-    
+    expected_malloc_slowpath_size = WORD*2
+
     def __init__(self):
         GcCache.__init__(self, False)
         # create a nursery
         NTP = rffi.CArray(lltype.Signed)
         self.nursery = lltype.malloc(NTP, 16, flavor='raw')
-        self.addrs = lltype.malloc(rffi.CArray(lltype.Signed), 2,
+        self.addrs = lltype.malloc(rffi.CArray(lltype.Signed), 3,
                                    flavor='raw')
         self.addrs[0] = rffi.cast(lltype.Signed, self.nursery)
-        self.addrs[1] = self.addrs[0] + 64
-        # 64 bytes
+        self.addrs[1] = self.addrs[0] + 16*WORD
+        self.addrs[2] = 0
+        # 16 WORDs
         def malloc_slowpath(size):
-            assert size == WORD*2
+            assert size == self.expected_malloc_slowpath_size
             nadr = rffi.cast(lltype.Signed, self.nursery)
             self.addrs[0] = nadr + size
+            self.addrs[2] += 1
             return nadr
         self.malloc_slowpath = malloc_slowpath
         self.MALLOC_SLOWPATH = lltype.FuncType([lltype.Signed],
                                                lltype.Signed)
-        self._counter = 123
+        self._counter = 123000
 
     def can_inline_malloc(self, descr):
         return True
@@ -204,7 +209,7 @@
     def get_nursery_top_addr(self):
         return rffi.cast(lltype.Signed, self.addrs) + WORD
 
-    def get_malloc_fixedsize_slowpath_addr(self):
+    def get_malloc_slowpath_addr(self):
         fptr = llhelper(lltype.Ptr(self.MALLOC_SLOWPATH), self.malloc_slowpath)
         return rffi.cast(lltype.Signed, fptr)
 
@@ -220,9 +225,11 @@
         cpu.gc_ll_descr = GCDescrFastpathMalloc()
         cpu.setup_once()
 
-        NODE = lltype.Struct('node', ('tid', lltype.Signed),
-                                     ('value', lltype.Signed))
-        nodedescr = cpu.sizeof(NODE)     # xxx hack: NODE is not a GcStruct
+        # hack: specify 'tid' explicitly, because this test is not running
+        # with the gc transformer
+        NODE = lltype.GcStruct('node', ('tid', lltype.Signed),
+                                       ('value', lltype.Signed))
+        nodedescr = cpu.sizeof(NODE)
         valuedescr = cpu.fielddescrof(NODE, 'value')
 
         self.cpu = cpu
@@ -254,6 +261,7 @@
         assert gc_ll_descr.nursery[1] == 42
         nurs_adr = rffi.cast(lltype.Signed, gc_ll_descr.nursery)
         assert gc_ll_descr.addrs[0] == nurs_adr + (WORD*2)
+        assert gc_ll_descr.addrs[2] == 0   # slowpath never called
 
     def test_malloc_slowpath(self):
         ops = '''
@@ -274,6 +282,7 @@
         gc_ll_descr = self.cpu.gc_ll_descr
         nadr = rffi.cast(lltype.Signed, gc_ll_descr.nursery)
         assert gc_ll_descr.addrs[0] == nadr + (WORD*2)
+        assert gc_ll_descr.addrs[2] == 1   # slowpath called once
 
     def test_new_with_vtable(self):
         ops = '''
@@ -289,3 +298,93 @@
         assert gc_ll_descr.nursery[1] == self.vtable_int
         nurs_adr = rffi.cast(lltype.Signed, gc_ll_descr.nursery)
         assert gc_ll_descr.addrs[0] == nurs_adr + (WORD*3)
+        assert gc_ll_descr.addrs[2] == 0   # slowpath never called
+
+
+class Seen(Exception):
+    pass
+
+class GCDescrFastpathMallocVarsize(GCDescrFastpathMalloc):
+    def can_inline_malloc_varsize(self, arraydescr, num_elem):
+        return num_elem < 5
+    def get_funcptr_for_newarray(self):
+        return 52
+    def init_array_descr(self, A, descr):
+        descr.tid = self._counter
+        self._counter += 1
+    def args_for_new_array(self, descr):
+        raise Seen("args_for_new_array")
+
+class TestMallocVarsizeFastpath(BaseTestRegalloc):
+    def setup_method(self, method):
+        cpu = CPU(None, None)
+        cpu.vtable_offset = WORD
+        cpu.gc_ll_descr = GCDescrFastpathMallocVarsize()
+        cpu.setup_once()
+        self.cpu = cpu
+
+        ARRAY = lltype.GcArray(lltype.Signed)
+        arraydescr = cpu.arraydescrof(ARRAY)
+        self.arraydescr = arraydescr
+
+        self.namespace = locals().copy()
+
+    def test_malloc_varsize_fastpath(self):
+        # Hack.  Running the GcLLDescr_framework without really having
+        # a complete GC means that we end up with both the tid and the
+        # length being at offset 0.  In this case, so the length overwrites
+        # the tid.  This is of course only the case in this test class.
+        ops = '''
+        []
+        p0 = new_array(4, descr=arraydescr)
+        setarrayitem_gc(p0, 0, 142, descr=arraydescr)
+        setarrayitem_gc(p0, 3, 143, descr=arraydescr)
+        finish(p0)
+        '''
+        self.interpret(ops, [])
+        # check the nursery
+        gc_ll_descr = self.cpu.gc_ll_descr
+        assert gc_ll_descr.nursery[0] == 4
+        assert gc_ll_descr.nursery[1] == 142
+        assert gc_ll_descr.nursery[4] == 143
+        nurs_adr = rffi.cast(lltype.Signed, gc_ll_descr.nursery)
+        assert gc_ll_descr.addrs[0] == nurs_adr + (WORD*5)
+        assert gc_ll_descr.addrs[2] == 0   # slowpath never called
+
+    def test_malloc_varsize_slowpath(self):
+        ops = '''
+        []
+        p0 = new_array(4, descr=arraydescr)
+        setarrayitem_gc(p0, 0, 420, descr=arraydescr)
+        setarrayitem_gc(p0, 3, 430, descr=arraydescr)
+        p1 = new_array(4, descr=arraydescr)
+        setarrayitem_gc(p1, 0, 421, descr=arraydescr)
+        setarrayitem_gc(p1, 3, 431, descr=arraydescr)
+        p2 = new_array(4, descr=arraydescr)
+        setarrayitem_gc(p2, 0, 422, descr=arraydescr)
+        setarrayitem_gc(p2, 3, 432, descr=arraydescr)
+        p3 = new_array(4, descr=arraydescr)
+        setarrayitem_gc(p3, 0, 423, descr=arraydescr)
+        setarrayitem_gc(p3, 3, 433, descr=arraydescr)
+        finish(p0, p1, p2, p3)
+        '''
+        gc_ll_descr = self.cpu.gc_ll_descr
+        gc_ll_descr.expected_malloc_slowpath_size = 5*WORD
+        self.interpret(ops, [])
+        assert gc_ll_descr.addrs[2] == 1   # slowpath called once
+
+    def test_malloc_varsize_too_big(self):
+        ops = '''
+        []
+        p0 = new_array(5, descr=arraydescr)
+        finish(p0)
+        '''
+        py.test.raises(Seen, self.interpret, ops, [])
+
+    def test_malloc_varsize_variable(self):
+        ops = '''
+        [i0]
+        p0 = new_array(i0, descr=arraydescr)
+        finish(p0)
+        '''
+        py.test.raises(Seen, self.interpret, ops, [])

diff --git a/pypy/translator/c/src/ll_math.h b/pypy/translator/c/src/ll_math.h
--- a/pypy/translator/c/src/ll_math.h
+++ b/pypy/translator/c/src/ll_math.h
@@ -1,9 +1,6 @@
 /* Definitions of some C99 math library functions, for those platforms
    that don't implement these functions already. */
 
-int _pypy_math_isinf(double x);
-int _pypy_math_isnan(double x);
-
 double _pypy_math_acosh(double x);
 double _pypy_math_asinh(double x);
 double _pypy_math_atanh(double x);

diff --git a/pypy/rpython/ootypesystem/rdict.py b/pypy/rpython/ootypesystem/rdict.py
--- a/pypy/rpython/ootypesystem/rdict.py
+++ b/pypy/rpython/ootypesystem/rdict.py
@@ -153,6 +153,13 @@
         hop.exception_cannot_occur()
         return self.send_message(hop, 'll_clear')
 
+    def rtype_method_popitem(self, hop):
+        v_dict, = hop.inputargs(self)
+        r_tuple = hop.r_result
+        cTUPLE = hop.inputconst(ootype.Void, r_tuple.lowleveltype)
+        hop.exception_is_here()
+        return hop.gendirectcall(ll_popitem, cTUPLE, v_dict)
+
     def __get_func(self, interp, r_func, fn, TYPE):
         if isinstance(r_func, MethodOfFrozenPBCRepr):
             obj = r_func.r_im_self.convert_const(fn.im_self)
@@ -353,6 +360,16 @@
 ll_dict_values = _make_ll_keys_values_items('values')
 ll_dict_items  = _make_ll_keys_values_items('items')
 
+def ll_popitem(ELEM, d):
+    it = d.ll_get_items_iterator()
+    if it.ll_go_next():
+        res = ootype.new(ELEM)
+        key = res.item0 = it.ll_current_key()
+        res.item1 = it.ll_current_value()
+        d.ll_remove(key)
+        return res
+    raise KeyError
+
 # ____________________________________________________________
 #
 #  Iteration.

diff --git a/pypy/translator/cli/opcodes.py b/pypy/translator/cli/opcodes.py
--- a/pypy/translator/cli/opcodes.py
+++ b/pypy/translator/cli/opcodes.py
@@ -71,6 +71,8 @@
     'hint':                     [PushArg(0), StoreResult],
     'direct_call':              [Call],
     'indirect_call':            [IndirectCall],
+    'int_between':              [PushAllArgs, 'call bool [pypylib]pypy.runtime.Utils::IntBetween(int32, int32, int32)'],
+
 
     'cast_ptr_to_weakadr':      [PushAllArgs, 'newobj instance void class %s::.ctor(object)' % WEAKREF],
     'gc__collect':              'call void class [mscorlib]System.GC::Collect()',
@@ -147,7 +149,10 @@
     'cast_float_to_uint':       'conv.u4',
     'cast_longlong_to_float':   'conv.r8',
     'cast_float_to_longlong':   'conv.i8',
+    'cast_ulonglong_to_float':  'conv.r8',
+    'cast_float_to_ulonglong':  'conv.u8',
     'cast_primitive':           [PushAllArgs, CastPrimitive],
+    'force_cast':               [PushAllArgs, CastPrimitive],
     'truncate_longlong_to_int': 'conv.i4',
     }
 
@@ -266,6 +271,8 @@
     'ullong_ge':                _not('clt.un'),
     'ullong_lshift':            [PushAllArgs, 'conv.u4', 'shl'],
     'ullong_rshift':            [PushAllArgs, 'conv.i4', 'shr'],
+    'ullong_and':               'and',
+    'ullong_or':                'or',
 
     'oois':                     'ceq',
     'ooisnot':                  _not('ceq'),

diff --git a/pypy/module/cpyext/test/test_typeobject.py b/pypy/module/cpyext/test/test_typeobject.py
--- a/pypy/module/cpyext/test/test_typeobject.py
+++ b/pypy/module/cpyext/test/test_typeobject.py
@@ -201,6 +201,23 @@
         assert cmpr == 3
         assert cmpr != 42
 
+    def test_richcompare(self):
+        module = self.import_module("comparisons")
+        cmpr = module.CmpType()
+
+        # should not crash
+        cmpr < 4
+        cmpr <= 4
+        cmpr > 4
+        cmpr >= 4
+
+        assert cmpr.__le__(4) is NotImplemented
+
+    def test_tpcompare(self):
+        module = self.import_module("comparisons")
+        cmpr = module.OldCmpType()
+        assert cmpr < cmpr
+
     def test_hash(self):
         module = self.import_module("comparisons")
         cmpr = module.CmpType()
@@ -245,6 +262,11 @@
         obj = foo.new()
         assert module.read_tp_dict(obj) == foo.fooType.copy
 
+    def test_custom_allocation(self):
+        foo = self.import_module("foo")
+        obj = foo.newCustom()
+        assert type(obj) is foo.Custom
+        assert type(foo.Custom) is foo.MetaType
 
 class TestTypes(BaseApiTest):
     def test_type_attributes(self, space, api):

diff --git a/pypy/module/cpyext/test/test_pystate.py b/pypy/module/cpyext/test/test_pystate.py
--- a/pypy/module/cpyext/test/test_pystate.py
+++ b/pypy/module/cpyext/test/test_pystate.py
@@ -29,17 +29,22 @@
         state = api.PyInterpreterState_Head()
         assert nullptr(PyInterpreterState.TO) == api.PyInterpreterState_Next(state)
 
-def clear_threadstate(space):
-    # XXX: this should collect the ThreadState memory
-    del space.getexecutioncontext().cpyext_threadstate
-
 class TestThreadState(BaseApiTest):
     def test_thread_state_get(self, space, api):
         ts = api.PyThreadState_Get()
         assert ts != nullptr(PyThreadState.TO)
-        clear_threadstate(space)
 
     def test_thread_state_interp(self, space, api):
         ts = api.PyThreadState_Get()
         assert ts.c_interp == api.PyInterpreterState_Head()
-        clear_threadstate(space)
+
+    def test_basic_threadstate_dance(self, space, api):
+        # Let extension modules call these functions,
+        # Not sure of the semantics in pypy though.
+        # (cpyext always acquires and releases the GIL around calls)
+        tstate = api.PyThreadState_Swap(None)
+        assert tstate is not None
+        assert not api.PyThreadState_Swap(tstate)
+
+        api.PyEval_AcquireThread(tstate)
+        api.PyEval_ReleaseThread(tstate)

diff --git a/pypy/interpreter/eval.py b/pypy/interpreter/eval.py
--- a/pypy/interpreter/eval.py
+++ b/pypy/interpreter/eval.py
@@ -56,13 +56,10 @@
     """A frame is an environment supporting the execution of a code object.
     Abstract base class."""
 
-    def __init__(self, space, w_globals=None, numlocals=-1):
+    def __init__(self, space, w_globals=None):
         self.space      = space
         self.w_globals  = w_globals  # wrapped dict of globals
         self.w_locals   = None       # wrapped dict of locals
-        if numlocals < 0:  # compute the minimal size based on arguments
-            numlocals = len(self.getcode().getvarnames())
-        self.numlocals = numlocals
 
     def run(self):
         "Abstract method to override. Runs the frame"
@@ -96,6 +93,10 @@
         where the order is according to self.getcode().signature()."""
         raise TypeError, "abstract"
 
+    def getfastscopelength(self):
+        "Abstract. Get the expected number of locals."
+        raise TypeError, "abstract"
+
     def fast2locals(self):
         # Copy values from self.fastlocals_w to self.w_locals
         if self.w_locals is None:
@@ -113,10 +114,11 @@
         # Copy values from self.w_locals to self.fastlocals_w
         assert self.w_locals is not None
         varnames = self.getcode().getvarnames()
+        numlocals = self.getfastscopelength()
 
-        new_fastlocals_w = [None]*self.numlocals
-        
-        for i in range(min(len(varnames), self.numlocals)):
+        new_fastlocals_w = [None] * numlocals
+
+        for i in range(min(len(varnames), numlocals)):
             w_name = self.space.wrap(varnames[i])
             try:
                 w_value = self.space.getitem(self.w_locals, w_name)

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
@@ -399,12 +399,7 @@
         return ll_rdict.ll_newdict(DICT)
     _ll_0_newdict.need_result_type = True
 
-    _ll_2_dict_getitem = ll_rdict.ll_dict_getitem
-    _ll_3_dict_setitem = ll_rdict.ll_dict_setitem
     _ll_2_dict_delitem = ll_rdict.ll_dict_delitem
-    _ll_3_dict_setdefault = ll_rdict.ll_setdefault
-    _ll_2_dict_contains = ll_rdict.ll_contains
-    _ll_3_dict_get = ll_rdict.ll_get
     _ll_1_dict_copy = ll_rdict.ll_copy
     _ll_1_dict_clear = ll_rdict.ll_clear
     _ll_2_dict_update = ll_rdict.ll_update

diff --git a/pypy/rlib/_jit_vref.py b/pypy/rlib/_jit_vref.py
--- a/pypy/rlib/_jit_vref.py
+++ b/pypy/rlib/_jit_vref.py
@@ -8,6 +8,8 @@
 from pypy.rpython.lltypesystem import lltype
 from pypy.rpython.error import TyperError
 
+from pypy.rpython.ootypesystem import ootype
+
 
 class SomeVRef(annmodel.SomeObject):
 
@@ -24,7 +26,10 @@
         return self.s_instance
 
     def rtyper_makerepr(self, rtyper):
-        return vrefrepr
+        if rtyper.type_system.name == 'lltypesystem':
+            return vrefrepr
+        elif rtyper.type_system.name == 'ootypesystem':
+            return oovrefrepr
 
     def rtyper_makekey(self):
         return self.__class__,
@@ -54,4 +59,20 @@
                              " prebuilt virtual_ref")
         return lltype.nullptr(OBJECTPTR.TO)
 
+from pypy.rpython.ootypesystem.rclass import OBJECT
+
+class OOVRefRepr(VRefRepr):
+    lowleveltype = OBJECT
+    def rtype_simple_call(self, hop):
+        [v] = hop.inputargs(self)
+        v = hop.genop('jit_force_virtual', [v], resulttype = OBJECT)
+        return hop.genop('oodowncast', [v], resulttype = hop.r_result)
+    
+    def convert_const(self, value):
+        if value() is not None:
+            raise TypeError("only supports virtual_ref_None as a"
+                            " prebuilt virtual_ref")
+        return ootype.ROOT._null
+
 vrefrepr = VRefRepr()
+oovrefrepr = OOVRefRepr()

diff --git a/pypy/translator/cli/test/test_class.py b/pypy/translator/cli/test/test_class.py
--- a/pypy/translator/cli/test/test_class.py
+++ b/pypy/translator/cli/test/test_class.py
@@ -1,11 +1,8 @@
 import py
 from pypy.translator.cli.test.runtest import CliTest
-from pypy.translator.oosupport.test_template.class_ import BaseTestClass, BaseTestSpecialcase
+from pypy.translator.oosupport.test_template.class_ import BaseTestClass
 
 # ====> ../../oosupport/test_template/class_.py
 
 class TestCliClass(CliTest, BaseTestClass):    
     pass
-
-class TestCliSpecialCase(CliTest, BaseTestSpecialcase):
-    pass

diff --git a/pypy/jit/backend/x86/arch.py b/pypy/jit/backend/x86/arch.py
--- a/pypy/jit/backend/x86/arch.py
+++ b/pypy/jit/backend/x86/arch.py
@@ -1,17 +1,29 @@
 # Constants that depend on whether we are on 32-bit or 64-bit
 
+# The frame size gives the standard fixed part at the start of
+# every assembler frame: the saved value of some registers,
+# one word for the force_index, and some extra space used only
+# during a malloc that needs to go via its slow path.
+
 import sys
 if sys.maxint == (2**31 - 1):
     WORD = 4
-    # ebp + ebx + esi + edi + force_index = 5 words
-    FRAME_FIXED_SIZE = 5
+    # ebp + ebx + esi + edi + 4 extra words + force_index = 9 words
+    FRAME_FIXED_SIZE = 9
+    FORCE_INDEX_OFS = -8*WORD
+    MY_COPY_OF_REGS = -7*WORD
     IS_X86_32 = True
     IS_X86_64 = False
 else:
     WORD = 8
-    # rbp + rbx + r12 + r13 + r14 + r15 + force_index = 7 words
-    FRAME_FIXED_SIZE = 7
+    # rbp + rbx + r12 + r13 + r14 + r15 + 11 extra words + force_index = 18
+    FRAME_FIXED_SIZE = 18
+    FORCE_INDEX_OFS = -17*WORD
+    MY_COPY_OF_REGS = -16*WORD
     IS_X86_32 = False
     IS_X86_64 = True
 
-FORCE_INDEX_OFS = -(FRAME_FIXED_SIZE-1)*WORD
+# The extra space has room for almost all registers, apart from eax and edx
+# which are used in the malloc itself.  They are:
+#   ecx, ebx, esi, edi               [32 and 64 bits]
+#   r8, r9, r10, r12, r13, r14, r15    [64 bits only]

diff --git a/pypy/config/translationoption.py b/pypy/config/translationoption.py
--- a/pypy/config/translationoption.py
+++ b/pypy/config/translationoption.py
@@ -343,7 +343,11 @@
     }
 
 def final_check_config(config):
-    pass
+    # XXX: this should be a real config option, but it is hard to refactor it;
+    # instead, we "just" patch it from here
+    from pypy.rlib import rfloat
+    if config.translation.type_system == 'ootype':
+        rfloat.USE_SHORT_FLOAT_REPR = False
 
 def set_opt_level(config, level):
     """Apply optimization suggestions on the 'config'.

diff --git a/pypy/module/itertools/interp_itertools.py b/pypy/module/itertools/interp_itertools.py
--- a/pypy/module/itertools/interp_itertools.py
+++ b/pypy/module/itertools/interp_itertools.py
@@ -486,6 +486,7 @@
 
 class W_IMap(Wrappable):
     _error_name = "imap"
+    _immutable_fields_ = ["w_fun", "iterators_w"]
 
     def __init__(self, space, w_fun, args_w):
         self.space = space

diff --git a/pypy/rlib/rfloat.py b/pypy/rlib/rfloat.py
--- a/pypy/rlib/rfloat.py
+++ b/pypy/rlib/rfloat.py
@@ -4,6 +4,8 @@
 from pypy.rpython.tool import rffi_platform
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
 from pypy.rlib import objectmodel
+from pypy.rpython.extfunc import register_external
+from pypy.annotation.model import SomeString
 
 USE_SHORT_FLOAT_REPR = True # XXX make it a translation option?
 
@@ -24,16 +26,28 @@
 globals().update(rffi_platform.configure(CConfig))
 
 def rstring_to_float(s):
+    return rstring_to_float_impl(s)
+
+def rstring_to_float_impl(s):
     if USE_SHORT_FLOAT_REPR:
         from pypy.rlib.rdtoa import strtod
         return strtod(s)
-
     sign, before_point, after_point, exponent = break_up_float(s)
-
     if not before_point and not after_point:
         raise ValueError
+    return parts_to_float(sign, before_point, after_point, exponent)
 
-    return parts_to_float(sign, before_point, after_point, exponent)
+def oo_rstring_to_float(s):
+    from pypy.rpython.annlowlevel import oostr
+    from pypy.rpython.ootypesystem import ootype
+    lls = oostr(s)
+    return ootype.ooparse_float(lls)
+
+register_external(rstring_to_float, [SomeString(can_be_None=False)], float,
+                  llimpl=rstring_to_float_impl,
+                  ooimpl=oo_rstring_to_float,
+                  sandboxsafe=True)
+
 
 # float as string  -> sign, beforept, afterpt, exponent
 def break_up_float(s):
@@ -153,128 +167,132 @@
     result = formatd(value, tp, precision, flags)
     return result, special
 
-if USE_SHORT_FLOAT_REPR:
-    def round_double(value, ndigits):
-        # The basic idea is very simple: convert and round the double to
-        # a decimal string using _Py_dg_dtoa, then convert that decimal
-        # string back to a double with _Py_dg_strtod.  There's one minor
-        # difficulty: Python 2.x expects round to do
-        # round-half-away-from-zero, while _Py_dg_dtoa does
-        # round-half-to-even.  So we need some way to detect and correct
-        # the halfway cases.
+def round_double(value, ndigits):
+    if USE_SHORT_FLOAT_REPR:
+        return round_double_short_repr(value, ndigits)
+    else:
+        return round_double_fallback_repr(value, ndigits)
 
-        # a halfway value has the form k * 0.5 * 10**-ndigits for some
-        # odd integer k.  Or in other words, a rational number x is
-        # exactly halfway between two multiples of 10**-ndigits if its
-        # 2-valuation is exactly -ndigits-1 and its 5-valuation is at
-        # least -ndigits.  For ndigits >= 0 the latter condition is
-        # automatically satisfied for a binary float x, since any such
-        # float has nonnegative 5-valuation.  For 0 > ndigits >= -22, x
-        # needs to be an integral multiple of 5**-ndigits; we can check
-        # this using fmod.  For -22 > ndigits, there are no halfway
-        # cases: 5**23 takes 54 bits to represent exactly, so any odd
-        # multiple of 0.5 * 10**n for n >= 23 takes at least 54 bits of
-        # precision to represent exactly.
+def round_double_short_repr(value, ndigits):
+    # The basic idea is very simple: convert and round the double to
+    # a decimal string using _Py_dg_dtoa, then convert that decimal
+    # string back to a double with _Py_dg_strtod.  There's one minor
+    # difficulty: Python 2.x expects round to do
+    # round-half-away-from-zero, while _Py_dg_dtoa does
+    # round-half-to-even.  So we need some way to detect and correct
+    # the halfway cases.
 
-        sign = copysign(1.0, value)
-        value = abs(value)
+    # a halfway value has the form k * 0.5 * 10**-ndigits for some
+    # odd integer k.  Or in other words, a rational number x is
+    # exactly halfway between two multiples of 10**-ndigits if its
+    # 2-valuation is exactly -ndigits-1 and its 5-valuation is at
+    # least -ndigits.  For ndigits >= 0 the latter condition is
+    # automatically satisfied for a binary float x, since any such
+    # float has nonnegative 5-valuation.  For 0 > ndigits >= -22, x
+    # needs to be an integral multiple of 5**-ndigits; we can check
+    # this using fmod.  For -22 > ndigits, there are no halfway
+    # cases: 5**23 takes 54 bits to represent exactly, so any odd
+    # multiple of 0.5 * 10**n for n >= 23 takes at least 54 bits of
+    # precision to represent exactly.
 
-        # find 2-valuation value
-        m, expo = math.frexp(value)
-        while m != math.floor(m):
-            m *= 2.0
-            expo -= 1
+    sign = copysign(1.0, value)
+    value = abs(value)
 
-        # determine whether this is a halfway case.
-        halfway_case = 0
-        if expo == -ndigits - 1:
-            if ndigits >= 0:
+    # find 2-valuation value
+    m, expo = math.frexp(value)
+    while m != math.floor(m):
+        m *= 2.0
+        expo -= 1
+
+    # determine whether this is a halfway case.
+    halfway_case = 0
+    if expo == -ndigits - 1:
+        if ndigits >= 0:
+            halfway_case = 1
+        elif ndigits >= -22:
+            # 22 is the largest k such that 5**k is exactly
+            # representable as a double
+            five_pow = 1.0
+            for i in range(-ndigits):
+                five_pow *= 5.0
+            if math.fmod(value, five_pow) == 0.0:
                 halfway_case = 1
-            elif ndigits >= -22:
-                # 22 is the largest k such that 5**k is exactly
-                # representable as a double
-                five_pow = 1.0
-                for i in range(-ndigits):
-                    five_pow *= 5.0
-                if math.fmod(value, five_pow) == 0.0:
-                    halfway_case = 1
 
-        # round to a decimal string; use an extra place for halfway case
-        strvalue = formatd(value, 'f', ndigits + halfway_case)
+    # round to a decimal string; use an extra place for halfway case
+    strvalue = formatd(value, 'f', ndigits + halfway_case)
 
-        if halfway_case:
-            buf = [c for c in strvalue]
-            if ndigits >= 0:
-                endpos = len(buf) - 1
-            else:
-                endpos = len(buf) + ndigits
-            # Sanity checks: there should be exactly ndigits+1 places
-            # following the decimal point, and the last digit in the
-            # buffer should be a '5'
-            if not objectmodel.we_are_translated():
-                assert buf[endpos] == '5'
-                if '.' in buf:
-                    assert endpos == len(buf) - 1
-                    assert buf.index('.') == len(buf) - ndigits - 2
+    if halfway_case:
+        buf = [c for c in strvalue]
+        if ndigits >= 0:
+            endpos = len(buf) - 1
+        else:
+            endpos = len(buf) + ndigits
+        # Sanity checks: there should be exactly ndigits+1 places
+        # following the decimal point, and the last digit in the
+        # buffer should be a '5'
+        if not objectmodel.we_are_translated():
+            assert buf[endpos] == '5'
+            if '.' in buf:
+                assert endpos == len(buf) - 1
+                assert buf.index('.') == len(buf) - ndigits - 2
 
-            # increment and shift right at the same time
-            i = endpos - 1
-            carry = 1
-            while i >= 0:
+        # increment and shift right at the same time
+        i = endpos - 1
+        carry = 1
+        while i >= 0:
+            digit = ord(buf[i])
+            if digit == ord('.'):
+                buf[i+1] = chr(digit)
+                i -= 1
                 digit = ord(buf[i])
-                if digit == ord('.'):
-                    buf[i+1] = chr(digit)
-                    i -= 1
-                    digit = ord(buf[i])
 
-                carry += digit - ord('0')
-                buf[i+1] = chr(carry % 10 + ord('0'))
-                carry /= 10
-                i -= 1
-            buf[0] = chr(carry + ord('0'))
-            if ndigits < 0:
-                buf.append('0')
+            carry += digit - ord('0')
+            buf[i+1] = chr(carry % 10 + ord('0'))
+            carry /= 10
+            i -= 1
+        buf[0] = chr(carry + ord('0'))
+        if ndigits < 0:
+            buf.append('0')
 
-            strvalue = ''.join(buf)
+        strvalue = ''.join(buf)
 
-        return sign * rstring_to_float(strvalue)
+    return sign * rstring_to_float(strvalue)
 
-else:
-    # fallback version, to be used when correctly rounded
-    # binary<->decimal conversions aren't available
-    def round_double(value, ndigits):
-        if ndigits >= 0:
-            if ndigits > 22:
-                # pow1 and pow2 are each safe from overflow, but
-                # pow1*pow2 ~= pow(10.0, ndigits) might overflow
-                pow1 = math.pow(10.0, ndigits - 22)
-                pow2 = 1e22
-            else:
-                pow1 = math.pow(10.0, ndigits)
-                pow2 = 1.0
+# fallback version, to be used when correctly rounded
+# binary<->decimal conversions aren't available
+def round_double_fallback_repr(value, ndigits):
+    if ndigits >= 0:
+        if ndigits > 22:
+            # pow1 and pow2 are each safe from overflow, but
+            # pow1*pow2 ~= pow(10.0, ndigits) might overflow
+            pow1 = math.pow(10.0, ndigits - 22)
+            pow2 = 1e22
+        else:
+            pow1 = math.pow(10.0, ndigits)
+            pow2 = 1.0
 
-            y = (value * pow1) * pow2
-            # if y overflows, then rounded value is exactly x
-            if isinf(y):
-                return value
+        y = (value * pow1) * pow2
+        # if y overflows, then rounded value is exactly x
+        if isinf(y):
+            return value
 
-        else:
-            pow1 = math.pow(10.0, -ndigits);
-            pow2 = 1.0 # unused; for translation
-            y = value / pow1
+    else:
+        pow1 = math.pow(10.0, -ndigits);
+        pow2 = 1.0 # unused; for translation
+        y = value / pow1
 
-        if y >= 0.0:
-            z = math.floor(y + 0.5)
-        else:
-            z = math.ceil(y - 0.5)
-        if math.fabs(y-z) == 1.0:   # obscure case, see the test
-            z = y
+    if y >= 0.0:
+        z = math.floor(y + 0.5)
+    else:
+        z = math.ceil(y - 0.5)
+    if math.fabs(y-z) == 1.0:   # obscure case, see the test
+        z = y
 
-        if ndigits >= 0:
-            z = (z / pow2) / pow1
-        else:
-            z *= pow1
-        return z
+    if ndigits >= 0:
+        z = (z / pow2) / pow1
+    else:
+        z *= pow1
+    return z
 
 INFINITY = 1e200 * 1e200
 NAN = INFINITY / INFINITY

diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -314,6 +314,7 @@
     'Py_BuildValue', 'Py_VaBuildValue', 'PyTuple_Pack',
 
     'PyErr_Format', 'PyErr_NewException', 'PyErr_NewExceptionWithDoc',
+    'PySys_WriteStdout', 'PySys_WriteStderr',
 
     'PyEval_CallFunction', 'PyEval_CallMethod', 'PyObject_CallFunction',
     'PyObject_CallMethod', 'PyObject_CallFunctionObjArgs', 'PyObject_CallMethodObjArgs',
@@ -399,21 +400,9 @@
 # So we need a forward and backward mapping in our State instance
 PyObjectStruct = lltype.ForwardReference()
 PyObject = lltype.Ptr(PyObjectStruct)
-PyBufferProcs = lltype.ForwardReference()
 PyObjectFields = (("ob_refcnt", lltype.Signed), ("ob_type", PyTypeObjectPtr))
-def F(ARGS, RESULT=lltype.Signed):
-    return lltype.Ptr(lltype.FuncType(ARGS, RESULT))
-PyBufferProcsFields = (
-    ("bf_getreadbuffer", F([PyObject, lltype.Signed, rffi.VOIDPP])),
-    ("bf_getwritebuffer", F([PyObject, lltype.Signed, rffi.VOIDPP])),
-    ("bf_getsegcount", F([PyObject, rffi.INTP])),
-    ("bf_getcharbuffer", F([PyObject, lltype.Signed, rffi.CCHARPP])),
-# we don't support new buffer interface for now
-    ("bf_getbuffer", rffi.VOIDP),
-    ("bf_releasebuffer", rffi.VOIDP))
 PyVarObjectFields = PyObjectFields + (("ob_size", Py_ssize_t), )
 cpython_struct('PyObject', PyObjectFields, PyObjectStruct)
-cpython_struct('PyBufferProcs', PyBufferProcsFields, PyBufferProcs)
 PyVarObjectStruct = cpython_struct("PyVarObject", PyVarObjectFields)
 PyVarObject = lltype.Ptr(PyVarObjectStruct)
 
@@ -538,7 +527,8 @@
 
             elif is_PyObject(callable.api_func.restype):
                 if result is None:
-                    retval = make_ref(space, None)
+                    retval = rffi.cast(callable.api_func.restype,
+                                       make_ref(space, None))
                 elif isinstance(result, Reference):
                     retval = result.get_ref(space)
                 elif not rffi._isllptr(result):
@@ -883,6 +873,7 @@
                                source_dir / "stringobject.c",
                                source_dir / "mysnprintf.c",
                                source_dir / "pythonrun.c",
+                               source_dir / "sysmodule.c",
                                source_dir / "bufferobject.c",
                                source_dir / "object.c",
                                source_dir / "cobject.c",

diff --git a/pypy/translator/cli/src/debug.cs b/pypy/translator/cli/src/debug.cs
--- a/pypy/translator/cli/src/debug.cs
+++ b/pypy/translator/cli/src/debug.cs
@@ -1,5 +1,6 @@
 using System;
 using System.IO;
+using System.Collections.Generic;
 using System.Diagnostics;
 
 // this code is modeled after translator/c/src/debug.h
@@ -21,7 +22,7 @@
         static int have_debug_prints = -1;
         static bool debug_ready = false;
         static bool debug_profile = false;
-        static string debug_prefix = null;
+        static string[] active_categories = null;
 
         public static void close_file()
         {
@@ -29,6 +30,14 @@
                 debug_file.Close();
         }
 
+        public static bool startswithoneof(string category, string[] active_categories)
+        {
+            foreach(string cat in active_categories)
+                if (category.StartsWith(cat))
+                    return true;
+            return false;
+        }
+
         public static bool HAVE_DEBUG_PRINTS()
         {
             if ((have_debug_prints & 1) != 0) {
@@ -48,7 +57,8 @@
             have_debug_prints <<= 1;
             if (!debug_profile) {
                 /* non-profiling version */
-                if (debug_prefix == null || !category.StartsWith(debug_prefix)) {
+                if (active_categories == null || 
+                    !startswithoneof(category, active_categories)) {
                     /* wrong section name, or no PYPYLOG at all, skip it */
                     return;
                 }
@@ -83,7 +93,8 @@
                 }
                 else {
                     /* PYPYLOG=prefix:filename --- conditional logging */
-                    debug_prefix = filename.Substring(0, colon);
+                    string debug_prefix = filename.Substring(0, colon);
+                    active_categories = debug_prefix.Split(',');
                     filename = filename.Substring(colon+1);
                 }
                 if (filename != "-")

diff --git a/pypy/objspace/std/test/test_dictmultiobject.py b/pypy/objspace/std/test/test_dictmultiobject.py
--- a/pypy/objspace/std/test/test_dictmultiobject.py
+++ b/pypy/objspace/std/test/test_dictmultiobject.py
@@ -1,3 +1,4 @@
+import sys
 from pypy.interpreter.error import OperationError
 from pypy.objspace.std.dictmultiobject import \
      W_DictMultiObject, setitem__DictMulti_ANY_ANY, getitem__DictMulti_ANY, \
@@ -151,6 +152,8 @@
 
 
 class AppTest_DictObject:
+    def setup_class(cls):
+        cls.w_on_pypy = cls.space.wrap("__pypy__" in sys.builtin_module_names)
 
     def test_equality(self):
         d = {1:2} 
@@ -259,7 +262,29 @@
         d[33] = 99
         assert d == dd
         assert x == 99
-    
+
+    def test_setdefault_fast(self):
+        class Key(object):
+            calls = 0
+            def __hash__(self):
+                self.calls += 1
+                return object.__hash__(self)
+
+        k = Key()
+        d = {}
+        d.setdefault(k, [])
+        if self.on_pypy:
+            assert k.calls == 1
+
+        d.setdefault(k, 1)
+        if self.on_pypy:
+            assert k.calls == 2
+
+        k = Key()
+        d.setdefault(k, 42)
+        if self.on_pypy:
+            assert k.calls == 1
+
     def test_update(self):
         d = {1:2, 3:4}
         dd = d.copy()
@@ -704,13 +729,20 @@
 
 
 class FakeString(str):
+    hash_count = 0
     def unwrap(self, space):
         self.unwrapped = True
         return str(self)
 
+    def __hash__(self):
+        self.hash_count += 1
+        return str.__hash__(self)
+
 # the minimal 'space' needed to use a W_DictMultiObject
 class FakeSpace:
+    hash_count = 0
     def hash_w(self, obj):
+        self.hash_count += 1
         return hash(obj)
     def unwrap(self, x):
         return x
@@ -726,6 +758,8 @@
         return []
     DictObjectCls = W_DictMultiObject
     def type(self, w_obj):
+        if isinstance(w_obj, FakeString):
+            return str
         return type(w_obj)
     w_str = str
     def str_w(self, string):
@@ -890,6 +924,19 @@
             impl.setitem(x, x)
         assert impl.r_dict_content is not None
 
+    def test_setdefault_fast(self):
+        on_pypy = "__pypy__" in sys.builtin_module_names
+        impl = self.impl
+        key = FakeString(self.string)
+        x = impl.setdefault(key, 1)
+        assert x == 1
+        if on_pypy:
+            assert key.hash_count == 1
+        x = impl.setdefault(key, 2)
+        assert x == 1
+        if on_pypy:
+            assert key.hash_count == 2
+
 class TestStrDictImplementation(BaseTestRDictImplementation):
     ImplementionClass = StrDictImplementation
 

diff --git a/pypy/module/cpyext/test/test_pyerrors.py b/pypy/module/cpyext/test/test_pyerrors.py
--- a/pypy/module/cpyext/test/test_pyerrors.py
+++ b/pypy/module/cpyext/test/test_pyerrors.py
@@ -96,6 +96,10 @@
         out, err = capfd.readouterr()
         assert "Exception ValueError: 'message' in 'location' ignored" == err.strip()
 
+    def test_ExceptionInstance_Class(self, space, api):
+        instance = space.call_function(space.w_ValueError)
+        assert api.PyExceptionInstance_Class(instance) is space.w_ValueError
+
 class AppTestFetch(AppTestCpythonExtensionBase):
     def setup_class(cls):
         AppTestCpythonExtensionBase.setup_class.im_func(cls)

diff --git a/pypy/rpython/rstr.py b/pypy/rpython/rstr.py
--- a/pypy/rpython/rstr.py
+++ b/pypy/rpython/rstr.py
@@ -221,14 +221,33 @@
 
     def rtype_method_split(self, hop):
         rstr = hop.args_r[0].repr
-        v_str, v_chr = hop.inputargs(rstr.repr, rstr.char_repr)
+        if hop.nb_args == 3:
+            v_str, v_chr, v_max = hop.inputargs(rstr.repr, rstr.char_repr, Signed)
+        else:
+            v_str, v_chr = hop.inputargs(rstr.repr, rstr.char_repr)
+            v_max = hop.inputconst(Signed, -1)
         try:
             list_type = hop.r_result.lowleveltype.TO
         except AttributeError:
             list_type = hop.r_result.lowleveltype
         cLIST = hop.inputconst(Void, list_type)
         hop.exception_cannot_occur()
-        return hop.gendirectcall(self.ll.ll_split_chr, cLIST, v_str, v_chr)
+        return hop.gendirectcall(self.ll.ll_split_chr, cLIST, v_str, v_chr, v_max)
+
+    def rtype_method_rsplit(self, hop):
+        rstr = hop.args_r[0].repr
+        if hop.nb_args == 3:
+            v_str, v_chr, v_max = hop.inputargs(rstr.repr, rstr.char_repr, Signed)
+        else:
+            v_str, v_chr = hop.inputargs(rstr.repr, rstr.char_repr)
+            v_max = hop.inputconst(Signed, -1)
+        try:
+            list_type = hop.r_result.lowleveltype.TO
+        except AttributeError:
+            list_type = hop.r_result.lowleveltype
+        cLIST = hop.inputconst(Void, list_type)
+        hop.exception_cannot_occur()
+        return hop.gendirectcall(self.ll.ll_rsplit_chr, cLIST, v_str, v_chr, v_max)
 
     def rtype_method_replace(self, hop):
         rstr = hop.args_r[0].repr

diff --git a/pypy/module/cpyext/slotdefs.py b/pypy/module/cpyext/slotdefs.py
--- a/pypy/module/cpyext/slotdefs.py
+++ b/pypy/module/cpyext/slotdefs.py
@@ -1,16 +1,20 @@
+from __future__ import with_statement
+
 import re
 
 from pypy.rpython.lltypesystem import rffi, lltype
-from pypy.module.cpyext.api import generic_cpy_call, cpython_api, PyObject
+from pypy.module.cpyext.api import (
+    cpython_api, generic_cpy_call, PyObject, Py_ssize_t)
 from pypy.module.cpyext.typeobjectdefs import (
     unaryfunc, wrapperfunc, ternaryfunc, PyTypeObjectPtr, binaryfunc,
-    getattrfunc, setattrofunc, lenfunc, ssizeargfunc, ssizessizeargfunc,
-    ssizeobjargproc, iternextfunc, initproc, richcmpfunc, hashfunc,
-    descrgetfunc, descrsetfunc, objobjproc)
+    getattrfunc, getattrofunc, setattrofunc, lenfunc, ssizeargfunc,
+    ssizessizeargfunc, ssizeobjargproc, iternextfunc, initproc, richcmpfunc,
+    cmpfunc, hashfunc, descrgetfunc, descrsetfunc, objobjproc, readbufferproc)
 from pypy.module.cpyext.pyobject import from_ref
 from pypy.module.cpyext.pyerrors import PyErr_Occurred
 from pypy.module.cpyext.state import State
 from pypy.interpreter.error import OperationError, operationerrfmt
+from pypy.interpreter.buffer import Buffer as W_Buffer
 from pypy.interpreter.argument import Arguments
 from pypy.rlib.unroll import unrolling_iterable
 from pypy.rlib.objectmodel import specialize
@@ -65,6 +69,12 @@
     finally:
         rffi.free_charp(name_ptr)
 
+def wrap_getattro(space, w_self, w_args, func):
+    func_target = rffi.cast(getattrofunc, func)
+    check_num_args(space, w_args, 1)
+    args_w = space.fixedview(w_args)
+    return generic_cpy_call(space, func_target, w_self, args_w[0])
+
 def wrap_setattr(space, w_self, w_args, func):
     func_target = rffi.cast(setattrofunc, func)
     check_num_args(space, w_args, 2)
@@ -187,18 +197,59 @@
     check_num_args(space, w_args, 0)
     return space.wrap(generic_cpy_call(space, func_target, w_self))
 
+class CPyBuffer(W_Buffer):
+    # Similar to Py_buffer
+
+    def __init__(self, ptr, size, w_obj):
+        self.ptr = ptr
+        self.size = size
+        self.w_obj = w_obj # kept alive
+
+    def getlength(self):
+        return self.size
+
+    def getitem(self, index):
+        return self.ptr[index]
+
+def wrap_getreadbuffer(space, w_self, w_args, func):
+    func_target = rffi.cast(readbufferproc, func)
+    with lltype.scoped_alloc(rffi.VOIDPP.TO, 1) as ptr:
+        index = rffi.cast(Py_ssize_t, 0)
+        size = generic_cpy_call(space, func_target, w_self, index, ptr)
+        if size < 0:
+            space.fromcache(State).check_and_raise_exception(always=True)
+        return space.wrap(CPyBuffer(ptr[0], size, w_self))
+
 def get_richcmp_func(OP_CONST):
     def inner(space, w_self, w_args, func):
         func_target = rffi.cast(richcmpfunc, func)
         check_num_args(space, w_args, 1)
-        args_w = space.fixedview(w_args)
-        other_w = args_w[0]
+        w_other, = space.fixedview(w_args)
         return generic_cpy_call(space, func_target,
-            w_self, other_w, rffi.cast(rffi.INT_real, OP_CONST))
+            w_self, w_other, rffi.cast(rffi.INT_real, OP_CONST))
     return inner
 
 richcmp_eq = get_richcmp_func(Py_EQ)
 richcmp_ne = get_richcmp_func(Py_NE)
+richcmp_lt = get_richcmp_func(Py_LT)
+richcmp_le = get_richcmp_func(Py_LE)
+richcmp_gt = get_richcmp_func(Py_GT)
+richcmp_ge = get_richcmp_func(Py_GE)
+
+def wrap_cmpfunc(space, w_self, w_args, func):
+    func_target = rffi.cast(cmpfunc, func)
+    check_num_args(space, w_args, 1)
+    w_other, = space.fixedview(w_args)
+
+    if not space.is_true(space.issubtype(space.type(w_self),
+                                         space.type(w_other))):
+        raise OperationError(space.w_TypeError, space.wrap(
+            "%s.__cmp__(x,y) requires y to be a '%s', not a '%s'" %
+            (space.type(w_self).getname(space),
+             space.type(w_self).getname(space),
+             space.type(w_other).getname(space))))
+
+    return space.wrap(generic_cpy_call(space, func_target, w_self, w_other))
 
 @cpython_api([PyTypeObjectPtr, PyObject, PyObject], PyObject, external=False)
 def slot_tp_new(space, type, w_args, w_kwds):
@@ -289,7 +340,12 @@
 
     # irregular interface, because of tp_getattr/tp_getattro confusion
     if NAME == "__getattr__":
-        wrapper = wrap_getattr
+        if SLOT == "tp_getattro":
+            wrapper = wrap_getattro
+        elif SLOT == "tp_getattr":
+            wrapper = wrap_getattr
+        else:
+            assert False
 
     function = globals().get(FUNCTION, None)
     assert FLAGS == 0 or FLAGS == PyWrapperFlag_KEYWORDS
@@ -455,7 +511,7 @@
                "oct(x)"),
         UNSLOT("__hex__", nb_hex, slot_nb_hex, wrap_unaryfunc,
                "hex(x)"),
-        NBSLOT("__index__", nb_index, slot_nb_index, wrap_unaryfunc, 
+        NBSLOT("__index__", nb_index, slot_nb_index, wrap_unaryfunc,
                "x[y:z] <==> x[y.__index__():z.__index__()]"),
         IBSLOT("__iadd__", nb_inplace_add, slot_nb_inplace_add,
                wrap_binaryfunc, "+"),
@@ -560,12 +616,19 @@
 for regex, repl in slotdef_replacements:
     slotdefs_str = re.sub(regex, repl, slotdefs_str)
 
+slotdefs = eval(slotdefs_str)
+# PyPy addition
+slotdefs += (
+    TPSLOT("__buffer__", "tp_as_buffer.c_bf_getreadbuffer", None, "wrap_getreadbuffer", ""),
+)
+
 slotdefs_for_tp_slots = unrolling_iterable(
     [(x.method_name, x.slot_name, x.slot_names, x.slot_func)
-     for x in eval(slotdefs_str)])
+     for x in slotdefs])
+
 slotdefs_for_wrappers = unrolling_iterable(
     [(x.method_name, x.slot_names, x.wrapper_func, x.wrapper_func_kwds, x.doc)
-     for x in eval(slotdefs_str)])
+     for x in slotdefs])
 
 if __name__ == "__main__":
     print slotdefs_str

diff --git a/pypy/translator/backendopt/merge_if_blocks.py b/pypy/translator/backendopt/merge_if_blocks.py
--- a/pypy/translator/backendopt/merge_if_blocks.py
+++ b/pypy/translator/backendopt/merge_if_blocks.py
@@ -1,4 +1,4 @@
-from pypy.objspace.flow.model import Block, Constant, Variable, flatten
+from pypy.objspace.flow.model import Block, Constant, Variable
 from pypy.objspace.flow.model import checkgraph, mkentrymap
 from pypy.translator.backendopt.support import log
 
@@ -75,14 +75,19 @@
             # False link
             checkvar = [var for var in current.operations[-1].args
                            if isinstance(var, Variable)][0]
+            resvar = current.operations[-1].result
             case = [var for var in current.operations[-1].args
                        if isinstance(var, Constant)][0]
-            chain.append((current, case))
             checkvars.append(checkvar)
             falseexit = current.exits[0]
             assert not falseexit.exitcase
             trueexit = current.exits[1]
             targetblock = falseexit.target
+            # if the result of the check is also passed through the link, we
+            # cannot construct the chain
+            if resvar in falseexit.args or resvar in trueexit.args:
+                break
+            chain.append((current, case))
             if len(entrymap[targetblock]) != 1:
                 break
             if checkvar not in falseexit.args:

diff --git a/pypy/module/cpyext/intobject.py b/pypy/module/cpyext/intobject.py
--- a/pypy/module/cpyext/intobject.py
+++ b/pypy/module/cpyext/intobject.py
@@ -5,9 +5,16 @@
     cpython_api, build_type_checkers, PyObject,
     CONST_STRING, CANNOT_FAIL, Py_ssize_t)
 from pypy.rlib.rarithmetic import r_uint
+import sys
 
 PyInt_Check, PyInt_CheckExact = build_type_checkers("Int")
 
+ at cpython_api([], lltype.Signed, error=CANNOT_FAIL)
+def PyInt_GetMax(space):
+    """Return the system's idea of the largest integer it can handle (LONG_MAX,
+    as defined in the system header files)."""
+    return sys.maxint
+
 @cpython_api([lltype.Signed], PyObject)
 def PyInt_FromLong(space, ival):
     """Create a new integer object with a value of ival.

diff --git a/pypy/objspace/std/typeobject.py b/pypy/objspace/std/typeobject.py
--- a/pypy/objspace/std/typeobject.py
+++ b/pypy/objspace/std/typeobject.py
@@ -10,7 +10,7 @@
 from pypy.rlib.objectmodel import we_are_translated
 from pypy.rlib.objectmodel import current_object_addr_as_int, compute_hash
 from pypy.rlib.jit import hint, purefunction_promote, we_are_jitted
-from pypy.rlib.jit import purefunction, dont_look_inside
+from pypy.rlib.jit import purefunction, dont_look_inside, unroll_safe
 from pypy.rlib.rarithmetic import intmask, r_uint
 
 # from compiler/misc.py
@@ -163,7 +163,7 @@
         if (not we_are_jitted() or w_self.is_heaptype() or
             w_self.space.config.objspace.std.mutable_builtintypes):
             return w_self._version_tag
-        # heap objects cannot get their version_tag changed
+        # prebuilt objects cannot get their version_tag changed
         return w_self._pure_version_tag()
 
     @purefunction_promote()
@@ -253,7 +253,7 @@
                     return w_value
         return None
                 
-
+    @unroll_safe
     def _lookup(w_self, key):
         space = w_self.space
         for w_class in w_self.mro_w:
@@ -262,6 +262,7 @@
                 return w_value
         return None
 
+    @unroll_safe
     def _lookup_where(w_self, key):
         # like lookup() but also returns the parent class in which the
         # attribute was found

diff --git a/lib-python/modified-2.7.0/distutils/command/build_ext.py b/lib-python/modified-2.7.0/distutils/command/build_ext.py
--- a/lib-python/modified-2.7.0/distutils/command/build_ext.py
+++ b/lib-python/modified-2.7.0/distutils/command/build_ext.py
@@ -184,7 +184,7 @@
             # the 'libs' directory is for binary installs - we assume that
             # must be the *native* platform.  But we don't really support
             # cross-compiling via a binary install anyway, so we let it go.
-            self.library_dirs.append(os.path.join(sys.exec_prefix, 'libs'))
+            self.library_dirs.append(os.path.join(sys.exec_prefix, 'include'))
             if self.debug:
                 self.build_temp = os.path.join(self.build_temp, "Debug")
             else:
@@ -192,8 +192,13 @@
 
             # Append the source distribution include and library directories,
             # this allows distutils on windows to work in the source tree
-            self.include_dirs.append(os.path.join(sys.exec_prefix, 'PC'))
-            if MSVC_VERSION == 9:
+            if 0:
+                # pypy has no PC directory
+                self.include_dirs.append(os.path.join(sys.exec_prefix, 'PC'))
+            if 1:
+                # pypy has no PCBuild directory
+                pass
+            elif MSVC_VERSION == 9:
                 # Use the .lib files for the correct architecture
                 if self.plat_name == 'win32':
                     suffix = ''
@@ -695,24 +700,14 @@
         shared extension.  On most platforms, this is just 'ext.libraries';
         on Windows and OS/2, we add the Python library (eg. python20.dll).
         """
-        # The python library is always needed on Windows.  For MSVC, this
-        # is redundant, since the library is mentioned in a pragma in
-        # pyconfig.h that MSVC groks.  The other Windows compilers all seem
-        # to need it mentioned explicitly, though, so that's what we do.
-        # Append '_d' to the python import library on debug builds.
+        # The python library is always needed on Windows.
         if sys.platform == "win32":
-            from distutils.msvccompiler import MSVCCompiler
-            if not isinstance(self.compiler, MSVCCompiler):
-                template = "python%d%d"
-                if self.debug:
-                    template = template + '_d'
-                pythonlib = (template %
-                       (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff))
-                # don't extend ext.libraries, it may be shared with other
-                # extensions, it is a reference to the original list
-                return ext.libraries + [pythonlib]
-            else:
-                return ext.libraries
+            template = "python%d%d"
+            pythonlib = (template %
+                   (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff))
+            # don't extend ext.libraries, it may be shared with other
+            # extensions, it is a reference to the original list
+            return ext.libraries + [pythonlib]
         elif sys.platform == "os2emx":
             # EMX/GCC requires the python library explicitly, and I
             # believe VACPP does as well (though not confirmed) - AIM Apr01

diff --git a/pypy/jit/metainterp/test/test_optimizeopt.py b/pypy/jit/metainterp/test/test_optimizeopt.py
--- a/pypy/jit/metainterp/test/test_optimizeopt.py
+++ b/pypy/jit/metainterp/test/test_optimizeopt.py
@@ -135,7 +135,7 @@
         return type(self) is type(other)      # xxx obscure
     def clone_if_mutable(self):
         res = Storage(self.metainterp_sd, self.original_greenkey)
-        self.copy_all_attrbutes_into(res)
+        self.copy_all_attributes_into(res)
         return res
 
 def _sortboxes(boxes):
@@ -816,6 +816,52 @@
         """
         self.optimize_loop(ops, expected, preamble)
 
+    def test_compare_with_itself(self):
+        ops = """
+        []
+        i0 = escape()
+        i1 = int_lt(i0, i0)
+        guard_false(i1) []
+        i2 = int_le(i0, i0)
+        guard_true(i2) []
+        i3 = int_eq(i0, i0)
+        guard_true(i3) []
+        i4 = int_ne(i0, i0)
+        guard_false(i4) []
+        i5 = int_gt(i0, i0)
+        guard_false(i5) []
+        i6 = int_ge(i0, i0)
+        guard_true(i6) []
+        jump()
+        """
+        expected = """
+        []
+        i0 = escape()
+        jump()
+        """
+        self.optimize_loop(ops, expected)
+
+    def test_compare_with_itself_uint(self):
+        py.test.skip("implement me")
+        ops = """
+        []
+        i0 = escape()
+        i7 = uint_lt(i0, i0)
+        guard_false(i7) []
+        i8 = uint_le(i0, i0)
+        guard_true(i8) []
+        i9 = uint_gt(i0, i0)
+        guard_false(i9) []
+        i10 = uint_ge(i0, i0)
+        guard_true(i10) []
+        jump()
+        """
+        expected = """
+        []
+        i0 = escape()
+        jump()
+        """
+        self.optimize_loop(ops, expected)
 
 
 
@@ -1791,7 +1837,7 @@
         """
         self.optimize_loop(ops, ops)
 
-    def test_duplicate_setfield_1(self):
+    def test_duplicate_setfield_0(self):
         ops = """
         [p1, i1, i2]
         setfield_gc(p1, i1, descr=valuedescr)
@@ -1800,8 +1846,27 @@
         """
         expected = """
         [p1, i1, i2]
+        jump(p1, i1, i2)
+        """
+        # in this case, all setfields are removed, because we can prove
+        # that in the loop it will always have the same value
+        self.optimize_loop(ops, expected)
+
+    def test_duplicate_setfield_1(self):
+        ops = """
+        [p1]
+        i1 = escape()
+        i2 = escape()
+        setfield_gc(p1, i1, descr=valuedescr)
         setfield_gc(p1, i2, descr=valuedescr)
-        jump(p1, i1, i2)
+        jump(p1)
+        """
+        expected = """
+        [p1]
+        i1 = escape()
+        i2 = escape()
+        setfield_gc(p1, i2, descr=valuedescr)
+        jump(p1)
         """
         self.optimize_loop(ops, expected)
 
@@ -1848,6 +1913,7 @@
         setfield_gc(p1, i4, descr=nextdescr)
         #
         setfield_gc(p1, i2, descr=valuedescr)
+        escape()
         jump(p1, i1, i2, p3)
         """
         preamble = """
@@ -1860,6 +1926,7 @@
         #
         setfield_gc(p1, i2, descr=valuedescr)
         setfield_gc(p1, i4, descr=nextdescr)
+        escape()
         jump(p1, i1, i2, p3, i3)
         """
         expected = """
@@ -1871,6 +1938,7 @@
         #
         setfield_gc(p1, i2, descr=valuedescr)
         setfield_gc(p1, i4, descr=nextdescr)
+        escape()
         jump(p1, i1, i2, p3, i3)
         """
         self.optimize_loop(ops, expected, preamble)
@@ -1943,6 +2011,7 @@
         guard_true(i3) []
         i4 = int_neg(i2)
         setfield_gc(p1, NULL, descr=nextdescr)
+        escape()
         jump(p1, i2, i4)
         """
         preamble = """
@@ -1950,12 +2019,14 @@
         guard_true(i3) [p1]
         i4 = int_neg(i2)
         setfield_gc(p1, NULL, descr=nextdescr)
+        escape()
         jump(p1, i2, i4)
         """
         expected = """
         [p1, i2, i4]
         guard_true(i4) [p1]
         setfield_gc(p1, NULL, descr=nextdescr)
+        escape()
         jump(p1, i2, 1)
         """
         self.optimize_loop(ops, expected, preamble)
@@ -1969,6 +2040,7 @@
         guard_true(i3) []
         i4 = int_neg(i2)
         setfield_gc(p1, NULL, descr=nextdescr)
+        escape()
         jump(p1, i2, i4)
         """
         preamble = """
@@ -1976,12 +2048,14 @@
         guard_true(i3) [i2, p1]
         i4 = int_neg(i2)
         setfield_gc(p1, NULL, descr=nextdescr)
+        escape()
         jump(p1, i2, i4)
         """
         expected = """
         [p1, i2, i4]
         guard_true(i4) [i2, p1]
         setfield_gc(p1, NULL, descr=nextdescr)
+        escape()
         jump(p1, i2, 1)
         """
         self.optimize_loop(ops, expected)
@@ -2027,15 +2101,34 @@
         guard_value(p1, ConstPtr(myptr)) []
         setfield_gc(p1, i1, descr=valuedescr)
         setfield_gc(ConstPtr(myptr), i2, descr=valuedescr)
+        escape()
         jump(p1, i1, i2)
         """
         expected = """
         [i1, i2]
         setfield_gc(ConstPtr(myptr), i2, descr=valuedescr)
+        escape()
         jump(i1, i2)
         """
         self.optimize_loop(ops, expected)
 
+    def test_dont_force_setfield_around_copystrcontent(self):
+        ops = """
+        [p0, i0, p1, i1, i2]
+        setfield_gc(p0, i1, descr=valuedescr)
+        copystrcontent(p0, i0, p1, i1, i2)
+        escape()
+        jump(p0, i0, p1, i1, i2)
+        """
+        expected = """
+        [p0, i0, p1, i1, i2]
+        copystrcontent(p0, i0, p1, i1, i2)
+        setfield_gc(p0, i1, descr=valuedescr)
+        escape()
+        jump(p0, i0, p1, i1, i2)
+        """
+        self.optimize_loop(ops, expected)
+
     def test_duplicate_getarrayitem_1(self):
         ops = """
         [p1]
@@ -2356,6 +2449,33 @@
         """
         self.optimize_loop(ops, expected, preamble)
 
+    def test_bug_5(self):
+        ops = """
+        [p0]
+        i0 = escape()
+        i2 = getfield_gc(p0, descr=valuedescr)
+        i4 = int_add(i2, 1)
+        setfield_gc(p0, i4, descr=valuedescr)
+        guard_true(i0) []
+        i6 = getfield_gc(p0, descr=valuedescr)
+        i8 = int_sub(i6, 1)
+        setfield_gc(p0, i8, descr=valuedescr)
+        escape()
+        jump(p0)
+        """
+        expected = """
+        [p0]
+        i0 = escape()
+        i2 = getfield_gc(p0, descr=valuedescr)
+        i4 = int_add(i2, 1)
+        setfield_gc(p0, i4, descr=valuedescr)
+        guard_true(i0) []
+        setfield_gc(p0, i2, descr=valuedescr)
+        escape()
+        jump(p0)
+        """
+        self.optimize_loop(ops, expected)
+
     def test_invalid_loop_1(self):
         ops = """
         [p1]
@@ -2637,7 +2757,7 @@
         """
         self.optimize_loop(ops, expected)
 
-    def test_fold_partially_constant_ops(self):
+    def test_fold_partially_constant_add_sub(self):
         ops = """
         [i0]
         i1 = int_sub(i0, 0)
@@ -2671,7 +2791,7 @@
         """
         self.optimize_loop(ops, expected)
 
-    def test_fold_partially_constant_ops_ovf(self):
+    def test_fold_partially_constant_add_sub_ovf(self):
         ops = """
         [i0]
         i1 = int_sub_ovf(i0, 0)
@@ -2708,6 +2828,21 @@
         """
         self.optimize_loop(ops, expected)
 
+    def test_fold_partially_constant_shift(self):
+        ops = """
+        [i0]
+        i1 = int_lshift(i0, 0)
+        i2 = int_rshift(i1, 0)
+        i3 = int_eq(i2, i0)
+        guard_true(i3) []
+        jump(i2)
+        """
+        expected = """
+        [i0]
+        jump(i0)
+        """
+        self.optimize_loop(ops, expected)
+
     # ----------
 
 class TestLLtype(OptimizeOptTest, LLtypeMixin):
@@ -2992,7 +3127,6 @@
         i0 = force_token()
         p2 = new_with_vtable(ConstClass(jit_virtual_ref_vtable))
         setfield_gc(p2, i0, descr=virtualtokendescr)
-        setfield_gc(p2, 5, descr=virtualrefindexdescr)
         escape(p2)
         setfield_gc(p2, p1, descr=virtualforceddescr)
         setfield_gc(p2, -3, descr=virtualtokendescr)
@@ -3025,7 +3159,6 @@
         #
         p2 = new_with_vtable(ConstClass(jit_virtual_ref_vtable))
         setfield_gc(p2, i3, descr=virtualtokendescr)
-        setfield_gc(p2, 3, descr=virtualrefindexdescr)
         setfield_gc(p0, p2, descr=nextdescr)
         #
         call_may_force(i1, descr=mayforcevirtdescr)
@@ -3065,7 +3198,6 @@
         #
         p2 = new_with_vtable(ConstClass(jit_virtual_ref_vtable))
         setfield_gc(p2, i3, descr=virtualtokendescr)
-        setfield_gc(p2, 2, descr=virtualrefindexdescr)
         setfield_gc(p0, p2, descr=nextdescr)
         #
         call_may_force(i1, descr=mayforcevirtdescr)
@@ -3103,6 +3235,7 @@
         guard_no_exception(descr=fdescr) [p2, p1]
         virtual_ref_finish(p2, p1)
         setfield_gc(p0, NULL, descr=refdescr)
+        escape()
         jump(p0, i1)
         """
         preamble = """
@@ -3111,6 +3244,7 @@
         call(i1, descr=nonwritedescr)
         guard_no_exception(descr=fdescr) [i3, i1, p0]
         setfield_gc(p0, NULL, descr=refdescr)
+        escape()
         jump(p0, i1)
         """
         expected = """
@@ -3119,6 +3253,7 @@
         call(i1, descr=nonwritedescr)
         guard_no_exception(descr=fdescr2) [i3, i1, p0]
         setfield_gc(p0, NULL, descr=refdescr)
+        escape()
         jump(p0, i1)
         """
         self.optimize_loop(ops, expected, preamble)
@@ -3129,7 +3264,7 @@
         #self.loop.inputargs[0].value = self.nodeobjvalue
         #self.check_expanded_fail_descr('''p2, p1
         #    p0.refdescr = p2
-        #    where p2 is a jit_virtual_ref_vtable, virtualtokendescr=i3, virtualrefindexdescr=2
+        #    where p2 is a jit_virtual_ref_vtable, virtualtokendescr=i3
         #    where p1 is a node_vtable, nextdescr=p1b
         #    where p1b is a node_vtable, valuedescr=i1
         #    ''', rop.GUARD_NO_EXCEPTION)
@@ -3150,7 +3285,6 @@
         i3 = force_token()
         p2 = new_with_vtable(ConstClass(jit_virtual_ref_vtable))
         setfield_gc(p2, i3, descr=virtualtokendescr)
-        setfield_gc(p2, 7, descr=virtualrefindexdescr)
         escape(p2)
         p1 = new_with_vtable(ConstClass(node_vtable))
         setfield_gc(p2, p1, descr=virtualforceddescr)
@@ -3176,7 +3310,6 @@
         i3 = force_token()
         p2 = new_with_vtable(ConstClass(jit_virtual_ref_vtable))
         setfield_gc(p2, i3, descr=virtualtokendescr)
-        setfield_gc(p2, 23, descr=virtualrefindexdescr)
         escape(p2)
         setfield_gc(p2, p1, descr=virtualforceddescr)
         setfield_gc(p2, -3, descr=virtualtokendescr)
@@ -3693,13 +3826,16 @@
         guard_true(i1) []
         jump(p0)
         """
-        # The dead strlen will be eliminated be the backend.
-        expected = """
+        preamble = """
         [p0]
         i0 = strlen(p0)
         jump(p0)
         """
-        self.optimize_strunicode_loop(ops, expected, expected)
+        expected = """
+        [p0]
+        jump(p0)
+        """
+        self.optimize_strunicode_loop(ops, expected, preamble)
 
     def test_addsub_const(self):
         ops = """
@@ -4839,6 +4975,58 @@
         p2 = new_with_vtable(ConstClass(node_vtable))
         setfield_gc(p2, i1, descr=nextdescr)
         """
+        py.test.skip("no test here")
+
+    def test_immutable_not(self):
+        ops = """
+        []
+        p0 = new_with_vtable(ConstClass(intobj_noimmut_vtable))
+        setfield_gc(p0, 42, descr=noimmut_intval)
+        escape(p0)
+        jump()
+        """
+        self.optimize_loop(ops, ops)
+
+    def test_immutable_variable(self):
+        ops = """
+        [i0]
+        p0 = new_with_vtable(ConstClass(intobj_immut_vtable))
+        setfield_gc(p0, i0, descr=immut_intval)
+        escape(p0)
+        jump(i0)
+        """
+        self.optimize_loop(ops, ops)
+
+    def test_immutable_incomplete(self):
+        ops = """
+        []
+        p0 = new_with_vtable(ConstClass(intobj_immut_vtable))
+        escape(p0)
+        jump()
+        """
+        self.optimize_loop(ops, ops)
+
+    def test_immutable_constantfold(self):
+        ops = """
+        []
+        p0 = new_with_vtable(ConstClass(intobj_immut_vtable))
+        setfield_gc(p0, 1242, descr=immut_intval)
+        escape(p0)
+        jump()
+        """
+        from pypy.rpython.lltypesystem import lltype, llmemory
+        class IntObj1242(object):
+            _TYPE = llmemory.GCREF.TO
+            def __eq__(self, other):
+                return other.container.intval == 1242
+        self.namespace['intobj1242'] = lltype._ptr(llmemory.GCREF,
+                                                   IntObj1242())
+        expected = """
+        []
+        escape(ConstPtr(intobj1242))
+        jump()
+        """
+        self.optimize_loop(ops, expected)
 
     # ----------
     def optimize_strunicode_loop(self, ops, optops, preamble=None):
@@ -5150,7 +5338,21 @@
         """
         expected = """
         [p0]
+        jump(p0)
+        """
+        self.optimize_loop(ops, expected)
+
+    def test_strlen_repeated(self):
+        ops = """
+        [p0]
         i0 = strlen(p0)
+        i1 = strlen(p0)
+        i2 = int_eq(i0, i1)
+        guard_true(i2) []
+        jump(p0)
+        """
+        expected = """
+        [p0]
         jump(p0)
         """
         self.optimize_loop(ops, expected)


diff --git a/pypy/rpython/test/test_rfloat.py b/pypy/rpython/test/test_rfloat.py
--- a/pypy/rpython/test/test_rfloat.py
+++ b/pypy/rpython/test/test_rfloat.py
@@ -156,6 +156,37 @@
                 return x
         self.interpret(fn, [1.0, 2.0, 3.0])
 
+    def test_copysign(self):
+        import math
+        def fn(x, y):
+            return math.copysign(x, y)
+        assert self.interpret(fn, [42, -1]) == -42
+        assert self.interpret(fn, [42, -0.0]) == -42
+        assert self.interpret(fn, [42, 0.0]) == 42
+
+    def test_rstring_to_float(self):
+        from pypy.rlib.rfloat import rstring_to_float
+        def fn(i):
+            s = ['42.3', '123.4'][i]
+            return rstring_to_float(s)
+        assert self.interpret(fn, [0]) == 42.3
+
+    def test_isnan(self):
+        import math
+        def fn(x):
+            inf = x * x
+            nan = inf / inf
+            return math.isnan(nan)
+        assert self.interpret(fn, [1e200])
+
+    def test_isinf(self):
+        import math
+        def fn(x):
+            inf = x * x
+            return math.isinf(inf)
+        assert self.interpret(fn, [1e200])
+
+        
 class TestLLtype(BaseTestRfloat, LLRtypeMixin):
 
     def test_hash(self):

diff --git a/pypy/jit/metainterp/optimizeopt/optimizer.py b/pypy/jit/metainterp/optimizeopt/optimizer.py
--- a/pypy/jit/metainterp/optimizeopt/optimizer.py
+++ b/pypy/jit/metainterp/optimizeopt/optimizer.py
@@ -191,7 +191,7 @@
 
     def test_emittable(self, op):
         return self.is_emittable(op)
-    
+
     def is_emittable(self, op):
         return self.next_optimization.test_emittable(op)
 
@@ -247,7 +247,7 @@
     def reconstruct_for_next_iteration(self, optimizer=None, valuemap=None):
         #return self.__class__()
         raise NotImplementedError
-    
+
 
 class Optimizer(Optimization):
 
@@ -283,20 +283,20 @@
         else:
             optimizations = []
             self.first_optimization = self
-            
-        self.optimizations  = optimizations 
+
+        self.optimizations  = optimizations
 
     def force_at_end_of_preamble(self):
         self.resumedata_memo = resume.ResumeDataLoopMemo(self.metainterp_sd)
         for o in self.optimizations:
             o.force_at_end_of_preamble()
-            
+
     def reconstruct_for_next_iteration(self, optimizer=None, valuemap=None):
         assert optimizer is None
         assert valuemap is None
         valuemap = {}
         new = Optimizer(self.metainterp_sd, self.loop)
-        optimizations = [o.reconstruct_for_next_iteration(new, valuemap) for o in 
+        optimizations = [o.reconstruct_for_next_iteration(new, valuemap) for o in
                          self.optimizations]
         new.set_optimizations(optimizations)
 
@@ -313,7 +313,7 @@
         for key, value in self.loop_invariant_results.items():
             new.loop_invariant_results[key] = \
                                  value.get_reconstructed(new, valuemap)
-            
+
         new.pure_operations = self.pure_operations
         new.producer = self.producer
         assert self.posponedop is None
@@ -439,7 +439,7 @@
 
     def test_emittable(self, op):
         return True
-    
+
     def emit_operation(self, op):
         ###self.heap_op_optimizer.emitting_operation(op)
         self._emit_operation(op)
@@ -517,19 +517,17 @@
             canfold = nextop.getopnum() == rop.GUARD_NO_OVERFLOW
         else:
             nextop = None
-            
+
         if canfold:
             for i in range(op.numargs()):
                 if self.get_constant_box(op.getarg(i)) is None:
                     break
             else:
                 # all constant arguments: constant-fold away
-                argboxes = [self.get_constant_box(op.getarg(i))
-                            for i in range(op.numargs())]
-                resbox = execute_nonspec(self.cpu, None,
-                                         op.getopnum(), argboxes, op.getdescr())
-                # FIXME: Don't we need to check for an overflow here?
-                self.make_constant(op.result, resbox.constbox())
+                resbox = self.constant_fold(op)
+                # note that INT_xxx_OVF is not done from here, and the
+                # overflows in the INT_xxx operations are ignored
+                self.make_constant(op.result, resbox)
                 return
 
             # did we do the exact same operation already?
@@ -548,6 +546,13 @@
         if nextop:
             self.emit_operation(nextop)
 
+    def constant_fold(self, op):
+        argboxes = [self.get_constant_box(op.getarg(i))
+                    for i in range(op.numargs())]
+        resbox = execute_nonspec(self.cpu, None,
+                                 op.getopnum(), argboxes, op.getdescr())
+        return resbox.constbox()
+
     #def optimize_GUARD_NO_OVERFLOW(self, op):
     #    # otherwise the default optimizer will clear fields, which is unwanted
     #    # in this case

diff --git a/pypy/jit/tl/pypyjit_demo.py b/pypy/jit/tl/pypyjit_demo.py
--- a/pypy/jit/tl/pypyjit_demo.py
+++ b/pypy/jit/tl/pypyjit_demo.py
@@ -1,19 +1,16 @@
 
 try:
-    import pypyjit
-    pypyjit.set_param(threshold=3, inlining=True)
+    def main(n):
+        def g(n):
+            return range(n)
+        s = 0
+        for i in range(n):  # ID: for
+            tmp = g(n)
+            s += tmp[i]     # ID: getitem
+            a = 0
+        return s
+    main(10)
 
-    def sqrt(y, n=10000):
-        x = y / 2
-        while n > 0:
-            #assert y > 0 and x > 0
-            if y > 0 and x > 0: pass
-            n -= 1
-            x = (x + y/x) / 2
-        return x
-
-    print sqrt(1234, 4)
-    
 except Exception, e:
     print "Exception: ", type(e)
     print e

diff --git a/pypy/jit/metainterp/optimizeopt/intbounds.py b/pypy/jit/metainterp/optimizeopt/intbounds.py
--- a/pypy/jit/metainterp/optimizeopt/intbounds.py
+++ b/pypy/jit/metainterp/optimizeopt/intbounds.py
@@ -213,7 +213,7 @@
         v2 = self.getvalue(op.getarg(1))
         if v1.intbound.known_lt(v2.intbound):
             self.make_constant_int(op.result, 1)
-        elif v1.intbound.known_ge(v2.intbound):
+        elif v1.intbound.known_ge(v2.intbound) or v1 is v2:
             self.make_constant_int(op.result, 0)
         else:
             self.emit_operation(op)
@@ -223,7 +223,7 @@
         v2 = self.getvalue(op.getarg(1))
         if v1.intbound.known_gt(v2.intbound):
             self.make_constant_int(op.result, 1)
-        elif v1.intbound.known_le(v2.intbound):
+        elif v1.intbound.known_le(v2.intbound) or v1 is v2:
             self.make_constant_int(op.result, 0)
         else:
             self.emit_operation(op)
@@ -231,7 +231,7 @@
     def optimize_INT_LE(self, op):
         v1 = self.getvalue(op.getarg(0))
         v2 = self.getvalue(op.getarg(1))
-        if v1.intbound.known_le(v2.intbound):
+        if v1.intbound.known_le(v2.intbound) or v1 is v2:
             self.make_constant_int(op.result, 1)
         elif v1.intbound.known_gt(v2.intbound):
             self.make_constant_int(op.result, 0)
@@ -241,7 +241,7 @@
     def optimize_INT_GE(self, op):
         v1 = self.getvalue(op.getarg(0))
         v2 = self.getvalue(op.getarg(1))
-        if v1.intbound.known_ge(v2.intbound):
+        if v1.intbound.known_ge(v2.intbound) or v1 is v2:
             self.make_constant_int(op.result, 1)
         elif v1.intbound.known_lt(v2.intbound):
             self.make_constant_int(op.result, 0)

diff --git a/pypy/objspace/flow/test/test_objspace.py b/pypy/objspace/flow/test/test_objspace.py
--- a/pypy/objspace/flow/test/test_objspace.py
+++ b/pypy/objspace/flow/test/test_objspace.py
@@ -1,8 +1,8 @@
 from __future__ import with_statement
 import new
 import py
-from pypy.objspace.flow.model import Constant, Block, Link, Variable, traverse
-from pypy.objspace.flow.model import flatten, mkentrymap, c_last_exception
+from pypy.objspace.flow.model import Constant, Block, Link, Variable
+from pypy.objspace.flow.model import mkentrymap, c_last_exception
 from pypy.interpreter.argument import Arguments
 from pypy.translator.simplify import simplify_graph
 from pypy.objspace.flow.objspace import FlowObjSpace, error
@@ -37,12 +37,10 @@
 
     def all_operations(self, graph):
         result = {}
-        def visit(node):
-            if isinstance(node, Block):
-                for op in node.operations:
-                    result.setdefault(op.opname, 0)
-                    result[op.opname] += 1
-        traverse(visit, graph)
+        for node in graph.iterblocks():
+            for op in node.operations:
+                result.setdefault(op.opname, 0)
+                result[op.opname] += 1
         return result
 
 
@@ -246,12 +244,9 @@
         x = self.codetest(self.implicitException)
         simplify_graph(x)
         self.show(x)
-        def cannot_reach_exceptblock(link):
-            if isinstance(link, Link):
-                assert link.target is not x.exceptblock
-        traverse(cannot_reach_exceptblock, x)
+        for link in x.iterlinks():
+            assert link.target is not x.exceptblock
 
-    
     def implicitAttributeError(x):
         try:
             x = getattr(x, "y")
@@ -263,10 +258,8 @@
         x = self.codetest(self.implicitAttributeError)
         simplify_graph(x)
         self.show(x)
-        def cannot_reach_exceptblock(link):
-            if isinstance(link, Link):
-                assert link.target is not x.exceptblock
-        traverse(cannot_reach_exceptblock, x)
+        for link in x.iterlinks():
+            assert link.target is not x.exceptblock
 
     #__________________________________________________________
     def implicitException_int_and_id(x):
@@ -311,14 +304,12 @@
         simplify_graph(x)
         self.show(x)
         found = {}
-        def find_exceptions(link):
-            if isinstance(link, Link):
+        for link in x.iterlinks():
                 if link.target is x.exceptblock:
                     if isinstance(link.args[0], Constant):
                         found[link.args[0].value] = True
                     else:
                         found[link.exitcase] = None
-        traverse(find_exceptions, x)
         assert found == {IndexError: True, KeyError: True, Exception: None}
     
     def reraiseAnything(x):
@@ -332,12 +323,10 @@
         simplify_graph(x)
         self.show(x)
         found = {}
-        def find_exceptions(link):
-            if isinstance(link, Link):
+        for link in x.iterlinks():
                 if link.target is x.exceptblock:
                     assert isinstance(link.args[0], Constant)
                     found[link.args[0].value] = True
-        traverse(find_exceptions, x)
         assert found == {ValueError: True, ZeroDivisionError: True, OverflowError: True}
 
     def loop_in_bare_except_bug(lst):
@@ -521,11 +510,9 @@
 
     def test_jump_target_specialization(self):
         x = self.codetest(self.jump_target_specialization)
-        def visitor(node):
-            if isinstance(node, Block):
-                for op in node.operations:
-                    assert op.opname != 'mul', "mul should have disappeared"
-        traverse(visitor, x)
+        for block in x.iterblocks():
+            for op in block.operations:
+                assert op.opname != 'mul', "mul should have disappeared"
 
     #__________________________________________________________
     def highly_branching_example(a,b,c,d,e,f,g,h,i,j):
@@ -573,7 +560,8 @@
 
     def test_highly_branching_example(self):
         x = self.codetest(self.highly_branching_example)
-        assert len(flatten(x)) < 60   # roughly 20 blocks + 30 links
+        # roughly 20 blocks + 30 links
+        assert len(list(x.iterblocks())) + len(list(x.iterlinks())) < 60
 
     #__________________________________________________________
     def test_unfrozen_user_class1(self):
@@ -589,11 +577,9 @@
         graph = self.codetest(f)
 
         results = []
-        def visit(link):
-            if isinstance(link, Link):
-                if link.target == graph.returnblock:
-                    results.extend(link.args)
-        traverse(visit, graph)
+        for link in graph.iterlinks():
+            if link.target == graph.returnblock:
+                results.extend(link.args)
         assert len(results) == 2
 
     def test_unfrozen_user_class2(self):
@@ -607,11 +593,9 @@
         graph = self.codetest(f)
 
         results = []
-        def visit(link):
-            if isinstance(link, Link):
-                if link.target == graph.returnblock:
-                    results.extend(link.args)
-        traverse(visit, graph)
+        for link in graph.iterlinks():
+            if link.target == graph.returnblock:
+                results.extend(link.args)
         assert not isinstance(results[0], Constant)
 
     def test_frozen_user_class1(self):
@@ -630,11 +614,9 @@
         graph = self.codetest(f)
 
         results = []
-        def visit(link):
-            if isinstance(link, Link):
-                if link.target == graph.returnblock:
-                    results.extend(link.args)
-        traverse(visit, graph)
+        for link in graph.iterlinks():
+            if link.target == graph.returnblock:
+                results.extend(link.args)
         assert len(results) == 1
 
     def test_frozen_user_class2(self):
@@ -650,11 +632,9 @@
         graph = self.codetest(f)
 
         results = []
-        def visit(link):
-            if isinstance(link, Link):
-                if link.target == graph.returnblock:
-                    results.extend(link.args)
-        traverse(visit, graph)
+        for link in graph.iterlinks():
+            if link.target == graph.returnblock:
+                results.extend(link.args)
         assert results == [Constant(4)]
 
     def test_const_star_call(self):
@@ -663,14 +643,9 @@
         def f():
             return g(1,*(2,3))
         graph = self.codetest(f)
-        call_args = []
-        def visit(block):
-            if isinstance(block, Block):
-                for op in block.operations:
-                    if op.opname == "call_args":
-                        call_args.append(op)
-        traverse(visit, graph)
-        assert not call_args
+        for block in graph.iterblocks():
+            for op in block.operations:
+                assert not op.opname == "call_args"
 
     def test_catch_importerror_1(self):
         def f():
@@ -997,11 +972,9 @@
         simplify_graph(x)
         self.show(x)
         excfound = []
-        def check(link):
-            if isinstance(link, Link):
-                if link.target is x.exceptblock:
-                    excfound.append(link.exitcase)
-        traverse(check, x)
+        for link in x.iterlinks():
+            if link.target is x.exceptblock:
+                excfound.append(link.exitcase)
         assert len(excfound) == 2
         excfound.sort()
         expected = [Exception, AttributeError]
@@ -1019,11 +992,9 @@
         simplify_graph(x)
         self.show(x)
         excfound = []
-        def check(link):
-            if isinstance(link, Link):
-                if link.target is x.exceptblock:
-                    excfound.append(link.exitcase)
-        traverse(check, x)
+        for link in x.iterlinks():
+            if link.target is x.exceptblock:
+                excfound.append(link.exitcase)
         assert len(excfound) == 2
         excfound.sort()
         expected = [Exception, TypeError]

diff --git a/pypy/rpython/lltypesystem/module/ll_math.py b/pypy/rpython/lltypesystem/module/ll_math.py
--- a/pypy/rpython/lltypesystem/module/ll_math.py
+++ b/pypy/rpython/lltypesystem/module/ll_math.py
@@ -6,7 +6,7 @@
 from pypy.rpython.lltypesystem import lltype, rffi
 from pypy.tool.sourcetools import func_with_new_name
 from pypy.tool.autopath import pypydir
-from pypy.rlib import rposix
+from pypy.rlib import jit, rposix
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
 from pypy.rlib.rfloat import isinf, isnan, INFINITY, NAN
 
@@ -20,8 +20,7 @@
         separate_module_files=[cdir.join('src', 'll_math.c')],
         export_symbols=['_pypy_math_acosh', '_pypy_math_asinh',
                         '_pypy_math_atanh',
-                        '_pypy_math_expm1', '_pypy_math_log1p',
-                        '_pypy_math_isinf', '_pypy_math_isnan'],
+                        '_pypy_math_expm1', '_pypy_math_log1p'],
         )
     math_prefix = '_pypy_math_'
 else:
@@ -57,8 +56,6 @@
 math_fmod  = llexternal('fmod',  [rffi.DOUBLE, rffi.DOUBLE], rffi.DOUBLE)
 math_hypot = llexternal(underscore + 'hypot',
                         [rffi.DOUBLE, rffi.DOUBLE], rffi.DOUBLE)
-math_isinf = math_llexternal('isinf', [rffi.DOUBLE], rffi.INT)
-math_isnan = math_llexternal('isnan', [rffi.DOUBLE], rffi.INT)
 
 # ____________________________________________________________
 #
@@ -91,13 +88,13 @@
 #
 # Custom implementations
 
-
 def ll_math_isnan(y):
-    return bool(math_isnan(y))
-
+    # By not calling into the extenal function the JIT can inline this.  Floats
+    # are awesome.
+    return y != y
 
 def ll_math_isinf(y):
-    return bool(math_isinf(y))
+    return y != 0 and y * .5 == y
 
 
 ll_math_copysign = math_copysign

diff --git a/lib_pypy/pyrepl/test/test_functional.py b/lib_pypy/pyrepl/test/test_functional.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/test/test_functional.py
@@ -0,0 +1,50 @@
+#   Copyright 2000-2007 Michael Hudson-Doyle <micahel at gmail.com>
+#                       Maciek Fijalkowski
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+# some functional tests, to see if this is really working
+
+import py
+import sys
+
+class TestTerminal(object):
+    def _spawn(self, *args, **kwds):
+        try:
+            import pexpect
+        except ImportError, e:
+            py.test.skip(str(e))
+        kwds.setdefault('timeout', 10)
+        child = pexpect.spawn(*args, **kwds)
+        child.logfile = sys.stdout
+        return child
+
+    def spawn(self, argv=[]):
+        # avoid running start.py, cause it might contain
+        # things like readline or rlcompleter(2) included
+        child = self._spawn(sys.executable, ['-S'] + argv)
+        child.sendline('from pyrepl.python_reader import main')
+        child.sendline('main()')
+        return child
+
+    def test_basic(self):
+        child = self.spawn()
+        child.sendline('a = 3')
+        child.sendline('a')
+        child.expect('3')
+        

diff --git a/pypy/translator/backendopt/test/test_malloc.py b/pypy/translator/backendopt/test/test_malloc.py
--- a/pypy/translator/backendopt/test/test_malloc.py
+++ b/pypy/translator/backendopt/test/test_malloc.py
@@ -3,7 +3,7 @@
 from pypy.translator.backendopt.all import backend_optimizations
 from pypy.translator.translator import TranslationContext, graphof
 from pypy.translator import simplify
-from pypy.objspace.flow.model import checkgraph, flatten, Block, mkentrymap
+from pypy.objspace.flow.model import checkgraph, Block, mkentrymap
 from pypy.rpython.llinterp import LLInterpreter
 from pypy.rpython.lltypesystem import lltype, llmemory
 from pypy.rpython.ootypesystem import ootype
@@ -22,8 +22,7 @@
         remover = cls.MallocRemover()
         checkgraph(graph)
         count1 = count2 = 0
-        for node in flatten(graph):
-            if isinstance(node, Block):
+        for node in graph.iterblocks():
                 for op in node.operations:
                     if op.opname == cls.MallocRemover.MALLOC_OP:
                         S = op.args[0].value
@@ -47,7 +46,7 @@
             auto_inline_graphs(t, t.graphs, inline)
         if option.view:
             t.view()
-        # to detect missing keepalives and broken intermediate graphs,
+        # to detect broken intermediate graphs,
         # we do the loop ourselves instead of calling remove_simple_mallocs()
         while True:
             progress = remover.remove_mallocs_once(graph)
@@ -158,18 +157,6 @@
     type_system = 'lltype'
     MallocRemover = LLTypeMallocRemover
 
-    def test_with_keepalive(self):
-        from pypy.rlib.objectmodel import keepalive_until_here
-        def fn1(x, y):
-            if x > 0:
-                t = x+y, x-y
-            else:
-                t = x-y, x+y
-            s, d = t
-            keepalive_until_here(t)
-            return s*d
-        self.check(fn1, [int, int], [15, 10], 125)
-
     def test_dont_remove_with__del__(self):
         import os
         delcalls = [0]
@@ -199,50 +186,6 @@
         op = graph.startblock.exits[0].target.exits[1].target.operations[0]
         assert op.opname == "malloc"
 
-    def test_add_keepalives(self):
-        class A:
-            pass
-        SMALL = lltype.Struct('SMALL', ('x', lltype.Signed))
-        BIG = lltype.GcStruct('BIG', ('z', lltype.Signed), ('s', SMALL))
-        def fn7(i):
-            big = lltype.malloc(BIG)
-            a = A()
-            a.big = big
-            a.small = big.s
-            a.small.x = 0
-            while i > 0:
-                a.small.x += i
-                i -= 1
-            return a.small.x
-        self.check(fn7, [int], [10], 55, must_be_removed=False)
-
-    def test_getsubstruct(self):
-        py.test.skip("fails because of the interior structure changes")
-        SMALL = lltype.Struct('SMALL', ('x', lltype.Signed))
-        BIG = lltype.GcStruct('BIG', ('z', lltype.Signed), ('s', SMALL))
-
-        def fn(n1, n2):
-            b = lltype.malloc(BIG)
-            b.z = n1
-            b.s.x = n2
-            return b.z - b.s.x
-
-        self.check(fn, [int, int], [100, 58], 42)
-
-    def test_fixedsizearray(self):
-        py.test.skip("fails because of the interior structure changes")
-        A = lltype.FixedSizeArray(lltype.Signed, 3)
-        S = lltype.GcStruct('S', ('a', A))
-
-        def fn(n1, n2):
-            s = lltype.malloc(S)
-            a = s.a
-            a[0] = n1
-            a[2] = n2
-            return a[0]-a[2]
-
-        self.check(fn, [int, int], [100, 42], 58)
-
     def test_wrapper_cannot_be_removed(self):
         SMALL = lltype.OpaqueType('SMALL')
         BIG = lltype.GcStruct('BIG', ('z', lltype.Signed), ('s', SMALL))

diff --git a/pypy/rlib/_rweakvaldict.py b/pypy/rlib/_rweakvaldict.py
--- a/pypy/rlib/_rweakvaldict.py
+++ b/pypy/rlib/_rweakvaldict.py
@@ -113,7 +113,7 @@
     @jit.dont_look_inside
     def ll_get(self, d, llkey):
         hash = self.ll_keyhash(llkey)
-        i = rdict.ll_dict_lookup(d, llkey, hash)
+        i = rdict.ll_dict_lookup(d, llkey, hash) & rdict.MASK
         #llop.debug_print(lltype.Void, i, 'get')
         valueref = d.entries[i].value
         if valueref:
@@ -132,7 +132,7 @@
     def ll_set_nonnull(self, d, llkey, llvalue):
         hash = self.ll_keyhash(llkey)
         valueref = weakref_create(llvalue)    # GC effects here, before the rest
-        i = rdict.ll_dict_lookup(d, llkey, hash)
+        i = rdict.ll_dict_lookup(d, llkey, hash) & rdict.MASK
         everused = d.entries.everused(i)
         d.entries[i].key = llkey
         d.entries[i].value = valueref
@@ -146,7 +146,7 @@
     @jit.dont_look_inside
     def ll_set_null(self, d, llkey):
         hash = self.ll_keyhash(llkey)
-        i = rdict.ll_dict_lookup(d, llkey, hash)
+        i = rdict.ll_dict_lookup(d, llkey, hash) & rdict.MASK
         if d.entries.everused(i):
             # If the entry was ever used, clean up its key and value.
             # We don't store a NULL value, but a dead weakref, because

diff --git a/pypy/translator/cli/test/test_list.py b/pypy/translator/cli/test/test_list.py
--- a/pypy/translator/cli/test/test_list.py
+++ b/pypy/translator/cli/test/test_list.py
@@ -7,7 +7,10 @@
     def test_recursive(self):
         py.test.skip("CLI doesn't support recursive lists")
 
-    def test_getitem_exc(self):
+    def test_getitem_exc_1(self):
+        py.test.skip('fixme!')
+
+    def test_getitem_exc_2(self):
         py.test.skip('fixme!')
 
     def test_list_unsigned(self):

diff --git a/pypy/rpython/memory/gctransform/framework.py b/pypy/rpython/memory/gctransform/framework.py
--- a/pypy/rpython/memory/gctransform/framework.py
+++ b/pypy/rpython/memory/gctransform/framework.py
@@ -9,6 +9,7 @@
 from pypy.rlib.rarithmetic import ovfcheck
 from pypy.rlib import rstack, rgc
 from pypy.rlib.debug import ll_assert
+from pypy.rlib.objectmodel import we_are_translated
 from pypy.translator.backendopt import graphanalyze
 from pypy.translator.backendopt.support import var_needsgc
 from pypy.annotation import model as annmodel
@@ -151,8 +152,13 @@
             # for regular translation: pick the GC from the config
             GCClass, GC_PARAMS = choose_gc_from_config(translator.config)
 
+        self.root_stack_jit_hook = None
         if hasattr(translator, '_jit2gc'):
             self.layoutbuilder = translator._jit2gc['layoutbuilder']
+            try:
+                self.root_stack_jit_hook = translator._jit2gc['rootstackhook']
+            except KeyError:
+                pass
         else:
             self.layoutbuilder = TransformerLayoutBuilder(translator, GCClass)
         self.layoutbuilder.transformer = self
@@ -500,6 +506,10 @@
         s_gc = self.translator.annotator.bookkeeper.valueoftype(GCClass)
         r_gc = self.translator.rtyper.getrepr(s_gc)
         self.c_const_gc = rmodel.inputconst(r_gc, self.gcdata.gc)
+        s_gc_data = self.translator.annotator.bookkeeper.valueoftype(
+            gctypelayout.GCData)
+        r_gc_data = self.translator.rtyper.getrepr(s_gc_data)
+        self.c_const_gcdata = rmodel.inputconst(r_gc_data, self.gcdata)
         self.malloc_zero_filled = GCClass.malloc_zero_filled
 
         HDR = self.HDR = self.gcdata.gc.gcheaderbuilder.HDR
@@ -786,6 +796,15 @@
                              resulttype=llmemory.Address)
         hop.genop('adr_add', [v_gc_adr, c_ofs], resultvar=op.result)
 
+    def gct_gc_adr_of_root_stack_top(self, hop):
+        op = hop.spaceop
+        ofs = llmemory.offsetof(self.c_const_gcdata.concretetype.TO,
+                                'inst_root_stack_top')
+        c_ofs = rmodel.inputconst(lltype.Signed, ofs)
+        v_gcdata_adr = hop.genop('cast_ptr_to_adr', [self.c_const_gcdata],
+                                 resulttype=llmemory.Address)
+        hop.genop('adr_add', [v_gcdata_adr, c_ofs], resultvar=op.result)
+
     def gct_gc_x_swap_pool(self, hop):
         op = hop.spaceop
         [v_malloced] = op.args
@@ -1327,6 +1346,14 @@
             return top
         self.decr_stack = decr_stack
 
+        self.rootstackhook = gctransformer.root_stack_jit_hook
+        if self.rootstackhook is None:
+            def collect_stack_root(callback, gc, addr):
+                if gc.points_to_valid_gc_object(addr):
+                    callback(gc, addr)
+                return sizeofaddr
+            self.rootstackhook = collect_stack_root
+
     def push_stack(self, addr):
         top = self.incr_stack(1)
         top.address[0] = addr
@@ -1336,10 +1363,7 @@
         return top.address[0]
 
     def allocate_stack(self):
-        result = llmemory.raw_malloc(self.rootstacksize)
-        if result:
-            llmemory.raw_memclear(result, self.rootstacksize)
-        return result
+        return llmemory.raw_malloc(self.rootstacksize)
 
     def setup_root_walker(self):
         stackbase = self.allocate_stack()
@@ -1351,12 +1375,11 @@
     def walk_stack_roots(self, collect_stack_root):
         gcdata = self.gcdata
         gc = self.gc
+        rootstackhook = self.rootstackhook
         addr = gcdata.root_stack_base
         end = gcdata.root_stack_top
         while addr != end:
-            if gc.points_to_valid_gc_object(addr):
-                collect_stack_root(gc, addr)
-            addr += sizeofaddr
+            addr += rootstackhook(collect_stack_root, gc, addr)
         if self.collect_stacks_from_other_threads is not None:
             self.collect_stacks_from_other_threads(collect_stack_root)
 
@@ -1463,12 +1486,11 @@
                 # collect all valid stacks from the dict (the entry
                 # corresponding to the current thread is not valid)
                 gc = self.gc
+                rootstackhook = self.rootstackhook
                 end = stacktop - sizeofaddr
                 addr = end.address[0]
                 while addr != end:
-                    if gc.points_to_valid_gc_object(addr):
-                        callback(gc, addr)
-                    addr += sizeofaddr
+                    addr += rootstackhook(callback, gc, addr)
 
         def collect_more_stacks(callback):
             ll_assert(get_aid() == gcdata.active_thread,

diff --git a/lib_pypy/pyrepl/curses.py b/lib_pypy/pyrepl/curses.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/curses.py
@@ -0,0 +1,39 @@
+
+#   Copyright 2000-2010 Michael Hudson-Doyle <micahel at gmail.com>
+#                       Armin Rigo
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+# Some try-import logic for two purposes: avoiding to bring in the whole
+# pure Python curses package if possible; and, in _curses is not actually
+# present, falling back to _minimal_curses (which is either a ctypes-based
+# pure Python module or a PyPy built-in module).
+try:
+    import _curses
+except ImportError:
+    try:
+        import _minimal_curses as _curses
+    except ImportError:
+        # Who knows, maybe some environment has "curses" but not "_curses".
+        # If not, at least the following import gives a clean ImportError.
+        import _curses
+
+setupterm = _curses.setupterm
+tigetstr = _curses.tigetstr
+tparm = _curses.tparm
+error = _curses.error

diff --git a/pypy/module/cpyext/__init__.py b/pypy/module/cpyext/__init__.py
--- a/pypy/module/cpyext/__init__.py
+++ b/pypy/module/cpyext/__init__.py
@@ -46,10 +46,12 @@
 import pypy.module.cpyext.complexobject
 import pypy.module.cpyext.weakrefobject
 import pypy.module.cpyext.funcobject
+import pypy.module.cpyext.frameobject
 import pypy.module.cpyext.classobject
 import pypy.module.cpyext.pypyintf
 import pypy.module.cpyext.memoryobject
 import pypy.module.cpyext.codecs
+import pypy.module.cpyext.pyfile
 
 # now that all rffi_platform.Struct types are registered, configure them
 api.configure_types()

diff --git a/pypy/translator/backendopt/mallocprediction.py b/pypy/translator/backendopt/mallocprediction.py
--- a/pypy/translator/backendopt/mallocprediction.py
+++ b/pypy/translator/backendopt/mallocprediction.py
@@ -176,7 +176,6 @@
             break
         count += newcount
     for graph in graphs:
-        removenoops.remove_superfluous_keep_alive(graph)
         removenoops.remove_duplicate_casts(graph, translator)
     return count
 

diff --git a/pypy/interpreter/test/test_eval.py b/pypy/interpreter/test/test_eval.py
--- a/pypy/interpreter/test/test_eval.py
+++ b/pypy/interpreter/test/test_eval.py
@@ -13,7 +13,8 @@
             
             def __init__(self, space, code, numlocals):
                 self.code = code
-                Frame.__init__(self, space, numlocals=numlocals)
+                Frame.__init__(self, space)
+                self.numlocals = numlocals
                 self.fastlocals_w = [None] * self.numlocals
 
             def getcode(self):
@@ -24,7 +25,10 @@
 
             def getfastscope(self):
                 return self.fastlocals_w
-        
+
+            def getfastscopelength(self):
+                return self.numlocals
+
         self.f = ConcreteFastscopeFrame(self.space, code, numlocals=5)
         
 

diff --git a/pypy/module/cpyext/include/Python.h b/pypy/module/cpyext/include/Python.h
--- a/pypy/module/cpyext/include/Python.h
+++ b/pypy/module/cpyext/include/Python.h
@@ -102,6 +102,7 @@
 #include "modsupport.h"
 #include "pythonrun.h"
 #include "pyerrors.h"
+#include "sysmodule.h"
 #include "stringobject.h"
 #include "descrobject.h"
 #include "tupleobject.h"
@@ -109,6 +110,8 @@
 #include "intobject.h"
 #include "listobject.h"
 #include "unicodeobject.h"
+#include "compile.h"
+#include "frameobject.h"
 #include "eval.h"
 #include "pymem.h"
 #include "pycobject.h"

diff --git a/pypy/module/cpyext/test/test_cpyext.py b/pypy/module/cpyext/test/test_cpyext.py
--- a/pypy/module/cpyext/test/test_cpyext.py
+++ b/pypy/module/cpyext/test/test_cpyext.py
@@ -106,6 +106,11 @@
             del obj
         import gc; gc.collect()
 
+        try:
+            del space.getexecutioncontext().cpyext_threadstate
+        except AttributeError:
+            pass
+
         for w_obj in state.non_heaptypes_w:
             Py_DecRef(space, w_obj)
         state.non_heaptypes_w[:] = []
@@ -385,6 +390,19 @@
         assert module.__doc__ == "docstring"
         assert module.return_cookie() == 3.14
 
+    def test_load_dynamic(self):
+        import sys
+        init = """
+        if (Py_IsInitialized())
+            Py_InitModule("foo", NULL);
+        """
+        foo = self.import_module(name='foo', init=init)
+        assert 'foo' in sys.modules
+        del sys.modules['foo']
+        import imp
+        foo2 = imp.load_dynamic('foo', foo.__file__)
+        assert 'foo' in sys.modules
+        assert foo.__dict__ == foo2.__dict__
 
     def test_InitModule4_dotted(self):
         """

diff --git a/pypy/doc/config/objspace.extmodules.rst b/pypy/doc/config/objspace.extmodules.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/config/objspace.extmodules.rst
@@ -0,0 +1,12 @@
+You can pass a comma-separated list of third-party builtin modules
+which should be translated along with the standard modules within
+``pypy.module``.
+
+The module names need to be fully qualified (i.e. have a ``.`` in them),
+be on the ``$PYTHONPATH`` and not conflict with any existing ones, e.g.
+``mypkg.somemod``.
+
+Once translated, the module will be accessible with a simple::
+
+    import somemod
+

diff --git a/pypy/jit/codewriter/test/test_regalloc.py b/pypy/jit/codewriter/test/test_regalloc.py
--- a/pypy/jit/codewriter/test/test_regalloc.py
+++ b/pypy/jit/codewriter/test/test_regalloc.py
@@ -9,7 +9,6 @@
 from pypy.objspace.flow.model import c_last_exception
 from pypy.rpython.lltypesystem import lltype, llmemory, rclass
 from pypy.rlib.rarithmetic import ovfcheck
-from pypy.rlib.objectmodel import keepalive_until_here
 
 
 class TestRegAlloc:

diff --git a/pypy/rpython/test/test_rdict.py b/pypy/rpython/test/test_rdict.py
--- a/pypy/rpython/test/test_rdict.py
+++ b/pypy/rpython/test/test_rdict.py
@@ -578,6 +578,26 @@
             res = self.interpret(fn, [3, 3])
             assert res == 123
 
+    def test_dict_popitem(self):
+        def func():
+            d = {}
+            d[5] = 2
+            d[6] = 3
+            k1, v1 = d.popitem()
+            assert len(d) == 1
+            k2, v2 = d.popitem()
+            try:
+                d.popitem()
+            except KeyError:
+                pass
+            else:
+                assert 0, "should have raised KeyError"
+            assert len(d) == 0
+            return k1*1000 + v1*100 + k2*10 + v2
+
+        res = self.interpret(func, [])
+        assert res in [5263, 6352]
+
 
 class TestLLtype(BaseTestRdict, LLRtypeMixin):
     def test_dict_but_not_with_char_keys(self):
@@ -682,26 +702,6 @@
         # if it does not crash, we are fine. It crashes if you forget the hash field.
         self.interpret(func, [])
 
-    def test_dict_popitem(self):
-        def func():
-            d = {}
-            d[5] = 2
-            d[6] = 3
-            k1, v1 = d.popitem()
-            assert len(d) == 1
-            k2, v2 = d.popitem()
-            try:
-                d.popitem()
-            except KeyError:
-                pass
-            else:
-                assert 0, "should have raised KeyError"
-            assert len(d) == 0
-            return k1*1000 + v1*100 + k2*10 + v2
-
-        res = self.interpret(func, [])
-        assert res in [5263, 6352]
-
     # ____________________________________________________________
 
     def test_opt_nullkeymarker(self):

diff --git a/pypy/rpython/lltypesystem/rffi.py b/pypy/rpython/lltypesystem/rffi.py
--- a/pypy/rpython/lltypesystem/rffi.py
+++ b/pypy/rpython/lltypesystem/rffi.py
@@ -306,6 +306,15 @@
 stackcounter = StackCounter()
 stackcounter._freeze_()
 
+def llexternal_use_eci(compilation_info):
+    """Return a dummy function that, if called in a RPython program,
+    adds the given ExternalCompilationInfo to it."""
+    eci = ExternalCompilationInfo(post_include_bits=['#define PYPY_NO_OP()'])
+    eci = eci.merge(compilation_info)
+    return llexternal('PYPY_NO_OP', [], lltype.Void,
+                      compilation_info=eci, sandboxsafe=True, _nowrapper=True,
+                      _callable=lambda: None)
+
 # ____________________________________________________________
 # Few helpers for keeping callback arguments alive
 # this makes passing opaque objects possible (they don't even pass
@@ -738,6 +747,7 @@
     def charpsize2str(cp, size):
         l = [cp[i] for i in range(size)]
         return emptystr.join(l)
+    charpsize2str._annenforceargs_ = [None, int]
 
     return (str2charp, free_charp, charp2str,
             get_nonmovingbuffer, free_nonmovingbuffer,

diff --git a/pypy/translator/backendopt/support.py b/pypy/translator/backendopt/support.py
--- a/pypy/translator/backendopt/support.py
+++ b/pypy/translator/backendopt/support.py
@@ -39,74 +39,6 @@
         # assume PyObjPtr
         return True
 
-def needs_conservative_livevar_calculation(block):
-    from pypy.rpython.lltypesystem import rclass
-    vars = block.getvariables()
-    assert len(block.exits) == 1
-    exitingvars = block.exits[0].args
-    for var in vars:
-        TYPE = getattr(var, "concretetype", lltype.Ptr(lltype.PyObject))
-        if isinstance(TYPE, lltype.Ptr) and not var_needsgc(var):
-            if isinstance(TYPE.TO, lltype.FuncType):
-                continue
-            try:
-                lltype.castable(TYPE, rclass.CLASSTYPE)
-            except lltype.InvalidCast:
-                if var in exitingvars:
-                    return True
-    else:
-        return False
-
-def generate_keepalive(vars, annotator=None):
-    keepalive_ops = []
-    for v in vars:
-        if isinstance(v, Constant):
-            continue
-        if v.concretetype._is_atomic():
-            continue
-        v_keepalive = Variable()
-        v_keepalive.concretetype = lltype.Void
-        if annotator is not None:
-            annotator.setbinding(v_keepalive, s_ImpossibleValue)
-        keepalive_ops.append(SpaceOperation('keepalive', [v], v_keepalive))
-    return keepalive_ops
-
-def split_block_with_keepalive(block, index_operation,
-                               keep_alive_op_args=True,
-                               annotator=None):
-    splitlink = split_block(annotator, block, index_operation)
-    afterblock = splitlink.target
-    conservative_keepalives = needs_conservative_livevar_calculation(block)
-    if conservative_keepalives:
-        keep_alive_vars = [var for var in block.getvariables()
-                               if var_needsgc(var)]
-        # XXX you could maybe remove more, if the variables are kept
-        # alive by something else. but this is sometimes hard to know
-        for i, var in enumerate(keep_alive_vars):
-            try:
-                index = splitlink.args.index(var)
-                newvar = afterblock.inputargs[index]
-            except ValueError:
-                splitlink.args.append(var)
-                newvar = copyvar(annotator, var)
-                afterblock.inputargs.append(newvar)
-            keep_alive_vars[i] = newvar
-    elif keep_alive_op_args and afterblock.operations: 
-        keep_alive_vars = [var for var in afterblock.operations[0].args
-                               if isinstance(var, Variable) and var_needsgc(var)]
-        if len(afterblock.operations) > 1 or afterblock.exitswitch != c_last_exception:
-            afterblock.operations[1:1] = generate_keepalive(keep_alive_vars,
-                                                            annotator=annotator)
-            keep_alive_vars = []
-    else:
-        keep_alive_vars = []
-    pos = len(afterblock.operations)
-    if afterblock.exitswitch == c_last_exception:
-        pos -= 1    # insert the keepalives just before the last operation
-                    # in case of exception-catching
-    afterblock.operations[pos:pos] = generate_keepalive(keep_alive_vars)
-    return splitlink
-
 def find_calls_from(translator, graph, memo=None):
     if memo and graph in memo:
         return memo[graph]

diff --git a/pypy/translator/backendopt/removenoops.py b/pypy/translator/backendopt/removenoops.py
--- a/pypy/translator/backendopt/removenoops.py
+++ b/pypy/translator/backendopt/removenoops.py
@@ -108,15 +108,3 @@
         for i, op in list(enumerate(block.operations))[::-1]:
             if op.opname == "debug_assert":
                 del block.operations[i]
-
-def remove_superfluous_keep_alive(graph):
-    for block in graph.iterblocks():
-        used = {}
-        for i, op in list(enumerate(block.operations))[::-1]:
-            if op.opname == "keepalive":
-                if op.args[0] in used:
-                    del block.operations[i]
-                else:
-                    used[op.args[0]] = True
- 
-

diff --git a/lib_pypy/pyrepl/tests/__init__.py b/lib_pypy/pyrepl/tests/__init__.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/tests/__init__.py
@@ -0,0 +1,20 @@
+#   Copyright 2000-2004 Michael Hudson-Doyle <micahel at gmail.com>
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+# moo

diff --git a/pypy/rpython/test/test_rbuiltin.py b/pypy/rpython/test/test_rbuiltin.py
--- a/pypy/rpython/test/test_rbuiltin.py
+++ b/pypy/rpython/test/test_rbuiltin.py
@@ -496,6 +496,13 @@
         res = self.interpret(llf, [rffi.r_short(123)], policy=LowLevelAnnotatorPolicy())
         assert res == 123
 
+    def test_force_cast(self):
+        def llfn(v):
+            return rffi.cast(rffi.SHORT, v)
+        res = self.interpret(llfn, [0x12345678])
+        assert res == 0x5678
+
+
 class TestLLtype(BaseTestRbuiltin, LLRtypeMixin):
 
     def test_isinstance_obj(self):

diff --git a/pypy/module/_io/interp_bufferedio.py b/pypy/module/_io/interp_bufferedio.py
--- a/pypy/module/_io/interp_bufferedio.py
+++ b/pypy/module/_io/interp_bufferedio.py
@@ -12,7 +12,6 @@
     W_IOBase, DEFAULT_BUFFER_SIZE, convert_size,
     check_readable_w, check_writable_w, check_seekable_w)
 from pypy.module._io.interp_io import W_BlockingIOError
-from pypy.module.thread.os_lock import Lock
 
 STATE_ZERO, STATE_OK, STATE_DETACHED = range(3)
 
@@ -121,7 +120,7 @@
         ## XXX cannot free a Lock?
         ## if self.lock:
         ##     self.lock.free()
-        self.lock = Lock(space)
+        self.lock = space.allocate_lock()
 
         try:
             self._raw_tell(space)

diff --git a/lib_pypy/pyrepl/cmdrepl.py b/lib_pypy/pyrepl/cmdrepl.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/cmdrepl.py
@@ -0,0 +1,118 @@
+#   Copyright 2000-2007 Michael Hudson-Doyle <micahel at gmail.com>
+#                       Maciek Fijalkowski
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+"""Wedge pyrepl behaviour into cmd.Cmd-derived classes.
+
+replize, when given a subclass of cmd.Cmd, returns a class that
+behaves almost identically to the supplied class, except that it uses
+pyrepl instead if raw_input.
+
+It was designed to let you do this:
+
+>>> import pdb
+>>> from pyrepl import replize
+>>> pdb.Pdb = replize(pdb.Pdb)
+
+which is in fact done by the `pythoni' script that comes with
+pyrepl."""
+
+from __future__ import nested_scopes
+
+from pyrepl import completing_reader as cr, reader, completer
+from pyrepl.completing_reader import CompletingReader as CR
+import cmd
+
+class CmdReader(CR):
+    def collect_keymap(self):
+        return super(CmdReader, self).collect_keymap() + (
+            ("\\M-\\n", "invalid-key"),
+            ("\\n", "accept"))
+    
+    CR_init = CR.__init__
+    def __init__(self, completions):
+        self.CR_init(self)
+        self.completions = completions
+
+    def get_completions(self, stem):
+        if len(stem) != self.pos:
+            return []
+        return cr.uniqify([s for s in self.completions
+                           if s.startswith(stem)])
+
+def replize(klass, history_across_invocations=1):
+
+    """Return a subclass of the cmd.Cmd-derived klass that uses
+    pyrepl instead of readline.
+
+    Raises a ValueError if klass does not derive from cmd.Cmd.
+
+    The optional history_across_invocations parameter (default 1)
+    controls whether instances of the returned class share
+    histories."""
+
+    completions = [s[3:]
+                   for s in completer.get_class_members(klass)
+                   if s.startswith("do_")]
+
+    if not issubclass(klass, cmd.Cmd):
+        raise Exception
+#    if klass.cmdloop.im_class is not cmd.Cmd:
+#        print "this may not work"
+
+    class CmdRepl(klass):
+        k_init = klass.__init__
+
+        if history_across_invocations:
+            _CmdRepl__history = []
+            def __init__(self, *args, **kw):
+                self.k_init(*args, **kw)
+                self.__reader = CmdReader(completions)
+                self.__reader.history = CmdRepl._CmdRepl__history
+                self.__reader.historyi = len(CmdRepl._CmdRepl__history)
+        else:
+            def __init__(self, *args, **kw):
+                self.k_init(*args, **kw)
+                self.__reader = CmdReader(completions)
+        
+        def cmdloop(self, intro=None):
+            self.preloop()
+            if intro is not None:
+                self.intro = intro
+            if self.intro:
+                print self.intro
+            stop = None
+            while not stop:
+                if self.cmdqueue:
+                    line = self.cmdqueue[0]
+                    del self.cmdqueue[0]
+                else:
+                    try:
+                        self.__reader.ps1 = self.prompt
+                        line = self.__reader.readline()
+                    except EOFError:
+                        line = "EOF"
+                line = self.precmd(line)
+                stop = self.onecmd(line)
+                stop = self.postcmd(stop, line)
+            self.postloop()
+
+    CmdRepl.__name__ = "replize(%s.%s)"%(klass.__module__, klass.__name__)
+    return CmdRepl
+

diff --git a/lib_pypy/pyrepl/historical_reader.py b/lib_pypy/pyrepl/historical_reader.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/historical_reader.py
@@ -0,0 +1,311 @@
+#   Copyright 2000-2004 Michael Hudson-Doyle <micahel at gmail.com>
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+from pyrepl import reader, commands
+from pyrepl.reader import Reader as R
+
+isearch_keymap = tuple(
+    [('\\%03o'%c, 'isearch-end') for c in range(256) if chr(c) != '\\'] + \
+    [(c, 'isearch-add-character')
+     for c in map(chr, range(32, 127)) if c != '\\'] + \
+    [('\\%03o'%c, 'isearch-add-character')
+     for c in range(256) if chr(c).isalpha() and chr(c) != '\\'] + \
+    [('\\\\', 'self-insert'),
+     (r'\C-r', 'isearch-backwards'),
+     (r'\C-s', 'isearch-forwards'),
+     (r'\C-c', 'isearch-cancel'),
+     (r'\C-g', 'isearch-cancel'),
+     (r'\<backspace>', 'isearch-backspace')])
+
+del c
+
+ISEARCH_DIRECTION_NONE = ''
+ISEARCH_DIRECTION_BACKWARDS = 'r'
+ISEARCH_DIRECTION_FORWARDS = 'f'
+
+class next_history(commands.Command):
+    def do(self):
+        r = self.reader
+        if r.historyi == len(r.history):
+            r.error("end of history list")
+            return
+        r.select_item(r.historyi + 1)
+
+class previous_history(commands.Command):
+    def do(self):
+        r = self.reader
+        if r.historyi == 0:
+            r.error("start of history list")
+            return
+        r.select_item(r.historyi - 1)
+
+class restore_history(commands.Command):
+    def do(self):
+        r = self.reader
+        if r.historyi != len(r.history):
+            if r.get_unicode() != r.history[r.historyi]:
+                r.buffer = list(r.history[r.historyi])
+                r.pos = len(r.buffer)
+                r.dirty = 1
+
+class first_history(commands.Command):
+    def do(self):
+        self.reader.select_item(0)
+
+class last_history(commands.Command):
+    def do(self):
+        self.reader.select_item(len(self.reader.history))
+
+class operate_and_get_next(commands.FinishCommand):
+    def do(self):
+        self.reader.next_history = self.reader.historyi + 1
+
+class yank_arg(commands.Command):
+    def do(self):
+        r = self.reader
+        if r.last_command is self.__class__:
+            r.yank_arg_i += 1
+        else:
+            r.yank_arg_i = 0
+        if r.historyi < r.yank_arg_i:
+            r.error("beginning of history list")
+            return
+        a = r.get_arg(-1)
+        # XXX how to split?
+        words = r.get_item(r.historyi - r.yank_arg_i - 1).split()
+        if a < -len(words) or a >= len(words):
+            r.error("no such arg")
+            return
+        w = words[a]
+        b = r.buffer
+        if r.yank_arg_i > 0:
+            o = len(r.yank_arg_yanked)
+        else:
+            o = 0
+        b[r.pos - o:r.pos] = list(w)
+        r.yank_arg_yanked = w
+        r.pos += len(w) - o
+        r.dirty = 1
+
+class forward_history_isearch(commands.Command):
+    def do(self):
+        r = self.reader
+        r.isearch_direction = ISEARCH_DIRECTION_FORWARDS
+        r.isearch_start = r.historyi, r.pos
+        r.isearch_term = ''
+        r.dirty = 1
+        r.push_input_trans(r.isearch_trans)
+        
+
+class reverse_history_isearch(commands.Command):
+    def do(self):
+        r = self.reader
+        r.isearch_direction = ISEARCH_DIRECTION_BACKWARDS
+        r.dirty = 1
+        r.isearch_term = ''
+        r.push_input_trans(r.isearch_trans)
+        r.isearch_start = r.historyi, r.pos
+
+class isearch_cancel(commands.Command):
+    def do(self):
+        r = self.reader
+        r.isearch_direction = ISEARCH_DIRECTION_NONE
+        r.pop_input_trans()
+        r.select_item(r.isearch_start[0])
+        r.pos = r.isearch_start[1]
+        r.dirty = 1
+
+class isearch_add_character(commands.Command):
+    def do(self):
+        r = self.reader
+        b = r.buffer
+        r.isearch_term += self.event[-1]
+        r.dirty = 1
+        p = r.pos + len(r.isearch_term) - 1
+        if b[p:p+1] != [r.isearch_term[-1]]:
+            r.isearch_next()
+
+class isearch_backspace(commands.Command):
+    def do(self):
+        r = self.reader
+        if len(r.isearch_term) > 0:
+            r.isearch_term = r.isearch_term[:-1]
+            r.dirty = 1
+        else:
+            r.error("nothing to rubout")
+
+class isearch_forwards(commands.Command):
+    def do(self):
+        r = self.reader
+        r.isearch_direction = ISEARCH_DIRECTION_FORWARDS
+        r.isearch_next()
+
+class isearch_backwards(commands.Command):
+    def do(self):
+        r = self.reader
+        r.isearch_direction = ISEARCH_DIRECTION_BACKWARDS
+        r.isearch_next()
+
+class isearch_end(commands.Command):
+    def do(self):
+        r = self.reader
+        r.isearch_direction = ISEARCH_DIRECTION_NONE
+        r.console.forgetinput()
+        r.pop_input_trans()
+        r.dirty = 1
+
+class HistoricalReader(R):
+    """Adds history support (with incremental history searching) to the
+    Reader class.
+
+    Adds the following instance variables:
+      * history:
+        a list of strings
+      * historyi:
+      * transient_history:
+      * next_history:
+      * isearch_direction, isearch_term, isearch_start:
+      * yank_arg_i, yank_arg_yanked:
+        used by the yank-arg command; not actually manipulated by any
+        HistoricalReader instance methods.
+    """
+
+    def collect_keymap(self):
+        return super(HistoricalReader, self).collect_keymap() + (
+            (r'\C-n', 'next-history'),
+            (r'\C-p', 'previous-history'),
+            (r'\C-o', 'operate-and-get-next'),
+            (r'\C-r', 'reverse-history-isearch'),
+            (r'\C-s', 'forward-history-isearch'),
+            (r'\M-r', 'restore-history'),
+            (r'\M-.', 'yank-arg'),
+            (r'\<page down>', 'last-history'),
+            (r'\<page up>', 'first-history'))
+
+
+    def __init__(self, console):
+        super(HistoricalReader, self).__init__(console)
+        self.history = []
+        self.historyi = 0
+        self.transient_history = {}
+        self.next_history = None
+        self.isearch_direction = ISEARCH_DIRECTION_NONE
+        for c in [next_history, previous_history, restore_history,
+                  first_history, last_history, yank_arg,
+                  forward_history_isearch, reverse_history_isearch,
+                  isearch_end, isearch_add_character, isearch_cancel,
+                  isearch_add_character, isearch_backspace,
+                  isearch_forwards, isearch_backwards, operate_and_get_next]:
+            self.commands[c.__name__] = c
+            self.commands[c.__name__.replace('_', '-')] = c
+        from pyrepl import input
+        self.isearch_trans = input.KeymapTranslator(
+            isearch_keymap, invalid_cls=isearch_end,
+            character_cls=isearch_add_character)
+        
+    def select_item(self, i):
+        self.transient_history[self.historyi] = self.get_unicode()
+        buf = self.transient_history.get(i)
+        if buf is None:
+            buf = self.history[i]
+        self.buffer = list(buf)
+        self.historyi = i
+        self.pos = len(self.buffer)
+        self.dirty = 1
+
+    def get_item(self, i):
+        if i <> len(self.history):
+            return self.transient_history.get(i, self.history[i])
+        else:
+            return self.transient_history.get(i, self.get_unicode())
+
+    def prepare(self):
+        super(HistoricalReader, self).prepare()
+        try:
+            self.transient_history = {}
+            if self.next_history is not None \
+               and self.next_history < len(self.history):
+                self.historyi = self.next_history
+                self.buffer[:] = list(self.history[self.next_history])
+                self.pos = len(self.buffer)
+                self.transient_history[len(self.history)] = ''
+            else:
+                self.historyi = len(self.history)
+            self.next_history = None
+        except:
+            self.restore()
+            raise
+
+    def get_prompt(self, lineno, cursor_on_line):
+        if cursor_on_line and self.isearch_direction <> ISEARCH_DIRECTION_NONE:
+            d = 'rf'[self.isearch_direction == ISEARCH_DIRECTION_FORWARDS]
+            return "(%s-search `%s') "%(d, self.isearch_term)
+        else:
+            return super(HistoricalReader, self).get_prompt(lineno, cursor_on_line)
+
+    def isearch_next(self):
+        st = self.isearch_term
+        p = self.pos
+        i = self.historyi
+        s = self.get_unicode()
+        forwards = self.isearch_direction == ISEARCH_DIRECTION_FORWARDS
+        while 1:
+            if forwards:
+                p = s.find(st, p + 1)
+            else:
+                p = s.rfind(st, 0, p + len(st) - 1)
+            if p != -1:
+                self.select_item(i)
+                self.pos = p
+                return
+            elif ((forwards and i == len(self.history) - 1)
+                  or (not forwards and i == 0)):
+                self.error("not found")
+                return
+            else:
+                if forwards:
+                    i += 1
+                    s = self.get_item(i)
+                    p = -1
+                else:
+                    i -= 1
+                    s = self.get_item(i)
+                    p = len(s)
+
+    def finish(self):
+        super(HistoricalReader, self).finish()
+        ret = self.get_unicode()
+        for i, t in self.transient_history.items():
+            if i < len(self.history) and i != self.historyi:
+                self.history[i] = t
+        if ret:
+            self.history.append(ret)
+
+def test():
+    from pyrepl.unix_console import UnixConsole
+    reader = HistoricalReader(UnixConsole())
+    reader.ps1 = "h**> "
+    reader.ps2 = "h/*> "
+    reader.ps3 = "h|*> "
+    reader.ps4 = "h\*> "
+    while reader.readline():
+        pass
+
+if __name__=='__main__':
+    test()

diff --git a/pypy/module/cpyext/src/modsupport.c b/pypy/module/cpyext/src/modsupport.c
--- a/pypy/module/cpyext/src/modsupport.c
+++ b/pypy/module/cpyext/src/modsupport.c
@@ -241,13 +241,12 @@
 
 		case 'I':
 		{
-      Py_FatalError("I unsupported so far");
-			//unsigned int n;
-			//n = va_arg(*p_va, unsigned int);
-			//if (n > (unsigned long)PyInt_GetMax())
-			//	return PyLong_FromUnsignedLong((unsigned long)n);
-			//else
-			//	return PyInt_FromLong(n);
+			unsigned int n;
+			n = va_arg(*p_va, unsigned int);
+			if (n > (unsigned long)PyInt_GetMax())
+				return PyLong_FromUnsignedLong((unsigned long)n);
+			else
+				return PyInt_FromLong(n);
 		}
 		
 		case 'n':
@@ -260,23 +259,20 @@
 
 		case 'k':
 		{
-      Py_FatalError("Py_BuildValue k unsupported so far\n");
-			/* unsigned long n; */
-			/* n = va_arg(*p_va, unsigned long); */
-			/* if (n > (unsigned long)PyInt_GetMax()) */
-			/* 	return PyLong_FromUnsignedLong(n); */
-			/* else */
-			/* 	return PyInt_FromLong(n); */
+			unsigned long n;
+			n = va_arg(*p_va, unsigned long);
+			if (n > (unsigned long)PyInt_GetMax())
+				return PyLong_FromUnsignedLong(n);
+			else
+				return PyInt_FromLong(n);
 		}
 
 #ifdef HAVE_LONG_LONG
 		case 'L':
-      Py_FatalError("Py_BuildValue L unsupported for now\n");
-			//return PyLong_FromLongLong((PY_LONG_LONG)va_arg(*p_va, PY_LONG_LONG));
+			return PyLong_FromLongLong((PY_LONG_LONG)va_arg(*p_va, PY_LONG_LONG));
 
 		case 'K':
-      Py_FatalError("Py_BuildValue K unsupported for now\n");
-			//return PyLong_FromUnsignedLongLong((PY_LONG_LONG)va_arg(*p_va, unsigned PY_LONG_LONG));
+			return PyLong_FromUnsignedLongLong((PY_LONG_LONG)va_arg(*p_va, unsigned PY_LONG_LONG));
 #endif
 #ifdef Py_USING_UNICODE
 		case 'u':

diff --git a/pypy/interpreter/test/test_interpreter.py b/pypy/interpreter/test/test_interpreter.py
--- a/pypy/interpreter/test/test_interpreter.py
+++ b/pypy/interpreter/test/test_interpreter.py
@@ -283,9 +283,14 @@
         sys.stdout = out = Out()
         try:
             raises(UnicodeError, "print unichr(0xa2)")
+            assert out.data == []
             out.encoding = "cp424"
             print unichr(0xa2)
             assert out.data == [unichr(0xa2).encode("cp424"), "\n"]
+            del out.data[:]
+            del out.encoding
+            print u"foo\t", u"bar\n", u"trick", u"baz\n"  # softspace handling
+            assert out.data == ["foo\t", "bar\n", "trick", " ", "baz\n", "\n"]
         finally:
             sys.stdout = save
 

diff --git a/pypy/module/imp/test/test_app.py b/pypy/module/imp/test/test_app.py
--- a/pypy/module/imp/test/test_app.py
+++ b/pypy/module/imp/test/test_app.py
@@ -1,3 +1,4 @@
+from __future__ import with_statement
 MARKER = 42
 
 class AppTestImpModule:
@@ -34,7 +35,8 @@
 
     def test_load_dynamic(self):
         raises(ImportError, self.imp.load_dynamic, 'foo', 'bar')
-        raises(ImportError, self.imp.load_dynamic, 'foo', 'bar', 'baz.so')
+        raises(ImportError, self.imp.load_dynamic, 'foo', 'bar',
+               open(self.file_module))
 
     def test_suffixes(self):
         for suffix, mode, type in self.imp.get_suffixes():
@@ -138,3 +140,58 @@
         )
         # Doesn't end up in there when run with -A
         assert sys.path_importer_cache.get(lib_pypy) is None
+
+    def test_rewrite_pyc_check_code_name(self):
+        # This one is adapted from cpython's Lib/test/test_import.py
+        from os import chmod
+        from os.path import join
+        from sys import modules, path
+        from shutil import rmtree
+        from tempfile import mkdtemp
+        code = """if 1:
+            import sys
+            code_filename = sys._getframe().f_code.co_filename
+            module_filename = __file__
+            constant = 1
+            def func():
+                pass
+            func_filename = func.func_code.co_filename
+            """
+
+        module_name = "unlikely_module_name"
+        dir_name = mkdtemp(prefix='pypy_test')
+        file_name = join(dir_name, module_name + '.py')
+        with open(file_name, "wb") as f:
+            f.write(code)
+        compiled_name = file_name + ("c" if __debug__ else "o")
+        chmod(file_name, 0777)
+
+        # Setup
+        sys_path = path[:]
+        orig_module = modules.pop(module_name, None)
+        assert modules.get(module_name) == None
+        path.insert(0, dir_name)
+
+        # Test
+        import py_compile
+        py_compile.compile(file_name, dfile="another_module.py")
+        __import__(module_name, globals(), locals())
+        mod = modules.get(module_name)
+
+        try:
+            # Ensure proper results
+            assert mod != orig_module
+            assert mod.module_filename == compiled_name
+            assert mod.code_filename == file_name
+            assert mod.func_filename == file_name
+        finally:
+            # TearDown
+            path[:] = sys_path
+            if orig_module is not None:
+                modules[module_name] = orig_module
+            else:
+                try:
+                    del modules[module_name]
+                except KeyError:
+                    pass
+            rmtree(dir_name, True)

diff --git a/pypy/module/cpyext/eval.py b/pypy/module/cpyext/eval.py
--- a/pypy/module/cpyext/eval.py
+++ b/pypy/module/cpyext/eval.py
@@ -112,6 +112,7 @@
     try:
         while True:
             count = fread(buf, 1, BUF_SIZE, fp)
+            count = rffi.cast(lltype.Signed, count)
             source += rffi.charpsize2str(buf, count)
             if count < BUF_SIZE:
                 if feof(fp):

diff --git a/pypy/module/cpyext/test/test_bufferobject.py b/pypy/module/cpyext/test/test_bufferobject.py
--- a/pypy/module/cpyext/test/test_bufferobject.py
+++ b/pypy/module/cpyext/test/test_bufferobject.py
@@ -46,4 +46,5 @@
                  return PyBuffer_New(150);
              """),
             ])
-        module.buffer_new()
+        b = module.buffer_new()
+        raises(AttributeError, getattr, b, 'x')

diff --git a/pypy/translator/jvm/metavm.py b/pypy/translator/jvm/metavm.py
--- a/pypy/translator/jvm/metavm.py
+++ b/pypy/translator/jvm/metavm.py
@@ -1,4 +1,5 @@
 from pypy.rpython.ootypesystem import ootype
+from pypy.rpython.lltypesystem import rffi
 from pypy.translator.oosupport.metavm import MicroInstruction
 from pypy.translator.jvm.typesystem import JvmScalarType, JvmClassType
 import pypy.translator.jvm.typesystem as jvm
@@ -94,14 +95,20 @@
     (ootype.SignedLongLong,   ootype.Signed):           jvm.L2I,
     (ootype.UnsignedLongLong, ootype.Unsigned):         jvm.L2I,
     (ootype.UnsignedLongLong, ootype.Signed):           jvm.L2I,
+    (ootype.Signed,           rffi.SHORT):              jvm.I2S,
+    (ootype.Unsigned,         ootype.SignedLongLong):   jvm.PYPYUINTTOLONG,
     (ootype.UnsignedLongLong, ootype.SignedLongLong):   None,
     (ootype.SignedLongLong,   ootype.UnsignedLongLong): None,
+    (ootype.Signed,           ootype.Unsigned):         None,
+    (ootype.Unsigned,         ootype.Signed):           None,
     }
 
 class _CastPrimitive(MicroInstruction):
     def render(self, generator, op):
         FROM = op.args[0].concretetype
         TO = op.result.concretetype
+        if TO == FROM:
+            return
         opcode = CASTS[(FROM, TO)]
         if opcode:
             generator.emit(opcode)

diff --git a/pypy/module/imp/importing.py b/pypy/module/imp/importing.py
--- a/pypy/module/imp/importing.py
+++ b/pypy/module/imp/importing.py
@@ -10,6 +10,7 @@
 from pypy.interpreter.error import OperationError, operationerrfmt
 from pypy.interpreter.baseobjspace import Wrappable
 from pypy.interpreter.eval import Code
+from pypy.interpreter.pycode import PyCode
 from pypy.rlib import streamio, jit, rposix
 from pypy.rlib.streamio import StreamErrors
 from pypy.rlib.rarithmetic import intmask
@@ -31,6 +32,7 @@
 else:
     SO = ".so"
 DEFAULT_SOABI = 'pypy-14'
+CHECK_FOR_PYW = sys.platform == 'win32'
 
 @specialize.memo()
 def get_so_extension(space):
@@ -57,6 +59,12 @@
     if os.path.exists(pyfile) and case_ok(pyfile):
         return PY_SOURCE, ".py", "U"
 
+    # on Windows, also check for a .pyw file
+    if CHECK_FOR_PYW:
+        pyfile = filepart + ".pyw"
+        if os.path.exists(pyfile) and case_ok(pyfile):
+            return PY_SOURCE, ".pyw", "U"
+
     # The .py file does not exist.  By default on PyPy, lonepycfiles
     # is False: if a .py file does not exist, we don't even try to
     # look for a lone .pyc file.
@@ -84,6 +92,9 @@
     # XXX that's slow
     def case_ok(filename):
         index = filename.rfind(os.sep)
+        if os.altsep is not None:
+            index2 = filename.rfind(os.altsep)
+            index = max(index, index2)
         if index < 0:
             directory = os.curdir
         else:
@@ -774,10 +785,24 @@
         if space.config.objspace.usepycfiles and write_pyc:
             write_compiled_module(space, code_w, cpathname, mode, mtime)
 
+    update_code_filenames(space, code_w, pathname)
     exec_code_module(space, w_mod, code_w)
 
     return w_mod
 
+def update_code_filenames(space, code_w, pathname, oldname=None):
+    assert isinstance(code_w, PyCode)
+    if oldname is None:
+        oldname = code_w.co_filename
+    elif code_w.co_filename != oldname:
+        return
+
+    code_w.co_filename = pathname
+    constants = code_w.co_consts_w
+    for const in constants:
+        if const is not None and isinstance(const, PyCode):
+            update_code_filenames(space, const, pathname, oldname)
+
 def _get_long(s):
     a = ord(s[0])
     b = ord(s[1])

diff --git a/pypy/jit/backend/x86/test/test_rx86_64_auto_encoding.py b/pypy/jit/backend/x86/test/test_rx86_64_auto_encoding.py
--- a/pypy/jit/backend/x86/test/test_rx86_64_auto_encoding.py
+++ b/pypy/jit/backend/x86/test/test_rx86_64_auto_encoding.py
@@ -18,7 +18,6 @@
     def should_skip_instruction(self, instrname, argmodes):
         return (
                 super(TestRx86_64, self).should_skip_instruction(instrname, argmodes) or
-                ('j' in argmodes) or
                 # Not testing FSTP on 64-bit for now
                 (instrname == 'FSTP')
         )


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
@@ -311,8 +311,7 @@
         # EggBlocks reuse the variables of their previous block,
         # which is deemed not acceptable for simplicity of the operations
         # that will be performed later on the flow graph.
-        def fixegg(link):
-            if isinstance(link, Link):
+        for link in list(self.graph.iterlinks()):
                 block = link.target
                 if isinstance(block, EggBlock):
                     if (not block.operations and len(block.exits) == 1 and
@@ -324,15 +323,14 @@
                         link.args = list(link2.args)
                         link.target = link2.target
                         assert link2.exitcase is None
-                        fixegg(link)
                     else:
                         mapping = {}
                         for a in block.inputargs:
                             mapping[a] = Variable(a)
                         block.renamevariables(mapping)
-            elif isinstance(link, SpamBlock):
+        for block in self.graph.iterblocks():
+            if isinstance(link, SpamBlock):
                 del link.framestate     # memory saver
-        traverse(fixegg, self.graph)
 
     def mergeblock(self, currentblock, currentstate):
         next_instr = currentstate.next_instr

diff --git a/pypy/module/cpyext/stubs.py b/pypy/module/cpyext/stubs.py
--- a/pypy/module/cpyext/stubs.py
+++ b/pypy/module/cpyext/stubs.py
@@ -351,14 +351,6 @@
     """Return the number of free variables in co."""
     raise NotImplementedError
 
- at cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real, PyObject, PyObject, PyObject, PyObject, PyObject, PyObject, PyObject, PyObject, rffi.INT_real, PyObject], PyCodeObject)
-def PyCode_New(space, argcount, nlocals, stacksize, flags, code, consts, names, varnames, freevars, cellvars, filename, name, firstlineno, lnotab):
-    """Return a new code object.  If you need a dummy code object to
-    create a frame, use PyCode_NewEmpty() instead.  Calling
-    PyCode_New() directly can bind you to a precise Python
-    version since the definition of the bytecode changes often."""
-    raise NotImplementedError
-
 @cpython_api([PyObject], rffi.INT_real, error=-1)
 def PyCodec_Register(space, search_function):
     """Register a new codec search function.
@@ -745,13 +737,6 @@
     described there."""
     raise NotImplementedError
 
- at cpython_api([], lltype.Void)
-def PyErr_SetInterrupt(space):
-    """This function simulates the effect of a SIGINT signal arriving --- the
-    next time PyErr_CheckSignals() is called, KeyboardInterrupt will be raised.
-    It may be called without holding the interpreter lock."""
-    raise NotImplementedError
-
 @cpython_api([rffi.INT_real], rffi.INT_real, error=CANNOT_FAIL)
 def PySignal_SetWakeupFd(space, fd):
     """This utility function specifies a file descriptor to which a '\0' byte will
@@ -850,13 +835,6 @@
     successful invocation of Py_EnterRecursiveCall()."""
     raise NotImplementedError
 
- at cpython_api([FILE, rffi.CCHARP, rffi.CCHARP, rffi.INT_real], PyObject)
-def PyFile_FromFile(space, fp, name, mode, close):
-    """Create a new PyFileObject from the already-open standard C file
-    pointer, fp.  The function close will be called when the file should be
-    closed.  Return NULL on failure."""
-    raise NotImplementedError
-
 @cpython_api([PyFileObject], lltype.Void)
 def PyFile_IncUseCount(space, p):
     """Increments the PyFileObject's internal use count to indicate
@@ -899,12 +877,6 @@
     borrow_from()
     raise NotImplementedError
 
- at cpython_api([PyFileObject, rffi.INT_real], lltype.Void)
-def PyFile_SetBufSize(space, p, n):
-    """Available on systems with setvbuf() only.  This should only be called
-    immediately after file object creation."""
-    raise NotImplementedError
-
 @cpython_api([PyFileObject, rffi.CCHARP], rffi.INT_real, error=0)
 def PyFile_SetEncoding(space, p, enc):
     """Set the file's encoding for Unicode output to enc. Return 1 on success and 0
@@ -941,12 +913,6 @@
     appropriate exception will be set."""
     raise NotImplementedError
 
- at cpython_api([rffi.CCHARP, PyObject], rffi.INT_real, error=-1)
-def PyFile_WriteString(space, s, p):
-    """Write string s to file object p.  Return 0 on success or -1 on
-    failure; the appropriate exception will be set."""
-    raise NotImplementedError
-
 @cpython_api([], PyObject)
 def PyFloat_GetInfo(space):
     """Return a structseq instance which contains information about the
@@ -1142,20 +1108,6 @@
     with an exception set on failure (the module still exists in this case)."""
     raise NotImplementedError
 
- at cpython_api([rffi.CCHARP], PyObject)
-def PyImport_AddModule(space, name):
-    """Return the module object corresponding to a module name.  The name argument
-    may be of the form package.module. First check the modules dictionary if
-    there's one there, and if not, create a new one and insert it in the modules
-    dictionary. Return NULL with an exception set on failure.
-    
-    This function does not load or import the module; if the module wasn't already
-    loaded, you will get an empty module object. Use PyImport_ImportModule()
-    or one of its variants to import a module.  Package structures implied by a
-    dotted name for name are not created if not already present."""
-    borrow_from()
-    raise NotImplementedError
-
 @cpython_api([rffi.CCHARP, PyObject], PyObject)
 def PyImport_ExecCodeModule(space, name, co):
     """Given a module name (possibly of the form package.module) and a code
@@ -1770,12 +1722,6 @@
     """
     raise NotImplementedError
 
- at cpython_api([], lltype.Signed, error=CANNOT_FAIL)
-def PyInt_GetMax(space):
-    """Return the system's idea of the largest integer it can handle (LONG_MAX,
-    as defined in the system header files)."""
-    raise NotImplementedError
-
 @cpython_api([], rffi.INT_real, error=CANNOT_FAIL)
 def PyInt_ClearFreeList(space):
     """Clear the integer free list. Return the number of items that could not
@@ -1997,14 +1943,6 @@
     """
     raise NotImplementedError
 
- at cpython_api([PyObject, PyObject, rffi.INTP], rffi.INT_real, error=-1)
-def PyObject_Cmp(space, o1, o2, result):
-    """Compare the values of o1 and o2 using a routine provided by o1, if one
-    exists, otherwise with a routine provided by o2.  The result of the
-    comparison is returned in result.  Returns -1 on failure.  This is the
-    equivalent of the Python statement result = cmp(o1, o2)."""
-    raise NotImplementedError
-
 @cpython_api([PyObject], PyObject)
 def PyObject_Bytes(space, o):
     """Compute a bytes representation of object o.  In 2.x, this is just a alias
@@ -2336,28 +2274,6 @@
     (: on Unix, ; on Windows)."""
     raise NotImplementedError
 
- at cpython_api([rffi.CCHARP, ], lltype.Void)
-def PySys_WriteStdout(space, format):
-    """Write the output string described by format to sys.stdout.  No
-    exceptions are raised, even if truncation occurs (see below).
-    
-    format should limit the total size of the formatted output string to
-    1000 bytes or less -- after 1000 bytes, the output string is truncated.
-    In particular, this means that no unrestricted "%s" formats should occur;
-    these should be limited using "%.<N>s" where <N> is a decimal number
-    calculated so that <N> plus the maximum size of other formatted text does not
-    exceed 1000 bytes.  Also watch out for "%f", which can print hundreds of
-    digits for very large numbers.
-    
-    If a problem occurs, or sys.stdout is unset, the formatted message
-    is written to the real (C level) stdout."""
-    raise NotImplementedError
-
- at cpython_api([rffi.CCHARP, ], lltype.Void)
-def PySys_WriteStderr(space, format):
-    """As above, but write to sys.stderr or stderr instead."""
-    raise NotImplementedError
-
 @cpython_api([rffi.INT_real], lltype.Void)
 def Py_Exit(space, status):
     """Exit the current process.  This calls Py_Finalize() and then calls the

diff --git a/pypy/rpython/lltypesystem/rstr.py b/pypy/rpython/lltypesystem/rstr.py
--- a/pypy/rpython/lltypesystem/rstr.py
+++ b/pypy/rpython/lltypesystem/rstr.py
@@ -722,31 +722,75 @@
         newlen = len(s1.chars) - 1
         return LLHelpers._ll_stringslice(s1, 0, newlen)
 
-    def ll_split_chr(LIST, s, c):
+    def ll_split_chr(LIST, s, c, max):
         chars = s.chars
         strlen = len(chars)
         count = 1
         i = 0
+        if max == 0:
+            i = strlen
         while i < strlen:
             if chars[i] == c:
                 count += 1
+                if max >= 0 and count > max:
+                    break
             i += 1
         res = LIST.ll_newlist(count)
         items = res.ll_items()
         i = 0
         j = 0
         resindex = 0
+        if max == 0:
+            j = strlen
         while j < strlen:
             if chars[j] == c:
                 item = items[resindex] = s.malloc(j - i)
                 item.copy_contents(s, item, i, 0, j - i)
                 resindex += 1
                 i = j + 1
+                if max >= 0 and resindex >= max:
+                    j = strlen
+                    break
             j += 1
         item = items[resindex] = s.malloc(j - i)
         item.copy_contents(s, item, i, 0, j - i)
         return res
 
+    def ll_rsplit_chr(LIST, s, c, max):
+        chars = s.chars
+        strlen = len(chars)
+        count = 1
+        i = 0
+        if max == 0:
+            i = strlen
+        while i < strlen:
+            if chars[i] == c:
+                count += 1
+                if max >= 0 and count > max:
+                    break
+            i += 1
+        res = LIST.ll_newlist(count)
+        items = res.ll_items()
+        i = strlen
+        j = strlen
+        resindex = count - 1
+        assert resindex >= 0
+        if max == 0:
+            j = 0
+        while j > 0:
+            j -= 1
+            if chars[j] == c:
+                item = items[resindex] = s.malloc(i - j - 1)
+                item.copy_contents(s, item, j + 1, 0, i - j - 1)
+                resindex -= 1
+                i = j
+                if resindex == 0:
+                    j = 0
+                    break
+        item = items[resindex] = s.malloc(i - j)
+        item.copy_contents(s, item, j, 0, i - j)
+        return res
+
     @purefunction
     def ll_replace_chr_chr(s, c1, c2):
         length = len(s.chars)

diff --git a/pypy/translator/backendopt/mallocv.py b/pypy/translator/backendopt/mallocv.py
--- a/pypy/translator/backendopt/mallocv.py
+++ b/pypy/translator/backendopt/mallocv.py
@@ -846,22 +846,6 @@
         else:
             return self.handle_default(op)
 
-    def handle_op_keepalive(self, op):
-        node = self.getnode(op.args[0])
-        if isinstance(node, VirtualSpecNode):
-            rtnodes, vtnodes = find_all_nodes([node])
-            newops = []
-            for rtnode in rtnodes:
-                v = self.renamings[rtnode]
-                if isinstance(v, Variable):
-                    T = v.concretetype
-                    if isinstance(T, lltype.Ptr) and T._needsgc():
-                        v0 = varoftype(lltype.Void)
-                        newops.append(SpaceOperation('keepalive', [v], v0))
-            return newops
-        else:
-            return self.handle_default(op)
-
     def handle_op_ptr_nonzero(self, op):
         node = self.getnode(op.args[0])
         if isinstance(node, VirtualSpecNode):


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
@@ -43,9 +43,14 @@
 
 class SizeDescr(AbstractDescr):
     size = 0      # help translation
+    is_immutable = False
 
-    def __init__(self, size):
+    def __init__(self, size, count_fields_if_immut=-1):
         self.size = size
+        self.count_fields_if_immut = count_fields_if_immut
+
+    def count_fields_if_immutable(self):
+        return self.count_fields_if_immut
 
     def repr_of_descr(self):
         return '<SizeDescr %s>' % self.size
@@ -62,15 +67,15 @@
         return cache[STRUCT]
     except KeyError:
         size = symbolic.get_size(STRUCT, gccache.translate_support_code)
+        count_fields_if_immut = heaptracker.count_fields_if_immutable(STRUCT)
         if heaptracker.has_gcstruct_a_vtable(STRUCT):
-            sizedescr = SizeDescrWithVTable(size)
+            sizedescr = SizeDescrWithVTable(size, count_fields_if_immut)
         else:
-            sizedescr = SizeDescr(size)
+            sizedescr = SizeDescr(size, count_fields_if_immut)
         gccache.init_size_descr(STRUCT, sizedescr)
         cache[STRUCT] = sizedescr
         return sizedescr
 
-
 # ____________________________________________________________
 # FieldDescrs
 

diff --git a/pypy/jit/backend/x86/regloc.py b/pypy/jit/backend/x86/regloc.py
--- a/pypy/jit/backend/x86/regloc.py
+++ b/pypy/jit/backend/x86/regloc.py
@@ -283,9 +283,15 @@
             # These are the worst cases:
             val2 = loc2.value_i()
             code1 = loc1.location_code()
-            if (code1 == 'j'
-                or (code1 == 'm' and not rx86.fits_in_32bits(loc1.value_m()[1]))
-                or (code1 == 'a' and not rx86.fits_in_32bits(loc1.value_a()[3]))):
+            if code1 == 'j':
+                checkvalue = loc1.value_j()
+            elif code1 == 'm':
+                checkvalue = loc1.value_m()[1]
+            elif code1 == 'a':
+                checkvalue = loc1.value_a()[3]
+            else:
+                checkvalue = 0
+            if not rx86.fits_in_32bits(checkvalue):
                 # INSN_ji, and both operands are 64-bit; or INSN_mi or INSN_ai
                 # and the constant offset in the address is 64-bit.
                 # Hopefully this doesn't happen too often
@@ -330,10 +336,10 @@
                         if code1 == possible_code1:
                             val1 = getattr(loc1, "value_" + possible_code1)()
                             # More faking out of certain operations for x86_64
-                            if self.WORD == 8 and possible_code1 == 'j':
+                            if possible_code1 == 'j' and not rx86.fits_in_32bits(val1):
                                 val1 = self._addr_as_reg_offset(val1)
                                 invoke(self, "m" + possible_code2, val1, val2)
-                            elif self.WORD == 8 and possible_code2 == 'j':
+                            elif possible_code2 == 'j' and not rx86.fits_in_32bits(val2):
                                 val2 = self._addr_as_reg_offset(val2)
                                 invoke(self, possible_code1 + "m", val1, val2)
                             elif possible_code1 == 'm' and not rx86.fits_in_32bits(val1[1]):
@@ -378,6 +384,10 @@
                             _rx86_getattr(self, name + "_l")(val)
                             self.add_pending_relocation()
                         else:
+                            # xxx can we avoid "MOV r11, $val; JMP/CALL *r11"
+                            # in case it would fit a 32-bit displacement?
+                            # Hard, because we don't know yet where this insn
+                            # will end up...
                             assert self.WORD == 8
                             self._load_scratch(val)
                             _rx86_getattr(self, name + "_r")(X86_64_SCRATCH_REG.value)

diff --git a/pypy/translator/backendopt/test/test_tailrecursion.py b/pypy/translator/backendopt/test/test_tailrecursion.py
--- a/pypy/translator/backendopt/test/test_tailrecursion.py
+++ b/pypy/translator/backendopt/test/test_tailrecursion.py
@@ -1,4 +1,4 @@
-from pypy.objspace.flow.model import traverse, Block, Link, Variable, Constant
+from pypy.objspace.flow.model import Block, Link, Variable, Constant
 from pypy.translator.backendopt.tailrecursion import remove_tail_calls_to_self
 from pypy.translator.translator import TranslationContext, graphof
 from pypy.rpython.llinterp import LLInterpreter

diff --git a/pypy/module/cpyext/test/comparisons.c b/pypy/module/cpyext/test/comparisons.c
--- a/pypy/module/cpyext/test/comparisons.c
+++ b/pypy/module/cpyext/test/comparisons.c
@@ -69,12 +69,31 @@
 };
 
 
+static int cmp_compare(PyObject *self, PyObject *other) {
+    return -1;
+}
+
+PyTypeObject OldCmpType = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "comparisons.OldCmpType",                       /* tp_name */
+    sizeof(CmpObject),                              /* tp_basicsize */
+    0,                                              /* tp_itemsize */
+    0,                                              /* tp_dealloc */
+    0,                                              /* tp_print */
+    0,                                              /* tp_getattr */
+    0,                                              /* tp_setattr */
+    (cmpfunc)cmp_compare,                           /* tp_compare */
+};
+
+
 void initcomparisons(void)
 {
     PyObject *m, *d;
 
     if (PyType_Ready(&CmpType) < 0)
         return;
+    if (PyType_Ready(&OldCmpType) < 0)
+        return;
     m = Py_InitModule("comparisons", NULL);
     if (m == NULL)
         return;
@@ -83,4 +102,6 @@
         return;
     if (PyDict_SetItemString(d, "CmpType", (PyObject *)&CmpType) < 0)
         return;
+    if (PyDict_SetItemString(d, "OldCmpType", (PyObject *)&OldCmpType) < 0)
+        return;
 }

diff --git a/pypy/module/signal/test/test_signal.py b/pypy/module/signal/test/test_signal.py
--- a/pypy/module/signal/test/test_signal.py
+++ b/pypy/module/signal/test/test_signal.py
@@ -262,6 +262,8 @@
             signal(SIGALRM, SIG_DFL)
 
 class AppTestItimer:
+    spaceconfig = dict(usemodules=['signal'])
+
     def test_itimer_real(self):
         import signal
 

diff --git a/pypy/translator/c/src/ll_math.c b/pypy/translator/c/src/ll_math.c
--- a/pypy/translator/c/src/ll_math.c
+++ b/pypy/translator/c/src/ll_math.c
@@ -22,18 +22,6 @@
 #endif
 #define PyPy_NAN (HUGE_VAL * 0.)
 
-int
-_pypy_math_isinf(double x)
-{
-    return PyPy_IS_INFINITY(x);
-}
-
-int
-_pypy_math_isnan(double x)
-{
-    return PyPy_IS_NAN(x);
-}
-
 /* The following copyright notice applies to the original
    implementations of acosh, asinh and atanh. */
 


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
@@ -250,7 +250,6 @@
         # this is the ticker check generated in PyFrame.handle_operation_error
         exc_ticker_check = """
             ticker2 = getfield_raw(ticker_address, descr=<SignedFieldDescr pypysig_long_struct.c_value .*>)
-            setfield_gc(_, _, descr=<GcPtrFieldDescr pypy.interpreter.pyframe.PyFrame.inst_w_f_trace .*>)
             ticker_cond1 = int_lt(ticker2, 0)
             guard_false(ticker_cond1, descr=...)
         """
@@ -260,13 +259,13 @@
     @classmethod
     def is_const(cls, v1):
         return isinstance(v1, str) and v1.startswith('ConstClass(')
-    
+
     def match_var(self, v1, exp_v2):
         assert v1 != '_'
         if exp_v2 == '_':
             return True
         if self.is_const(v1) or self.is_const(exp_v2):
-            return v1 == exp_v2
+            return v1[:-1].startswith(exp_v2[:-1])
         if v1 not in self.alpha_map:
             self.alpha_map[v1] = exp_v2
         return self.alpha_map[v1] == exp_v2
@@ -285,9 +284,9 @@
         self.match_var(op.res, exp_res)
         self._assert(len(op.args) == len(exp_args), "wrong number of arguments")
         for arg, exp_arg in zip(op.args, exp_args):
-            self._assert(self.match_var(arg, exp_arg), "variable mismatch")
+            self._assert(self.match_var(arg, exp_arg), "variable mismatch: %r instead of %r" % (arg, exp_arg))
         self.match_descr(op.descr, exp_descr)
-        
+
 
     def _next_op(self, iter_ops, assert_raises=False):
         try:

diff --git a/pypy/module/thread/ll_thread.py b/pypy/module/thread/ll_thread.py
--- a/pypy/module/thread/ll_thread.py
+++ b/pypy/module/thread/ll_thread.py
@@ -1,10 +1,10 @@
 
-from pypy.rpython.lltypesystem import rffi
-from pypy.rpython.lltypesystem import lltype, llmemory
+from pypy.rpython.lltypesystem import rffi, lltype, llmemory
 from pypy.rpython.tool import rffi_platform as platform
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
 import py, os
 from pypy.rpython.extregistry import ExtRegistryEntry
+from pypy.rlib import jit
 from pypy.rlib.debug import ll_assert
 from pypy.rlib.objectmodel import we_are_translated
 from pypy.rpython.lltypesystem.lloperation import llop
@@ -79,6 +79,7 @@
 
 # wrappers...
 
+ at jit.loop_invariant
 def get_ident():
     return rffi.cast(lltype.Signed, c_thread_get_ident())
 
@@ -113,6 +114,12 @@
     def __del__(self):
         free_ll_lock(self._lock)
 
+    def __enter__(self):
+        self.acquire(True)
+        
+    def __exit__(self, *args):
+        self.release()
+
 # ____________________________________________________________
 #
 # Stack size

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
@@ -1,5 +1,5 @@
 
-from pypy.jit.metainterp.history import Const, Box
+from pypy.jit.metainterp.history import Const, Box, REF
 from pypy.rlib.objectmodel import we_are_translated
 
 class TempBox(Box):
@@ -37,6 +37,11 @@
         self.frame_depth += size
         return newloc
 
+    def reserve_location_in_frame(self, size):
+        frame_depth = self.frame_depth
+        self.frame_depth += size
+        return frame_depth
+
     # abstract methods that need to be overwritten for specific assemblers
     @staticmethod
     def frame_pos(loc, type):
@@ -313,11 +318,12 @@
             self.assembler.regalloc_mov(reg, to)
         # otherwise it's clean
 
-    def before_call(self, force_store=[], save_all_regs=False):
+    def before_call(self, force_store=[], save_all_regs=0):
         """ Spill registers before a call, as described by
         'self.save_around_call_regs'.  Registers are not spilled if
         they don't survive past the current operation, unless they
-        are listed in 'force_store'.
+        are listed in 'force_store'.  'save_all_regs' can be 0 (default),
+        1 (save all), or 2 (save default+PTRs).
         """
         for v, reg in self.reg_bindings.items():
             if v not in force_store and self.longevity[v][1] <= self.position:
@@ -325,9 +331,11 @@
                 del self.reg_bindings[v]
                 self.free_regs.append(reg)
                 continue
-            if not save_all_regs and reg not in self.save_around_call_regs:
-                # we don't have to
-                continue
+            if save_all_regs != 1 and reg not in self.save_around_call_regs:
+                if save_all_regs == 0:
+                    continue    # we don't have to
+                if v.type != REF:
+                    continue    # only save GC pointers
             self._sync_var(v)
             del self.reg_bindings[v]
             self.free_regs.append(reg)

diff --git a/pypy/module/pypyjit/test/test_pypy_c.py b/pypy/module/pypyjit/test/test_pypy_c.py
--- a/pypy/module/pypyjit/test/test_pypy_c.py
+++ b/pypy/module/pypyjit/test/test_pypy_c.py
@@ -3,6 +3,7 @@
 import py
 from py.test import skip
 import sys, os, re
+import subprocess
 
 class BytecodeTrace(list):
     def get_opnames(self, prefix=""):
@@ -118,13 +119,12 @@
         print >> f, "print 'OK :-)'"
         f.close()
 
-        if sys.platform.startswith('win'):
-            py.test.skip("XXX this is not Windows-friendly")
         print logfilepath
-        child_stdout = os.popen('PYPYLOG=":%s" "%s" "%s"' % (
-            logfilepath, self.pypy_c, filepath), 'r')
-        result = child_stdout.read()
-        child_stdout.close()
+        env = os.environ.copy()
+        env['PYPYLOG'] = ":%s" % (logfilepath,)
+        p = subprocess.Popen([self.pypy_c, str(filepath)],
+                             env=env, stdout=subprocess.PIPE)
+        result, _ = p.communicate()
         assert result
         if result.strip().startswith('SKIP:'):
             py.test.skip(result.strip())
@@ -1454,6 +1454,8 @@
                 res1 += dd(a, b, a1, b1)
                 res2 += dd(a, b, a2, b2)
                 res3 += dd(a, b, a3, b3)
+        # The purpose of this test is to check that we get
+        # the correct results, not really to count operations.
         self.run_source('''
         def main(a, b):
             i = sa = 0
@@ -1461,11 +1463,10 @@
 %s                
                 i += 1
             return sa
-        ''' % code, 179, ([a1, b1], 2000 * res1),
-                         ([a2, b2], 2000 * res2),
-                         ([a3, b3], 2000 * res3),
-                         count_debug_merge_point=False)
-        
+        ''' % code, sys.maxint, ([a1, b1], 2000 * res1),
+                                ([a2, b2], 2000 * res2),
+                                ([a3, b3], 2000 * res3))
+
     def test_mod(self):
         avalues = ('a', 'b', 7, -42, 8)
         bvalues = ['b'] + range(-10, 0) + range(1,10)
@@ -1486,6 +1487,8 @@
                 res1 += dd(a, b, a1, b1)
                 res2 += dd(a, b, a2, b2)
                 res3 += dd(a, b, a3, b3)
+        # The purpose of this test is to check that we get
+        # the correct results, not really to count operations.
         self.run_source('''
         def main(a, b):
             i = sa = 0
@@ -1495,11 +1498,10 @@
 %s
                 i += 1
             return sa
-        ''' % code, 450, ([a1, b1], 2000 * res1),
-                         ([a2, b2], 2000 * res2),
-                         ([a3, b3], 2000 * res3),
-                         count_debug_merge_point=False)
-        
+        ''' % code, sys.maxint, ([a1, b1], 2000 * res1),
+                                ([a2, b2], 2000 * res2),
+                                ([a3, b3], 2000 * res3))
+
     def test_dont_trace_every_iteration(self):
         self.run_source('''
         def main(a, b):

diff --git a/pypy/jit/backend/llsupport/test/test_descr.py b/pypy/jit/backend/llsupport/test/test_descr.py
--- a/pypy/jit/backend/llsupport/test/test_descr.py
+++ b/pypy/jit/backend/llsupport/test/test_descr.py
@@ -18,12 +18,33 @@
     descr_t = get_size_descr(c0, T)
     assert descr_s.size == symbolic.get_size(S, False)
     assert descr_t.size == symbolic.get_size(T, False)
+    assert descr_s.count_fields_if_immutable() == -1
+    assert descr_t.count_fields_if_immutable() == -1
     assert descr_s == get_size_descr(c0, S)
     assert descr_s != get_size_descr(c1, S)
     #
     descr_s = get_size_descr(c1, S)
     assert isinstance(descr_s.size, Symbolic)
+    assert descr_s.count_fields_if_immutable() == -1
 
+def test_get_size_descr_immut():
+    S = lltype.GcStruct('S', hints={'immutable': True})
+    T = lltype.GcStruct('T', ('parent', S),
+                        ('x', lltype.Char),
+                        hints={'immutable': True})
+    U = lltype.GcStruct('U', ('parent', T),
+                        ('u', lltype.Ptr(T)),
+                        ('v', lltype.Signed),
+                        hints={'immutable': True})
+    V = lltype.GcStruct('V', ('parent', U),
+                        ('miss1', lltype.Void),
+                        ('miss2', lltype.Void),
+                        hints={'immutable': True})
+    for STRUCT, expected in [(S, 0), (T, 1), (U, 3), (V, 3)]:
+        for translated in [False, True]:
+            c0 = GcCache(translated)
+            descr_s = get_size_descr(c0, STRUCT)
+            assert descr_s.count_fields_if_immutable() == expected
 
 def test_get_field_descr():
     U = lltype.Struct('U')

diff --git a/pypy/rpython/test/test_rint.py b/pypy/rpython/test/test_rint.py
--- a/pypy/rpython/test/test_rint.py
+++ b/pypy/rpython/test/test_rint.py
@@ -4,7 +4,7 @@
 from pypy.annotation import model as annmodel
 from pypy.rpython.test import snippet
 from pypy.rlib.rarithmetic import r_int, r_uint, r_longlong, r_ulonglong
-from pypy.rlib.rarithmetic import ovfcheck, r_int64, intmask
+from pypy.rlib.rarithmetic import ovfcheck, r_int64, intmask, int_between
 from pypy.rlib import objectmodel
 from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin
 
@@ -215,6 +215,14 @@
             assert res == f(inttype(0))
             assert type(res) == inttype
 
+    def test_and_or(self):
+        inttypes = [int, r_uint, r_int64, r_ulonglong]
+        for inttype in inttypes:
+            def f(a, b, c):
+                return a&b|c
+            res = self.interpret(f, [inttype(0x1234), inttype(0x00FF), inttype(0x5600)])
+            assert res == f(0x1234, 0x00FF, 0x5600)
+
     def test_neg_abs_ovf(self):
         for op in (operator.neg, abs):
             def f(x):
@@ -266,6 +274,8 @@
                 x = inttype(random.randint(-100000, 100000))
                 y = inttype(random.randint(-100000, 100000))
                 if not y: continue
+                if (i & 31) == 0:
+                    x = (x//y) * y      # case where x is exactly divisible by y
                 res = self.interpret(d, [x, y])
                 assert res == d(x, y)
 
@@ -276,6 +286,8 @@
                 x = inttype(random.randint(-100000, 100000))
                 y = inttype(random.randint(-100000, 100000))
                 if not y: continue
+                if (i & 31) == 0:
+                    x = (x//y) * y      # case where x is exactly divisible by y
                 res = self.interpret(m, [x, y])
                 assert res == m(x, y)
 
@@ -384,6 +396,18 @@
         else:
             assert res == 123456789012345678
 
+    def test_int_between(self):
+        def fn(a, b, c):
+            return int_between(a, b, c)
+        assert self.interpret(fn, [1, 1, 3])
+        assert self.interpret(fn, [1, 2, 3])
+        assert not self.interpret(fn, [1, 0, 2])
+        assert not self.interpret(fn, [1, 5, 2])
+        assert not self.interpret(fn, [1, 2, 2])
+        assert not self.interpret(fn, [1, 1, 1])
+
+
+
 class TestLLtype(BaseTestRint, LLRtypeMixin):
     pass
 

diff --git a/pypy/translator/jvm/src/pypy/PyPy.java b/pypy/translator/jvm/src/pypy/PyPy.java
--- a/pypy/translator/jvm/src/pypy/PyPy.java
+++ b/pypy/translator/jvm/src/pypy/PyPy.java
@@ -38,6 +38,10 @@
     public final static int INT_MIN = Integer.MIN_VALUE;
     public final static double ULONG_MAX = 18446744073709551616.0;
 
+    public static boolean int_between(int a, int b, int c) {
+        return a <= b && b < c;
+    }
+
     /** 
      * Compares two unsigned integers (value1 and value2) and returns
      * a value greater than, equal to, or less than zero if value 1 is
@@ -163,6 +167,13 @@
             return ULONG_MAX + value;
         }
     }
+
+    public static long double_to_ulong(double value) {
+        if (value < 0)
+            return (long)(ULONG_MAX + value);
+        else
+            return (long)value;
+    }
     
     public static int double_to_uint(double value) {
         if (value <= Integer.MAX_VALUE)
@@ -746,11 +757,13 @@
         return str.substring(start, end);
     }
 
-    public static Object[] ll_split_chr(String str, char c) {
+    public static Object[] ll_split_chr(String str, char c, int max) {
         ArrayList list = new ArrayList();
         int lastidx = 0, idx = 0;
         while ((idx = str.indexOf(c, lastidx)) != -1)
         {
+            if (max >= 0 && list.size() >= max)
+                break;
             String sub = str.substring(lastidx, idx);
             list.add(sub);
             lastidx = idx+1;
@@ -759,6 +772,21 @@
         return list.toArray(new String[list.size()]);
     }
 
+    public static Object[] ll_rsplit_chr(String str, char c, int max) {
+        ArrayList list = new ArrayList();
+        int lastidx = str.length(), idx = 0;
+        while ((idx = str.lastIndexOf(c, lastidx - 1)) != -1)
+        {
+            if (max >= 0 && list.size() >= max)
+                break;
+            String sub = str.substring(idx + 1, lastidx);
+            list.add(0, sub);
+            lastidx = idx;
+        }
+        list.add(0, str.substring(0, lastidx));
+        return list.toArray(new String[list.size()]);
+    }
+
     public static String ll_substring(String str, int start, int cnt) {
         return str.substring(start,start+cnt);
     }
@@ -1158,6 +1186,18 @@
         return Math.tanh(x);
     }
 
+    public double ll_math_copysign(double x, double y) {
+        return Math.copySign(x, y);
+    }
+
+    public boolean ll_math_isnan(double x) {
+        return Double.isNaN(x);
+    }
+
+    public boolean ll_math_isinf(double x) {
+        return Double.isInfinite(x);
+    }
+
     private double check(double v) {
         if (Double.isNaN(v))
             interlink.throwValueError();
@@ -1170,9 +1210,42 @@
         return Character.toLowerCase(c);
     }
 
+    public int locale_tolower(int chr)
+    {
+        return Character.toLowerCase(chr);
+    }
+
+    public int locale_isupper(int chr)
+    {
+        return boolean2int(Character.isUpperCase(chr));
+    }
+
+    public int locale_islower(int chr)
+    {
+        return boolean2int(Character.isLowerCase(chr));
+    }
+
+    public int locale_isalpha(int chr)
+    {
+        return boolean2int(Character.isLetter(chr));
+    }
+
+    public int locale_isalnum(int chr)
+    {
+        return boolean2int(Character.isLetterOrDigit(chr));
+    }
+
+
     // ----------------------------------------------------------------------
     // Self Test
 
+    public static int boolean2int(boolean b)
+    {
+        if (b)
+            return 1;
+        return 0;
+    }
+
     public static int __counter = 0, __failures = 0;
     public static void ensure(boolean f) {
         if (f) {

diff --git a/pypy/jit/backend/x86/support.py b/pypy/jit/backend/x86/support.py
--- a/pypy/jit/backend/x86/support.py
+++ b/pypy/jit/backend/x86/support.py
@@ -38,11 +38,7 @@
 if sys.platform == 'win32':
     ensure_sse2_floats = lambda : None
 else:
-    _sse2_eci = ExternalCompilationInfo(
+    ensure_sse2_floats = rffi.llexternal_use_eci(ExternalCompilationInfo(
         compile_extra = ['-msse2', '-mfpmath=sse',
                          '-DPYPY_CPU_HAS_STANDARD_PRECISION'],
-        separate_module_sources = ['void PYPY_NO_OP(void) {}'],
-        )
-    ensure_sse2_floats = rffi.llexternal('PYPY_NO_OP', [], lltype.Void,
-                                         compilation_info=_sse2_eci,
-                                         sandboxsafe=True)
+        ))

diff --git a/pypy/objspace/std/test/test_listobject.py b/pypy/objspace/std/test/test_listobject.py
--- a/pypy/objspace/std/test/test_listobject.py
+++ b/pypy/objspace/std/test/test_listobject.py
@@ -347,8 +347,9 @@
         assert list('') == []
         assert list('abc') == ['a', 'b', 'c']
         assert list((1, 2)) == [1, 2]
-        l = []
+        l = [1]
         assert list(l) is not l
+        assert list(l) == l
         assert list(range(10)) == range(10)
 
     def test_explicit_new_init(self):

diff --git a/pypy/translator/jvm/test/test_builtin.py b/pypy/translator/jvm/test/test_builtin.py
--- a/pypy/translator/jvm/test/test_builtin.py
+++ b/pypy/translator/jvm/test/test_builtin.py
@@ -37,6 +37,15 @@
     def test_cast_primitive(self):
         py.test.skip('fixme!')
 
+    def test_os_fstat(self):
+        import os, stat
+        def fn():
+            fd = os.open(__file__, os.O_RDONLY, 0)
+            st = os.fstat(fd)
+            os.close(fd)
+            return st.st_mode
+        res = self.interpret(fn, [])
+        assert stat.S_ISREG(res)
 
 class TestJvmTime(JvmTest, BaseTestTime):
 

diff --git a/pypy/jit/codewriter/heaptracker.py b/pypy/jit/codewriter/heaptracker.py
--- a/pypy/jit/codewriter/heaptracker.py
+++ b/pypy/jit/codewriter/heaptracker.py
@@ -10,6 +10,30 @@
 def int2adr(int):
     return llmemory.cast_int_to_adr(int)
 
+def count_fields_if_immutable(STRUCT):
+    assert isinstance(STRUCT, lltype.GcStruct)
+    if STRUCT._hints.get('immutable', False):
+        try:
+            return _count_fields(STRUCT)
+        except ValueError:
+            pass
+    return -1
+
+def _count_fields(STRUCT):
+    if STRUCT == rclass.OBJECT:
+        return 0    # don't count 'typeptr'
+    result = 0
+    for fieldname, TYPE in STRUCT._flds.items():
+        if TYPE is lltype.Void:
+            pass       # ignore Voids
+        elif not isinstance(TYPE, lltype.ContainerType):
+            result += 1
+        elif isinstance(TYPE, lltype.GcStruct):
+            result += _count_fields(TYPE)
+        else:
+            raise ValueError(TYPE)
+    return result
+
 # ____________________________________________________________
 
 def has_gcstruct_a_vtable(GCSTRUCT):

diff --git a/pypy/objspace/flow/model.py b/pypy/objspace/flow/model.py
--- a/pypy/objspace/flow/model.py
+++ b/pypy/objspace/flow/model.py
@@ -379,27 +379,6 @@
     return result
 
 
-def traverse(visit, functiongraph):
-    block = functiongraph.startblock
-    visit(block)
-    seen = identity_dict()
-    seen[block] = True
-    stack = list(block.exits[::-1])
-    while stack:
-        link = stack.pop()
-        visit(link)
-        block = link.target
-        if block not in seen:
-            visit(block)
-            seen[block] = True
-            stack += block.exits[::-1]
-
-
-def flatten(funcgraph):
-    l = []
-    traverse(l.append, funcgraph)
-    return l
-
 def flattenobj(*args):
     for arg in args:
         try:
@@ -497,6 +476,19 @@
             assert block.operations == ()
             assert block.exits == ()
 
+        def definevar(v, only_in_link=None):
+            assert isinstance(v, Variable)
+            assert v not in vars, "duplicate variable %r" % (v,)
+            assert v not in vars_previous_blocks, (
+                "variable %r used in more than one block" % (v,))
+            vars[v] = only_in_link
+
+        def usevar(v, in_link=None):
+            assert v in vars
+            if in_link is not None:
+                assert vars[v] is None or vars[v] is in_link
+
+
         for block in graph.iterblocks():
             assert bool(block.isstartblock) == (block is graph.startblock)
             assert type(block.exits) is tuple, (
@@ -506,18 +498,6 @@
                 assert block in exitblocks
             vars = {}
 
-            def definevar(v, only_in_link=None):
-                assert isinstance(v, Variable)
-                assert v not in vars, "duplicate variable %r" % (v,)
-                assert v not in vars_previous_blocks, (
-                    "variable %r used in more than one block" % (v,))
-                vars[v] = only_in_link
-
-            def usevar(v, in_link=None):
-                assert v in vars
-                if in_link is not None:
-                    assert vars[v] is None or vars[v] is in_link
-
             for v in block.inputargs:
                 definevar(v)
 

diff --git a/.hgignore b/.hgignore
--- a/.hgignore
+++ b/.hgignore
@@ -17,7 +17,6 @@
 ^pypy/doc/.+\.html$
 ^pypy/doc/basicblock\.asc$
 ^pypy/doc/.+\.svninfo$
-^pypy/translator/c/src/dtoa.o$
 ^pypy/translator/c/src/libffi_msvc/.+\.obj$
 ^pypy/translator/c/src/libffi_msvc/.+\.dll$
 ^pypy/translator/c/src/libffi_msvc/.+\.lib$

diff --git a/pypy/module/cpyext/test/test_pyfile.py b/pypy/module/cpyext/test/test_pyfile.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/test/test_pyfile.py
@@ -0,0 +1,72 @@
+from pypy.module.cpyext.api import fopen, fclose, fwrite
+from pypy.module.cpyext.test.test_api import BaseApiTest
+from pypy.rpython.lltypesystem import rffi, lltype
+from pypy.tool.udir import udir
+import pytest
+
+class TestFile(BaseApiTest):
+
+    def test_file_fromstring(self, space, api):
+        filename = rffi.str2charp(str(udir / "_test_file"))
+        mode = rffi.str2charp("wb")
+        w_file = api.PyFile_FromString(filename, mode)
+        rffi.free_charp(filename)
+        rffi.free_charp(mode)
+
+        assert api.PyFile_Check(w_file)
+        assert api.PyFile_CheckExact(w_file)
+        assert not api.PyFile_Check(space.wrap("text"))
+
+        space.call_method(w_file, "write", space.wrap("text"))
+        space.call_method(w_file, "close")
+        assert (udir / "_test_file").read() == "text"
+
+    def test_file_getline(self, space, api):
+        filename = rffi.str2charp(str(udir / "_test_file"))
+
+        mode = rffi.str2charp("w")
+        w_file = api.PyFile_FromString(filename, mode)
+        space.call_method(w_file, "write",
+                          space.wrap("line1\nline2\nline3\nline4"))
+        space.call_method(w_file, "close")
+
+        rffi.free_charp(mode)
+        mode = rffi.str2charp("r")
+        w_file = api.PyFile_FromString(filename, mode)
+        rffi.free_charp(filename)
+        rffi.free_charp(mode)
+
+        w_line = api.PyFile_GetLine(w_file, 0)
+        assert space.str_w(w_line) == "line1\n"
+
+        w_line = api.PyFile_GetLine(w_file, 4)
+        assert space.str_w(w_line) == "line"
+
+        w_line = api.PyFile_GetLine(w_file, 0)
+        assert space.str_w(w_line) == "2\n"
+
+        # XXX We ought to raise an EOFError here, but don't
+        w_line = api.PyFile_GetLine(w_file, -1)
+        # assert api.PyErr_Occurred() is space.w_EOFError
+        assert space.str_w(w_line) == "line3\n"
+
+        space.call_method(w_file, "close")
+
+    @pytest.mark.xfail
+    def test_file_fromfile(self, space, api):
+        api.PyFile_Fromfile()
+
+    @pytest.mark.xfail
+    def test_file_setbufsize(self, space, api):
+        api.PyFile_SetBufSize()
+
+    def test_file_writestring(self, space, api, capfd):
+        s = rffi.str2charp("test\n")
+        try:
+            api.PyFile_WriteString(s, space.sys.get("stdout"))
+        finally:
+            rffi.free_charp(s)
+        out, err = capfd.readouterr()
+        out = out.replace('\r\n', '\n')
+        assert out == "test\n"
+

diff --git a/lib_pypy/pyrepl/completer.py b/lib_pypy/pyrepl/completer.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/completer.py
@@ -0,0 +1,87 @@
+#   Copyright 2000-2004 Michael Hudson-Doyle <micahel at gmail.com>
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+import __builtin__
+
+class Completer:
+    def __init__(self, ns):
+        self.ns = ns
+
+    def complete(self, text):
+        if "." in text:
+            return self.attr_matches(text)
+        else:
+            return self.global_matches(text)
+
+    def global_matches(self, text):
+        """Compute matches when text is a simple name.
+
+        Return a list of all keywords, built-in functions and names
+        currently defines in __main__ that match.
+
+        """
+        import keyword
+        matches = []
+        n = len(text)
+        for list in [keyword.kwlist,
+                     __builtin__.__dict__.keys(),
+                     self.ns.keys()]:
+            for word in list:
+                if word[:n] == text and word != "__builtins__":
+                    matches.append(word)
+        return matches
+
+    def attr_matches(self, text):
+        """Compute matches when text contains a dot.
+
+        Assuming the text is of the form NAME.NAME....[NAME], and is
+        evaluatable in the globals of __main__, it will be evaluated
+        and its attributes (as revealed by dir()) are used as possible
+        completions.  (For class instances, class members are are also
+        considered.)
+
+        WARNING: this can still invoke arbitrary C code, if an object
+        with a __getattr__ hook is evaluated.
+
+        """
+        import re
+        m = re.match(r"(\w+(\.\w+)*)\.(\w*)", text)
+        if not m:
+            return []
+        expr, attr = m.group(1, 3)
+        object = eval(expr, self.ns)
+        words = dir(object)
+        if hasattr(object, '__class__'):
+            words.append('__class__')
+            words = words + get_class_members(object.__class__)
+        matches = []
+        n = len(attr)
+        for word in words:
+            if word[:n] == attr and word != "__builtins__":
+                matches.append("%s.%s" % (expr, word))
+        return matches
+
+def get_class_members(klass):
+    ret = dir(klass)
+    if hasattr(klass, '__bases__'):
+        for base in klass.__bases__:
+            ret = ret + get_class_members(base)
+    return ret
+
+

diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py
--- a/pypy/config/pypyoption.py
+++ b/pypy/config/pypyoption.py
@@ -13,7 +13,7 @@
                and not p.basename.startswith('test')]
 
 essential_modules = dict.fromkeys(
-    ["exceptions", "_file", "sys", "__builtin__", "posix", "signal"]
+    ["exceptions", "_file", "sys", "__builtin__", "posix"]
 )
 
 default_modules = essential_modules.copy()
@@ -40,8 +40,9 @@
 translation_modules.update(dict.fromkeys(
     ["fcntl", "rctime", "select", "signal", "_rawffi", "zlib",
      "struct", "md5", "cStringIO", "array", "_ffi",
-     # the following are needed for pyrepl (and hence for the interactive prompt/pdb)
-     "termios", "_minimal_curses", "fcntl", "signal",
+     # the following are needed for pyrepl (and hence for the
+     # interactive prompt/pdb)
+     "termios", "_minimal_curses",
      ]))
 
 working_oo_modules = default_modules.copy()
@@ -162,6 +163,11 @@
                cmdline="--allworkingmodules",
                negation=True),
 
+    StrOption("extmodules",
+              "Comma-separated list of third-party builtin modules",
+              cmdline="--ext",
+              default=None),
+
     BoolOption("translationmodules",
           "use only those modules that are needed to run translate.py on pypy",
                default=False,
@@ -355,8 +361,8 @@
         config.objspace.std.suggest(optimized_list_getitem=True)
         config.objspace.std.suggest(getattributeshortcut=True)
         config.objspace.std.suggest(newshortcut=True)
-        if not IS_64_BITS:
-            config.objspace.std.suggest(withsmalllong=True)
+        #if not IS_64_BITS:
+        #    config.objspace.std.suggest(withsmalllong=True)
 
     # extra costly optimizations only go in level 3
     if level == '3':

diff --git a/pypy/translator/stackless/transform.py b/pypy/translator/stackless/transform.py
--- a/pypy/translator/stackless/transform.py
+++ b/pypy/translator/stackless/transform.py
@@ -2,7 +2,7 @@
 from pypy.rpython.lltypesystem.lloperation import LL_OPERATIONS
 from pypy.rlib import rarithmetic
 from pypy.rpython import rclass, rmodel
-from pypy.translator.backendopt import support
+from pypy.translator.unsimplify import split_block
 from pypy.objspace.flow import model
 from pypy.translator import unsimplify, simplify
 from pypy.translator.unsimplify import varoftype
@@ -598,7 +598,7 @@
             link = block.exits[0]
             nextblock = None
         else:
-            link = support.split_block_with_keepalive(block, i+1)
+            link = split_block(None, block, i+1)
             i = 0
             nextblock = link.target
 
@@ -765,7 +765,7 @@
             exitcases = dict.fromkeys([l.exitcase for l in block.exits])
             nextblock = None
         else:
-            link = support.split_block_with_keepalive(block, i+1)
+            link = split_block(None, block, i+1)
             nextblock = link.target
             block.exitswitch = model.c_last_exception
             link.llexitcase = None

diff --git a/pypy/module/posix/__init__.py b/pypy/module/posix/__init__.py
--- a/pypy/module/posix/__init__.py
+++ b/pypy/module/posix/__init__.py
@@ -5,6 +5,25 @@
 import os, sys
 exec 'import %s as posix' % os.name
 
+# this is the list of function which is *not* present in the posix module of
+# IronPython 2.6, and that we want to ignore for now
+lltype_only_defs = [
+    'chown', 'chroot', 'closerange', 'confstr', 'confstr_names', 'ctermid', 'dup',
+    'dup2', 'execv', 'execve', 'fchdir', 'fchmod', 'fchown', 'fdatasync', 'fork',
+    'forkpty', 'fpathconf', 'fstatvfs', 'fsync', 'ftruncate', 'getegid', 'geteuid',
+    'getgid', 'getgroups', 'getloadavg', 'getlogin', 'getpgid', 'getpgrp', 'getppid',
+    'getsid', 'getuid', 'kill', 'killpg', 'lchown', 'link', 'lseek', 'major',
+    'makedev', 'minor', 'mkfifo', 'mknod', 'nice', 'openpty', 'pathconf', 'pathconf_names',
+    'pipe', 'readlink', 'setegid', 'seteuid', 'setgid', 'setgroups', 'setpgid', 'setpgrp',
+    'setregid', 'setreuid', 'setsid', 'setuid', 'stat_float_times', 'statvfs',
+    'statvfs_result', 'symlink', 'sysconf', 'sysconf_names', 'tcgetpgrp', 'tcsetpgrp',
+    'ttyname', 'uname', 'wait', 'wait3', 'wait4'
+    ]
+
+# the Win32 urandom implementation isn't going to translate on JVM or CLI so
+# we have to remove it
+lltype_only_defs.append('urandom')
+
 class Module(MixedModule):
     """This module provides access to operating system functionality that is
 standardized by the C Standard and the POSIX standard (a thinly
@@ -31,6 +50,10 @@
 
     if hasattr(os, 'wait'):
         appleveldefs['wait'] = 'app_posix.wait'
+    if hasattr(os, 'wait3'):
+        appleveldefs['wait3'] = 'app_posix.wait3'
+    if hasattr(os, 'wait4'):
+        appleveldefs['wait4'] = 'app_posix.wait4'
         
     interpleveldefs = {
     'open'      : 'interp_posix.open',
@@ -156,11 +179,12 @@
             interpleveldefs[name] = 'interp_posix.' + name
 
     def __init__(self, space, w_name):
+        # if it's an ootype translation, remove all the defs that are lltype
+        # only
         backend = space.config.translation.backend
-        # the Win32 urandom implementation isn't going to translate on JVM or CLI
-        # so we have to remove it
-        if 'urandom' in self.interpleveldefs and (backend == 'cli' or backend == 'jvm'):
-            del self.interpleveldefs['urandom']
+        if backend == 'cli' or backend == 'jvm':
+            for name in lltype_only_defs:
+                self.interpleveldefs.pop(name, None)
         MixedModule.__init__(self, space, w_name)
 
     def startup(self, space):

diff --git a/lib_pypy/pyrepl/input.py b/lib_pypy/pyrepl/input.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/input.py
@@ -0,0 +1,97 @@
+#   Copyright 2000-2004 Michael Hudson-Doyle <micahel at gmail.com>
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+# (naming modules after builtin functions is not such a hot idea...)
+
+# an KeyTrans instance translates Event objects into Command objects
+
+# hmm, at what level do we want [C-i] and [tab] to be equivalent?
+# [meta-a] and [esc a]?  obviously, these are going to be equivalent
+# for the UnixConsole, but should they be for PygameConsole?
+
+# it would in any situation seem to be a bad idea to bind, say, [tab]
+# and [C-i] to *different* things... but should binding one bind the
+# other?
+
+# executive, temporary decision: [tab] and [C-i] are distinct, but
+# [meta-key] is identified with [esc key].  We demand that any console
+# class does quite a lot towards emulating a unix terminal.
+
+from pyrepl import unicodedata_
+
+class InputTranslator(object):
+    def push(self, evt):
+        pass
+    def get(self):
+        pass
+    def empty(self):
+        pass
+
+class KeymapTranslator(InputTranslator):
+    def __init__(self, keymap, verbose=0,
+                 invalid_cls=None, character_cls=None):
+        self.verbose = verbose
+        from pyrepl.keymap import compile_keymap, parse_keys
+        self.keymap = keymap
+        self.invalid_cls = invalid_cls
+        self.character_cls = character_cls
+        d = {}
+        for keyspec, command in keymap:
+            keyseq = tuple(parse_keys(keyspec))
+            d[keyseq] = command
+        if self.verbose:
+            print d
+        self.k = self.ck = compile_keymap(d, ())
+        self.results = []
+        self.stack = []
+    def push(self, evt):
+        if self.verbose:
+            print "pushed", evt.data,
+        key = evt.data
+        d = self.k.get(key)
+        if isinstance(d, dict):
+            if self.verbose:
+                print "transition"
+            self.stack.append(key)
+            self.k = d
+        else:
+            if d is None:
+                if self.verbose:
+                    print "invalid"
+                if self.stack or len(key) > 1 or unicodedata_.category(key) == 'C':
+                    self.results.append(
+                        (self.invalid_cls, self.stack + [key]))
+                else:
+                    # small optimization:
+                    self.k[key] = self.character_cls
+                    self.results.append(
+                        (self.character_cls, [key]))
+            else:
+                if self.verbose:
+                    print "matched", d
+                self.results.append((d, self.stack + [key]))
+            self.stack = []
+            self.k = self.ck
+    def get(self):
+        if self.results:
+            return self.results.pop(0)
+        else:
+            return None
+    def empty(self):
+        return not self.results

diff --git a/pypy/objspace/std/mapdict.py b/pypy/objspace/std/mapdict.py
--- a/pypy/objspace/std/mapdict.py
+++ b/pypy/objspace/std/mapdict.py
@@ -604,6 +604,18 @@
         else:
             self._as_rdict().impl_fallback_setitem(w_key, w_value)
 
+    def impl_setdefault(self,  w_key, w_default):
+        space = self.space
+        if space.is_w(space.type(w_key), space.w_str):
+            key = space.str_w(w_key)
+            w_result = self.impl_getitem_str(key)
+            if w_result is not None:
+                return w_result
+            self.impl_setitem_str(key, w_default)
+            return w_default
+        else:
+            return self._as_rdict().impl_fallback_setdefault(w_key, w_default)
+
     def impl_delitem(self, w_key):
         space = self.space
         w_key_type = space.type(w_key)

diff --git a/pypy/rlib/test/test_rcoroutine.py b/pypy/rlib/test/test_rcoroutine.py
--- a/pypy/rlib/test/test_rcoroutine.py
+++ b/pypy/rlib/test/test_rcoroutine.py
@@ -1,13 +1,16 @@
 """
 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']

diff --git a/pypy/translator/goal/query.py b/pypy/translator/goal/query.py
--- a/pypy/translator/goal/query.py
+++ b/pypy/translator/goal/query.py
@@ -30,15 +30,13 @@
 def polluted_qgen(translator):
     """list functions with still real SomeObject variables"""
     annotator = translator.annotator
-    def visit(block):
-        if isinstance(block, flowmodel.Block):
-            for v in block.getvariables():
-                s = annotator.binding(v, None)
-                if s and s.__class__ == annmodel.SomeObject and s.knowntype != type:
-                    raise Found
     for g in translator.graphs:
         try:
-            flowmodel.traverse(visit, g)
+            for block in g.iterblocks():
+                for v in block.getvariables():
+                    s = annotator.binding(v, None)
+                    if s and s.__class__ == annmodel.SomeObject and s.knowntype != type:
+                        raise Found
         except Found:
             line = "%s: %s" % (g, graph_sig(translator, g))
             yield line

diff --git a/pypy/tool/jitlogparser/storage.py b/pypy/tool/jitlogparser/storage.py
--- a/pypy/tool/jitlogparser/storage.py
+++ b/pypy/tool/jitlogparser/storage.py
@@ -30,18 +30,18 @@
             self.codes[fname] = res
             return res
 
-    def disassemble_code(self, fname, startlineno):
+    def disassemble_code(self, fname, startlineno, name):
         try:
             if py.path.local(fname).check(file=False):
                 return None # cannot find source file
         except py.error.EACCES:
             return None # cannot open the file
-        key = (fname, startlineno)
+        key = (fname, startlineno, name)
         try:
             return self.disassembled_codes[key]
         except KeyError:
             codeobjs = self.load_code(fname)
-            if startlineno not in codeobjs:
+            if (startlineno, name) not in codeobjs:
                 # cannot find the code obj at this line: this can happen for
                 # various reasons, e.g. because the .py files changed since
                 # the log was produced, or because the co_firstlineno
@@ -49,7 +49,7 @@
                 # produced by gateway.applevel(), such as the ones found in
                 # nanos.py)
                 return None
-            code = codeobjs[startlineno]
+            code = codeobjs[(startlineno, name)]
             res = dis(code)
             self.disassembled_codes[key] = res
             return res

diff --git a/pypy/module/cpyext/test/test_sysmodule.py b/pypy/module/cpyext/test/test_sysmodule.py
--- a/pypy/module/cpyext/test/test_sysmodule.py
+++ b/pypy/module/cpyext/test/test_sysmodule.py
@@ -14,6 +14,21 @@
         assert module.get("excepthook")
         assert not module.get("spam_spam_spam")
 
+    def test_writestdout(self):
+        module = self.import_extension('foo', [
+            ("writestdout", "METH_NOARGS",
+             """
+                 PySys_WriteStdout("format: %d\\n", 42);
+                 Py_RETURN_NONE;
+             """)])
+        import sys, StringIO
+        sys.stdout = StringIO.StringIO()
+        try:
+            module.writestdout()
+            assert sys.stdout.getvalue() == "format: 42\n"
+        finally:
+            sys.stdout = sys.__stdout__
+
 class TestSysModule(BaseApiTest):
     def test_sysmodule(self, space, api):
         buf = rffi.str2charp("last_tb")

diff --git a/py/_io/terminalwriter.py b/py/_io/terminalwriter.py
--- a/py/_io/terminalwriter.py
+++ b/py/_io/terminalwriter.py
@@ -81,6 +81,9 @@
         oldcolors = GetConsoleInfo(handle).wAttributes
         attr |= (oldcolors & 0x0f0)
         SetConsoleTextAttribute(handle, attr)
+        while len(text) > 32768:
+            file.write(text[:32768])
+            text = text[32768:]
         file.write(text)
         SetConsoleTextAttribute(handle, oldcolors)
     else:

diff --git a/pypy/rpython/lltypesystem/rlist.py b/pypy/rpython/lltypesystem/rlist.py
--- a/pypy/rpython/lltypesystem/rlist.py
+++ b/pypy/rpython/lltypesystem/rlist.py
@@ -16,7 +16,6 @@
 from pypy.rlib.debug import ll_assert
 from pypy.rlib.rarithmetic import ovfcheck
 from pypy.rpython.lltypesystem import rffi
-from pypy.rlib.objectmodel import keepalive_until_here
 from pypy.rpython.lltypesystem.lloperation import llop
 from pypy.rlib import rgc
 

diff --git a/pypy/module/cpyext/include/pyerrors.h b/pypy/module/cpyext/include/pyerrors.h
--- a/pypy/module/cpyext/include/pyerrors.h
+++ b/pypy/module/cpyext/include/pyerrors.h
@@ -15,6 +15,20 @@
 PyObject *PyErr_NewExceptionWithDoc(char *name, char *doc, PyObject *base, PyObject *dict);
 PyObject *PyErr_Format(PyObject *exception, const char *format, ...);
 
+/* These APIs aren't really part of the error implementation, but
+   often needed to format error messages; the native C lib APIs are
+   not available on all platforms, which is why we provide emulations
+   for those platforms in Python/mysnprintf.c,
+   WARNING:  The return value of snprintf varies across platforms; do
+   not rely on any particular behavior; eventually the C99 defn may
+   be reliable.
+*/
+#if defined(MS_WIN32) && !defined(HAVE_SNPRINTF)
+# define HAVE_SNPRINTF
+# define snprintf _snprintf
+# define vsnprintf _vsnprintf
+#endif
+
 #ifdef __cplusplus
 }
 #endif

diff --git a/pypy/module/cpyext/test/test_stringobject.py b/pypy/module/cpyext/test/test_stringobject.py
--- a/pypy/module/cpyext/test/test_stringobject.py
+++ b/pypy/module/cpyext/test/test_stringobject.py
@@ -194,8 +194,8 @@
         c_buf = py_str.c_ob_type.c_tp_as_buffer
         assert c_buf
         py_obj = rffi.cast(PyObject, py_str)
-        assert c_buf.c_bf_getsegcount(py_obj, lltype.nullptr(rffi.INTP.TO)) == 1
-        ref = lltype.malloc(rffi.INTP.TO, 1, flavor='raw')
+        assert c_buf.c_bf_getsegcount(py_obj, lltype.nullptr(Py_ssize_tP.TO)) == 1
+        ref = lltype.malloc(Py_ssize_tP.TO, 1, flavor='raw')
         assert c_buf.c_bf_getsegcount(py_obj, ref) == 1
         assert ref[0] == 10
         lltype.free(ref, flavor='raw')

diff --git a/pypy/rlib/objectmodel.py b/pypy/rlib/objectmodel.py
--- a/pypy/rlib/objectmodel.py
+++ b/pypy/rlib/objectmodel.py
@@ -255,7 +255,7 @@
     x = ord(s[0]) << 7
     i = 0
     while i < length:
-        x = (1000003*x) ^ ord(s[i])
+        x = intmask((1000003*x) ^ ord(s[i]))
         i += 1
     x ^= length
     return intmask(x)

diff --git a/pypy/module/cpyext/include/sysmodule.h b/pypy/module/cpyext/include/sysmodule.h
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/include/sysmodule.h
@@ -0,0 +1,13 @@
+#ifndef Py_SYSMODULE_H
+#define Py_SYSMODULE_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+PyAPI_FUNC(void) PySys_WriteStdout(const char *format, ...);
+PyAPI_FUNC(void) PySys_WriteStderr(const char *format, ...);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_SYSMODULE_H */


diff --git a/pypy/translator/jvm/typesystem.py b/pypy/translator/jvm/typesystem.py
--- a/pypy/translator/jvm/typesystem.py
+++ b/pypy/translator/jvm/typesystem.py
@@ -181,6 +181,7 @@
 
 jIntegerClass = JvmClassType('java.lang.Integer')
 jLongClass = JvmClassType('java.lang.Long')
+jShortClass = JvmClassType('java.lang.Short')
 jDoubleClass = JvmClassType('java.lang.Double')
 jByteClass = JvmClassType('java.lang.Byte')
 jCharClass = JvmClassType('java.lang.Character')
@@ -239,6 +240,7 @@
 jDouble = JvmScalarType('D', jDoubleClass, 'doubleValue')
 jByte = JvmScalarType('B', jByteClass, 'byteValue')
 jChar = JvmScalarType('C', jCharClass, 'charValue')
+jShort = JvmScalarType('S', jShortClass, 'shortValue')
 
 class Generifier(object):
 
@@ -527,6 +529,7 @@
         if desc == 'C':    return self._o("i")   # Characters
         if desc == 'B':    return self._o("i")   # Bytes
         if desc == 'Z':    return self._o("i")   # Boolean
+        if desc == 'S':    return self._o("i")   # Short
 
         assert False, "Unknown argtype=%s" % repr(argtype)
         raise NotImplementedError
@@ -625,6 +628,7 @@
 NOP =       Opcode('nop')
 I2D =       Opcode('i2d')
 I2L =       Opcode('i2l')
+I2S =       Opcode('i2s')
 D2I=        Opcode('d2i')
 #D2L=        Opcode('d2l') #PAUL
 L2I =       Opcode('l2i')
@@ -891,6 +895,7 @@
 SYSTEMIDENTITYHASH =    Method.s(jSystem, 'identityHashCode', (jObject,), jInt)
 SYSTEMGC =              Method.s(jSystem, 'gc', (), jVoid)
 INTTOSTRINGI =          Method.s(jIntegerClass, 'toString', (jInt,), jString)
+SHORTTOSTRINGS =        Method.s(jShortClass, 'toString', (jShort,), jString)
 LONGTOSTRINGL =         Method.s(jLongClass, 'toString', (jLong,), jString)
 DOUBLETOSTRINGD =       Method.s(jDoubleClass, 'toString', (jDouble,), jString)
 CHARTOSTRINGC =         Method.s(jCharClass, 'toString', (jChar,), jString)
@@ -922,15 +927,19 @@
 CLASSISASSIGNABLEFROM = Method.v(jClass, 'isAssignableFrom', (jClass,), jBool)
 STRINGBUILDERAPPEND =   Method.v(jStringBuilder, 'append',
                                  (jString,), jStringBuilder)
+PYPYINTBETWEEN =        Method.s(jPyPy, 'int_between', (jInt,jInt,jInt), jBool)
 PYPYUINTCMP =           Method.s(jPyPy, 'uint_cmp', (jInt,jInt,), jInt)
 PYPYULONGCMP =          Method.s(jPyPy, 'ulong_cmp', (jLong,jLong), jInt)
 PYPYUINTMOD =           Method.v(jPyPy, 'uint_mod', (jInt, jInt), jInt)
 PYPYUINTMUL =           Method.v(jPyPy, 'uint_mul', (jInt, jInt), jInt)
 PYPYUINTDIV =           Method.v(jPyPy, 'uint_div', (jInt, jInt), jInt)
 PYPYULONGMOD =          Method.v(jPyPy, 'ulong_mod', (jLong, jLong), jLong)
+PYPYUINTTOLONG =        Method.s(jPyPy, 'uint_to_long', (jInt,), jLong)
 PYPYUINTTODOUBLE =      Method.s(jPyPy, 'uint_to_double', (jInt,), jDouble)
 PYPYDOUBLETOUINT =      Method.s(jPyPy, 'double_to_uint', (jDouble,), jInt)
 PYPYDOUBLETOLONG =      Method.v(jPyPy, 'double_to_long', (jDouble,), jLong) #PAUL
+PYPYDOUBLETOULONG =     Method.s(jPyPy, 'double_to_ulong', (jDouble,), jLong)
+PYPYULONGTODOUBLE =     Method.s(jPyPy, 'ulong_to_double', (jLong,), jDouble)
 PYPYLONGBITWISENEGATE = Method.v(jPyPy, 'long_bitwise_negate', (jLong,), jLong)
 PYPYSTRTOINT =          Method.v(jPyPy, 'str_to_int', (jString,), jInt)
 PYPYSTRTOUINT =         Method.v(jPyPy, 'str_to_uint', (jString,), jInt)

diff --git a/pypy/jit/metainterp/optimizeopt/__init__.py b/pypy/jit/metainterp/optimizeopt/__init__.py
--- a/pypy/jit/metainterp/optimizeopt/__init__.py
+++ b/pypy/jit/metainterp/optimizeopt/__init__.py
@@ -27,7 +27,7 @@
 
 def optimize_loop_1(metainterp_sd, loop, enable_opts,
                     inline_short_preamble=True, retraced=False):
-    """Optimize loop.operations to remove internal overheadish operations. 
+    """Optimize loop.operations to remove internal overheadish operations.
     """
     optimizations = []
     unroll = 'unroll' in enable_opts
@@ -43,7 +43,7 @@
 
     if 'rewrite' not in enable_opts or 'virtualize' not in enable_opts:
         optimizations.append(OptSimplify())
-    
+
     if inline_short_preamble:
         optimizations = [OptInlineShortPreamble(retraced)] + optimizations
 

diff --git a/pypy/translator/backendopt/test/test_removenoops.py b/pypy/translator/backendopt/test/test_removenoops.py
--- a/pypy/translator/backendopt/test/test_removenoops.py
+++ b/pypy/translator/backendopt/test/test_removenoops.py
@@ -1,12 +1,12 @@
 from pypy.translator.backendopt.removenoops import remove_same_as, \
-        remove_unaryops, remove_duplicate_casts, remove_superfluous_keep_alive
+        remove_unaryops, remove_duplicate_casts
 from pypy.translator.backendopt.inline import simple_inline_function
 from pypy.translator.translator import TranslationContext, graphof
 from pypy.rpython.memory.gctransform.test.test_transform import getops
 from pypy.translator.test.snippet import simple_method
 from pypy.translator.backendopt.all import backend_optimizations
 from pypy.translator.backendopt.all import INLINE_THRESHOLD_FOR_TEST
-from pypy.objspace.flow.model import checkgraph, flatten, Block
+from pypy.objspace.flow.model import checkgraph, Block
 from pypy.rpython.lltypesystem import lltype
 from pypy.rpython.lltypesystem.lloperation import llop
 from pypy.rpython.llinterp import LLInterpreter
@@ -115,20 +115,6 @@
     result = interp.eval_graph(f_graph, [-2])
     assert result == -1
 
-def test_remove_keepalive():
-    S = lltype.GcStruct("s", ("f", lltype.Signed))
-    def f():
-        s1 = lltype.malloc(S)
-        llop.keepalive(lltype.Void, s1)
-        s2 = lltype.malloc(S)
-        llop.keepalive(lltype.Void, s1)
-        llop.keepalive(lltype.Void, s2)
-        return lltype.cast_ptr_to_int(s1) + lltype.cast_ptr_to_int(s2)
-    graph, t = get_graph(f, [])
-    remove_superfluous_keep_alive(graph)
-    ops = getops(graph)
-    assert len(ops['keepalive']) == 2
-
 def test_remove_duplicate_casts():
     class A(object):
         def __init__(self, x, y):


diff --git a/pypy/translator/cli/metavm.py b/pypy/translator/cli/metavm.py
--- a/pypy/translator/cli/metavm.py
+++ b/pypy/translator/cli/metavm.py
@@ -270,23 +270,38 @@
 
         generator.ilasm.call('void [pypylib]pypy.runtime.DebugPrint::DEBUG_PRINT(%s)' % signature)
 
+INT_SIZE = {
+    ootype.Bool: 1,
+    ootype.Char: 2,
+    ootype.UniChar: 2,
+    rffi.SHORT: 2,
+    ootype.Signed: 4,
+    ootype.Unsigned: 4,
+    ootype.SignedLongLong: 8,
+    ootype.UnsignedLongLong: 8
+    }
 
-OOTYPE_TO_MNEMONIC = {
-    ootype.Bool: 'i1', 
-    ootype.Char: 'i2',
-    ootype.UniChar: 'i2',
-    rffi.SHORT: 'i2',
-    ootype.Signed: 'i4',
-    ootype.SignedLongLong: 'i8',
-    ootype.Unsigned: 'u4',
-    ootype.UnsignedLongLong: 'u8',
-    ootype.Float: 'r8',
-    }
+UNSIGNED_TYPES = [ootype.Char, ootype.UniChar, rffi.USHORT,
+                  ootype.Unsigned, ootype.UnsignedLongLong]
+
+def ootype_to_mnemonic(FROM, TO, default=None):
+    if TO == ootype.Float:
+        return 'r8'
+    #
+    try:
+        size = str(INT_SIZE[TO])
+    except KeyError:
+        return default
+    if FROM in UNSIGNED_TYPES:
+        return 'u' + size
+    else:
+        return 'i' + size
 
 class _CastPrimitive(MicroInstruction):
     def render(self, generator, op):
+        FROM = op.args[0].concretetype
         TO = op.result.concretetype
-        mnemonic = OOTYPE_TO_MNEMONIC[TO]
+        mnemonic = ootype_to_mnemonic(FROM, TO)
         generator.ilasm.opcode('conv.%s' % mnemonic)
 
 Call = _Call()

diff --git a/pypy/module/cpyext/include/frameobject.h b/pypy/module/cpyext/include/frameobject.h
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/include/frameobject.h
@@ -0,0 +1,17 @@
+#ifndef Py_FRAMEOBJECT_H
+#define Py_FRAMEOBJECT_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+    PyObject_HEAD
+    PyCodeObject *f_code;
+    PyObject *f_globals;
+    int f_lineno;
+} PyFrameObject;
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_FRAMEOBJECT_H */

diff --git a/pypy/doc/config/generate.py b/pypy/doc/config/generate.py
--- a/pypy/doc/config/generate.py
+++ b/pypy/doc/config/generate.py
@@ -8,8 +8,8 @@
 for descr in all_optiondescrs:
     prefix = descr._name
     c = config.Config(descr)
-    thisdir.join(prefix + ".txt").ensure()
+    thisdir.join(prefix + ".rst").ensure()
     for p in c.getpaths(include_groups=True):
-        basename = prefix + "." + p + ".txt"
+        basename = prefix + "." + p + ".rst"
         f = thisdir.join(basename)
         f.ensure()

diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py
--- a/pypy/interpreter/pyopcode.py
+++ b/pypy/interpreter/pyopcode.py
@@ -138,11 +138,13 @@
                 # raised after the exception handler block was popped.
                 try:
                     trace = self.w_f_trace
-                    self.w_f_trace = None
+                    if trace is not None:
+                        self.w_f_trace = None
                     try:
                         ec.bytecode_trace_after_exception(self)
                     finally:
-                        self.w_f_trace = trace
+                        if trace is not None:
+                            self.w_f_trace = trace
                 except OperationError, e:
                     operr = e
             pytraceback.record_application_traceback(
@@ -1421,9 +1423,10 @@
 
         # add a softspace unless we just printed a string which ends in a '\t'
         # or '\n' -- or more generally any whitespace character but ' '
-        if isinstance(x, str) and x and x[-1].isspace() and x[-1]!=' ':
-            return
-        # XXX add unicode handling
+        if isinstance(x, (str, unicode)) and x:
+            lastchar = x[-1]
+            if lastchar.isspace() and lastchar != ' ':
+                return
         file_softspace(stream, True)
     print_item_to._annspecialcase_ = "specialize:argtype(0)"
 

diff --git a/pypy/translator/goal/old_queries.py b/pypy/translator/goal/old_queries.py
--- a/pypy/translator/goal/old_queries.py
+++ b/pypy/translator/goal/old_queries.py
@@ -415,12 +415,10 @@
         ops = 0
     count = Counter()
     def visit(block):
-        if isinstance(block, flowmodel.Block):
+    for block in graph.iterblocks():
             count.blocks += 1
             count.ops += len(block.operations)
-        elif isinstance(block, flowmodel.Link):
-            count.links += 1
-    flowmodel.traverse(visit, graph)
+    count.links = len(list(graph.iterlinks()))
     return count.blocks, count.links, count.ops
 
 # better used before backends opts

diff --git a/pypy/module/_multiprocessing/test/test_connection.py b/pypy/module/_multiprocessing/test/test_connection.py
--- a/pypy/module/_multiprocessing/test/test_connection.py
+++ b/pypy/module/_multiprocessing/test/test_connection.py
@@ -10,7 +10,7 @@
 
 class AppTestBufferTooShort:
     def setup_class(cls):
-        space = gettestobjspace(usemodules=('_multiprocessing', 'thread'))
+        space = gettestobjspace(usemodules=('_multiprocessing', 'thread', 'signal'))
         cls.space = space
 
         if option.runappdirect:
@@ -88,7 +88,7 @@
 
 class AppTestSocketConnection(BaseConnectionTest):
     def setup_class(cls):
-        space = gettestobjspace(usemodules=('_multiprocessing', 'thread'))
+        space = gettestobjspace(usemodules=('_multiprocessing', 'thread', 'signal'))
         cls.space = space
         cls.w_connections = space.newlist([])
 

diff --git a/pypy/module/thread/test/support.py b/pypy/module/thread/test/support.py
--- a/pypy/module/thread/test/support.py
+++ b/pypy/module/thread/test/support.py
@@ -32,7 +32,7 @@
 class GenericTestThread:
 
     def setup_class(cls):
-        space = gettestobjspace(usemodules=('thread', 'time'))
+        space = gettestobjspace(usemodules=('thread', 'time', 'signal'))
         cls.space = space
 
         if option.runappdirect:

diff --git a/pypy/interpreter/nestedscope.py b/pypy/interpreter/nestedscope.py
--- a/pypy/interpreter/nestedscope.py
+++ b/pypy/interpreter/nestedscope.py
@@ -219,12 +219,14 @@
             freevars = [self.space.interp_w(Cell, cell)
                         for cell in self.space.fixedview(w_freevarstuple)]
         else:
-            nfreevars = len(codeobj.co_freevars)
-            freevars = [self.space.interp_w(Cell, self.popvalue())
-                        for i in range(nfreevars)]
-            freevars.reverse()
-        defaultarguments = [self.popvalue() for i in range(numdefaults)]
-        defaultarguments.reverse()
+            n = len(codeobj.co_freevars)
+            freevars = [None] * n
+            while True:
+                n -= 1
+                if n < 0:
+                    break
+                freevars[n] = self.space.interp_w(Cell, self.popvalue())
+        defaultarguments = self.popvalues(numdefaults)
         fn = function.Function(self.space, codeobj, self.w_globals,
                                defaultarguments, freevars)
         self.pushvalue(self.space.wrap(fn))

diff --git a/lib_pypy/pyrepl/unix_eventqueue.py b/lib_pypy/pyrepl/unix_eventqueue.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/unix_eventqueue.py
@@ -0,0 +1,86 @@
+#   Copyright 2000-2008 Michael Hudson-Doyle <micahel at gmail.com>
+#                       Armin Rigo
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+# Bah, this would be easier to test if curses/terminfo didn't have so
+# much non-introspectable global state.
+
+from pyrepl import keymap
+from pyrepl.console import Event
+from pyrepl import curses
+from termios import tcgetattr, VERASE
+import os
+
+_keynames = {
+    "delete" : "kdch1",
+    "down" : "kcud1",
+    "end" : "kend",
+    "enter" : "kent",
+    "f1"  : "kf1",    "f2"  : "kf2",    "f3"  : "kf3",    "f4"  : "kf4",
+    "f5"  : "kf5",    "f6"  : "kf6",    "f7"  : "kf7",    "f8"  : "kf8",
+    "f9"  : "kf9",    "f10" : "kf10",   "f11" : "kf11",   "f12" : "kf12",
+    "f13" : "kf13",   "f14" : "kf14",   "f15" : "kf15",   "f16" : "kf16",
+    "f17" : "kf17",   "f18" : "kf18",   "f19" : "kf19",   "f20" : "kf20",
+    "home" : "khome",
+    "insert" : "kich1",
+    "left" : "kcub1",
+    "page down" : "knp",
+    "page up"   : "kpp",
+    "right" : "kcuf1",
+    "up" : "kcuu1",
+    }
+
+class EventQueue(object):
+    def __init__(self, fd):
+        our_keycodes = {}
+        for key, tiname in _keynames.items():
+            keycode = curses.tigetstr(tiname)
+            if keycode:
+                our_keycodes[keycode] = unicode(key)
+        if os.isatty(fd):
+            our_keycodes[tcgetattr(fd)[6][VERASE]] = u'backspace'
+        self.k = self.ck = keymap.compile_keymap(our_keycodes)
+        self.events = []
+        self.buf = []
+    def get(self):
+        if self.events:
+            return self.events.pop(0)
+        else:
+            return None
+    def empty(self):
+        return not self.events
+    def insert(self, event):
+        self.events.append(event)
+    def push(self, char):
+        if char in self.k:
+            k = self.k[char]
+            if isinstance(k, dict):
+                self.buf.append(char)
+                self.k = k
+            else:
+                self.events.append(Event('key', k, ''.join(self.buf) + char))
+                self.buf = []
+                self.k = self.ck
+        elif self.buf:
+            self.events.extend([Event('key', c, c) for c in self.buf])
+            self.buf = []
+            self.k = self.ck
+            self.push(char)
+        else:
+            self.events.append(Event('key', char, char))

diff --git a/lib_pypy/pyrepl/simple_interact.py b/lib_pypy/pyrepl/simple_interact.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/simple_interact.py
@@ -0,0 +1,64 @@
+#   Copyright 2000-2010 Michael Hudson-Doyle <micahel at gmail.com>
+#                       Armin Rigo
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+"""This is an alternative to python_reader which tries to emulate
+the CPython prompt as closely as possible, with the exception of
+allowing multiline input and multiline history entries.
+"""
+
+import sys
+from pyrepl.readline import multiline_input, _error, _get_reader
+
+def check():     # returns False if there is a problem initializing the state
+    try:
+        _get_reader()
+    except _error:
+        return False
+    return True
+
+def run_multiline_interactive_console(mainmodule=None):
+    import code
+    if mainmodule is None:
+        import __main__ as mainmodule
+    console = code.InteractiveConsole(mainmodule.__dict__)
+
+    def more_lines(unicodetext):
+        # ooh, look at the hack:
+        src = "#coding:utf-8\n"+unicodetext.encode('utf-8')
+        try:
+            code = console.compile(src, '<input>', 'single')
+        except (OverflowError, SyntaxError, ValueError):
+            return False
+        else:
+            return code is None
+
+    while 1:
+        try:
+            ps1 = getattr(sys, 'ps1', '>>> ')
+            ps2 = getattr(sys, 'ps2', '... ')
+            try:
+                statement = multiline_input(more_lines, ps1, ps2)
+            except EOFError:
+                break
+            more = console.push(statement)
+            assert not more
+        except KeyboardInterrupt:
+            console.write("\nKeyboardInterrupt\n")
+            console.resetbuffer()

diff --git a/lib_pypy/pyrepl/__init__.py b/lib_pypy/pyrepl/__init__.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/__init__.py
@@ -0,0 +1,19 @@
+#   Copyright 2000-2008 Michael Hudson-Doyle <micahel at gmail.com>
+#                       Armin Rigo
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

diff --git a/pypy/translator/cli/src/pypylib.cs b/pypy/translator/cli/src/pypylib.cs
--- a/pypy/translator/cli/src/pypylib.cs
+++ b/pypy/translator/cli/src/pypylib.cs
@@ -26,7 +26,10 @@
             else {
                 string res = "";
                 foreach(char ch in x)
-                    res+= string.Format("\\x{0:X2}", (int)ch);
+                    if (ch >= 32 && ch < 128)
+                        res+= ch;
+                    else
+                        res+= string.Format("\\x{0:X2}", (int)ch);
                 return string.Format("'{0}'", res);
             }
         }
@@ -498,6 +501,11 @@
             }
         }
 
+        public static bool IntBetween(int a, int b, int c)
+        {
+            return a <= b && b < c;
+        }
+
         public static bool Equal<T>(T t1, T t2) 
         { 
             if (t1 == null)
@@ -717,9 +725,31 @@
             return s.Substring(start, count);
         }
 
-        public static string[] ll_split_chr(string s, char ch)
+        public static string[] ll_split_chr(string s, char ch, int max)
         {
-            return s.Split(ch);
+            if (max < 0)
+                return s.Split(ch);
+            else
+                return s.Split(new Char[] {ch}, max + 1);
+        }
+
+        public static string[] ll_rsplit_chr(string s, char ch, int max)
+        {
+            string[] splits = s.Split(ch);
+            if (max < 0 || splits.Length <= max + 1)
+                return splits;
+            else {
+                /* XXX not very efficient */
+                string first = splits[0];
+                // join the first (length - max - 1) items
+                int i;
+                for (i = 1; i < splits.Length - max; i++)
+                    first += ch + splits[i];
+                splits[0] = first;
+                Array.Copy(splits, i, splits, 1, max);
+                Array.Resize(ref splits, max + 1);
+                return splits;
+            }
         }
 
         public static bool ll_contains(string s, char ch)
@@ -1123,10 +1153,36 @@
 
     public class rffi
     {
-      public static int tolower(int chr)
-      {
-        return (int)Char.ToLower((char)chr);
-      }
+        public static int tolower(int chr)
+        {
+            return (int)Char.ToLower((char)chr);
+        }
+
+        public static int locale_tolower(int chr)
+        {
+            return (int)Char.ToLower((char)chr);
+        }
+
+        public static int locale_isupper(int chr)
+        {
+            return Convert.ToInt32(Char.IsUpper((char)chr));
+        }
+
+        public static int locale_islower(int chr)
+        {
+            return Convert.ToInt32(Char.IsLower((char)chr));
+        }
+
+        public static int locale_isalpha(int chr)
+        {
+            return Convert.ToInt32(Char.IsLetter((char)chr));
+        }
+
+        public static int locale_isalnum(int chr)
+        {
+            return Convert.ToInt32(Char.IsLetterOrDigit((char)chr));
+        }
+
     }
 
 }

diff --git a/pypy/translator/simplify.py b/pypy/translator/simplify.py
--- a/pypy/translator/simplify.py
+++ b/pypy/translator/simplify.py
@@ -9,7 +9,7 @@
 from pypy.objspace.flow import operation
 from pypy.objspace.flow.model import (SpaceOperation, Variable, Constant, Block,
                                       Link, c_last_exception, checkgraph,
-                                      traverse, mkentrymap)
+                                      mkentrymap)
 from pypy.rlib import rarithmetic
 from pypy.translator import unsimplify
 from pypy.translator.backendopt import ssa
@@ -76,23 +76,19 @@
 def desugar_isinstance(graph):
     """Replace isinstance operation with a call to isinstance."""
     constant_isinstance = Constant(isinstance)
-    def visit(block):
-        if not isinstance(block, Block):
-            return
+    for block in graph.iterblocks():
         for i in range(len(block.operations) - 1, -1, -1):
             op = block.operations[i]
             if op.opname == "isinstance":
                 args = [constant_isinstance, op.args[0], op.args[1]]
                 new_op = SpaceOperation("simple_call", args, op.result)
                 block.operations[i] = new_op
-    traverse(visit, graph)
 
 def eliminate_empty_blocks(graph):
     """Eliminate basic blocks that do not contain any operations.
     When this happens, we need to replace the preceeding link with the
     following link.  Arguments of the links should be updated."""
-    def visit(link):
-        if isinstance(link, Link):
+    for link in list(graph.iterlinks()):
             while not link.target.operations:
                 block1 = link.target
                 if block1.exitswitch is not None:
@@ -113,7 +109,6 @@
                 link.args = outputargs
                 link.target = exit.target
                 # the while loop above will simplify recursively the new link
-    traverse(visit, graph)
 
 def transform_ovfcheck(graph):
     """The special function calls ovfcheck and ovfcheck_lshift need to
@@ -174,11 +169,10 @@
     def rename(v):
         return renaming.get(v, v)
 
-    def visit(block):
-        if not (isinstance(block, Block)
-                and block.exitswitch == clastexc
+    for block in graph.iterblocks():
+        if not (block.exitswitch == clastexc
                 and block.exits[-1].exitcase is Exception):
-            return
+            continue
         covered = [link.exitcase for link in block.exits[1:-1]]
         seen = []
         preserve = list(block.exits[:-1])
@@ -233,8 +227,6 @@
             exits.append(link)
         block.recloseblock(*(preserve + exits))
 
-    traverse(visit, graph)
-
 def transform_xxxitem(graph):
     # xxx setitem too
     for block in graph.iterblocks():
@@ -262,9 +254,9 @@
                 return True
         return False
 
-    def visit(block):
-        if not (isinstance(block, Block) and block.exitswitch == clastexc):
-            return
+    for block in list(graph.iterblocks()):
+        if block.exitswitch != clastexc:
+            continue
         exits = []
         seen = []
         for link in block.exits:
@@ -283,8 +275,6 @@
             seen.append(case)
         block.recloseblock(*exits)
 
-    traverse(visit, graph)
-
 def join_blocks(graph):
     """Links can be deleted if they are the single exit of a block and
     the single entry point of the next block.  When this happens, we can
@@ -340,8 +330,7 @@
     this is how implicit exceptions are removed (see _implicit_ in
     flowcontext.py).
     """
-    def visit(block):
-        if isinstance(block, Block):
+    for block in list(graph.iterblocks()):
             for i in range(len(block.exits)-1, -1, -1):
                 exit = block.exits[i]
                 if not (exit.target is graph.exceptblock and
@@ -361,7 +350,6 @@
                 lst = list(block.exits)
                 del lst[i]
                 block.recloseblock(*lst)
-    traverse(visit, graph)
 
 
 # _____________________________________________________________________
@@ -627,12 +615,11 @@
                         tgts.append((exit.exitcase, tgt))
         return tgts
 
-    def visit(block):
-        if isinstance(block, Block) and block.operations and block.operations[-1].opname == 'is_true':
+    for block in graph.iterblocks():
+        if block.operations and block.operations[-1].opname == 'is_true':
             tgts = has_is_true_exitpath(block)
             if tgts:
                 candidates.append((block, tgts))
-    traverse(visit, graph)
 
     while candidates:
         cand, tgts = candidates.pop()

diff --git a/pypy/module/thread/os_local.py b/pypy/module/thread/os_local.py
--- a/pypy/module/thread/os_local.py
+++ b/pypy/module/thread/os_local.py
@@ -12,7 +12,7 @@
     def __init__(self, space, initargs):
         self.initargs = initargs
         ident = thread.get_ident()
-        self.dicts = {ident: space.newdict()}
+        self.dicts = {ident: space.newdict(instance=True)}
 
     def getdict(self, space):
         ident = thread.get_ident()
@@ -51,10 +51,6 @@
                         __dict__ = GetSetProperty(descr_get_dict, cls=Local),
                         )
 
-def getlocaltype(space):
-    return space.gettypeobject(Local.typedef)
-
-
 def finish_thread(w_obj):
     assert isinstance(w_obj, Local)
     ident = thread.get_ident()

diff --git a/pypy/rpython/module/ll_os.py b/pypy/rpython/module/ll_os.py
--- a/pypy/rpython/module/ll_os.py
+++ b/pypy/rpython/module/ll_os.py
@@ -29,7 +29,7 @@
 from pypy.rpython.lltypesystem.rstr import STR
 from pypy.rpython.annlowlevel import llstr
 from pypy.rlib import rgc
-from pypy.rlib.objectmodel import keepalive_until_here, specialize
+from pypy.rlib.objectmodel import specialize
 
 def monkeypatch_rposix(posixfunc, unicodefunc, signature):
     func_name = posixfunc.__name__

diff --git a/pypy/translator/jvm/src/pypy/StatResult.java b/pypy/translator/jvm/src/pypy/StatResult.java
--- a/pypy/translator/jvm/src/pypy/StatResult.java
+++ b/pypy/translator/jvm/src/pypy/StatResult.java
@@ -8,7 +8,7 @@
  *
  * <p>The actual stat() function is defined in PyPy.java.
  */
-class StatResult {
+public class StatResult {
     public int item0, item3, item4, item5;
     public long item1, item2, item6;
     public double item7, item8, item9;

diff --git a/pypy/translator/gensupp.py b/pypy/translator/gensupp.py
--- a/pypy/translator/gensupp.py
+++ b/pypy/translator/gensupp.py
@@ -6,15 +6,13 @@
 import sys
 
 from pypy.objspace.flow.model import Block
-from pypy.objspace.flow.model import traverse
 
 # ordering the blocks of a graph by source position
 
 def ordered_blocks(graph):
     # collect all blocks
     allblocks = []
-    def visit(block):
-        if isinstance(block, Block):
+    for block in graph.iterblocks():
             # first we order by offset in the code string
             if block.operations:
                 ofs = block.operations[0].offset
@@ -26,7 +24,6 @@
             else:
                 txt = "dummy"
             allblocks.append((ofs, txt, block))
-    traverse(visit, graph)
     allblocks.sort()
     #for ofs, txt, block in allblocks:
     #    print ofs, txt, block

diff --git a/pypy/translator/jvm/src/pypy/ll_os.java b/pypy/translator/jvm/src/pypy/ll_os.java
--- a/pypy/translator/jvm/src/pypy/ll_os.java
+++ b/pypy/translator/jvm/src/pypy/ll_os.java
@@ -14,10 +14,22 @@
 
 abstract class FileWrapper
 {
+    private final String name;
+
+    public FileWrapper(String name)
+    {
+        this.name = name;
+    }
+
     public abstract void write(String buffer);
     public abstract String read(int count);
     public abstract void close();
     public abstract RandomAccessFile getFile();
+
+    public String getName()
+    {
+        return this.name;
+    }
 }
 
 class PrintStreamWrapper extends FileWrapper
@@ -25,8 +37,9 @@
     private final PrintStream stream;
     private final ll_os os;
 
-    public PrintStreamWrapper(PrintStream stream, ll_os os)
+    public PrintStreamWrapper(String name, PrintStream stream, ll_os os)
     {
+        super(name);
         this.stream = stream;
         this.os = os;
     }
@@ -58,8 +71,9 @@
     private final InputStream stream;
     private final ll_os os;
 
-    public InputStreamWrapper(InputStream stream, ll_os os)
+    public InputStreamWrapper(String name, InputStream stream, ll_os os)
     {
+        super(name);
         this.stream = stream;
         this.os = os;
     }
@@ -102,11 +116,13 @@
     private final boolean canWrite;
     private final ll_os os;
 
-    public RandomAccessFileWrapper(RandomAccessFile file, 
+    public RandomAccessFileWrapper(String name,
+                                   RandomAccessFile file, 
                                    boolean canRead, 
                                    boolean canWrite,
                                    ll_os os)
     {
+        super(name);
         this.file = file;
         this.canRead = canRead;
         this.canWrite = canWrite;
@@ -228,9 +244,9 @@
 
     public ll_os(Interlink interlink) {
         this.interlink = interlink;
-        FileDescriptors.put(0, new InputStreamWrapper(System.in, this));
-        FileDescriptors.put(1, new PrintStreamWrapper(System.out, this));
-        FileDescriptors.put(2, new PrintStreamWrapper(System.err, this));
+        FileDescriptors.put(0, new InputStreamWrapper("<stdin>", System.in, this));
+        FileDescriptors.put(1, new PrintStreamWrapper("<stdout>", System.out, this));
+        FileDescriptors.put(2, new PrintStreamWrapper("<stderr>", System.err, this));
         fdcount = 2;
     }
 
@@ -339,7 +355,7 @@
         // XXX: we ignore O_CREAT
         RandomAccessFile file = open_file(name, javaMode, flags);
         RandomAccessFileWrapper wrapper = 
-          new RandomAccessFileWrapper(file, canRead, canWrite, this);
+            new RandomAccessFileWrapper(name, file, canRead, canWrite, this);
 
         fdcount++;
         FileDescriptors.put(fdcount, wrapper);
@@ -418,6 +434,12 @@
         return ll_os_stat(path); // XXX
     }
 
+    public StatResult ll_os_fstat(int fd)
+    {
+        String name = getfd(fd).getName();
+        return ll_os_stat(name);
+    }
+
     public String ll_os_strerror(int errno)
     {
         String msg = ErrorMessages.remove(errno);

diff --git a/pypy/module/cpyext/include/modsupport.h b/pypy/module/cpyext/include/modsupport.h
--- a/pypy/module/cpyext/include/modsupport.h
+++ b/pypy/module/cpyext/include/modsupport.h
@@ -38,7 +38,9 @@
 
 
 PyObject * Py_BuildValue(const char *, ...);
+PyObject * Py_VaBuildValue(const char *, va_list);
 PyObject * _Py_BuildValue_SizeT(const char *, ...);
+PyObject * _Py_VaBuildValue_SizeT(const char *, va_list);
 int _PyArg_NoKeywords(const char *funcname, PyObject *kw);
 
 int PyArg_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t max, ...);

diff --git a/pypy/rpython/memory/test/test_gc.py b/pypy/rpython/memory/test/test_gc.py
--- a/pypy/rpython/memory/test/test_gc.py
+++ b/pypy/rpython/memory/test/test_gc.py
@@ -8,7 +8,7 @@
 from pypy.rpython.lltypesystem.rstr import STR
 from pypy.rpython.lltypesystem.lloperation import llop
 from pypy.rlib.objectmodel import we_are_translated
-from pypy.rlib.objectmodel import compute_unique_id, keepalive_until_here
+from pypy.rlib.objectmodel import compute_unique_id
 from pypy.rlib import rgc
 from pypy.rlib.rstring import StringBuilder
 from pypy.rlib.rarithmetic import LONG_BIT

diff --git a/pypy/translator/backendopt/test/test_mallocprediction.py b/pypy/translator/backendopt/test/test_mallocprediction.py
--- a/pypy/translator/backendopt/test/test_mallocprediction.py
+++ b/pypy/translator/backendopt/test/test_mallocprediction.py
@@ -4,7 +4,7 @@
 from pypy.translator.backendopt.all import backend_optimizations
 from pypy.translator.translator import TranslationContext, graphof
 from pypy.rpython.llinterp import LLInterpreter
-from pypy.objspace.flow.model import checkgraph, flatten, Block
+from pypy.objspace.flow.model import checkgraph, Block
 from pypy.conftest import option
 import sys
 

diff --git a/pypy/annotation/unaryop.py b/pypy/annotation/unaryop.py
--- a/pypy/annotation/unaryop.py
+++ b/pypy/annotation/unaryop.py
@@ -499,10 +499,14 @@
     def getanyitem(str):
         return str.basecharclass()
 
-    def method_split(str, patt): # XXX
+    def method_split(str, patt, max=-1):
         getbookkeeper().count("str_split", str, patt)
         return getbookkeeper().newlist(str.basestringclass())
 
+    def method_rsplit(str, patt, max=-1):
+        getbookkeeper().count("str_rsplit", str, patt)
+        return getbookkeeper().newlist(str.basestringclass())
+
     def method_replace(str, s1, s2):
         return str.basestringclass()
 

diff --git a/pypy/module/_stackless/test/conftest.py b/pypy/module/_stackless/test/conftest.py
--- a/pypy/module/_stackless/test/conftest.py
+++ b/pypy/module/_stackless/test/conftest.py
@@ -2,6 +2,7 @@
 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/doc/getting-started-dev.rst b/pypy/doc/getting-started-dev.rst
--- a/pypy/doc/getting-started-dev.rst
+++ b/pypy/doc/getting-started-dev.rst
@@ -4,7 +4,6 @@
 
 .. contents::
 
-
 .. _`try out the translator`:
 
 Trying out the translator
@@ -18,9 +17,7 @@
 
   * Download and install Pygame_.
 
-  * Download and install `Dot Graphviz`_ (optional if you have an internet
-    connection: the flowgraph viewer then connects to
-    codespeak.net and lets it convert the flowgraph by a graphviz server).
+  * Download and install `Dot Graphviz`_ 
 
 To start the interactive translator shell do::
 

diff --git a/pypy/translator/backendopt/test/test_mallocv.py b/pypy/translator/backendopt/test/test_mallocv.py
--- a/pypy/translator/backendopt/test/test_mallocv.py
+++ b/pypy/translator/backendopt/test/test_mallocv.py
@@ -5,7 +5,7 @@
 from pypy.translator.backendopt.all import backend_optimizations
 from pypy.translator.translator import TranslationContext, graphof
 from pypy.translator import simplify
-from pypy.objspace.flow.model import checkgraph, flatten, Block, mkentrymap
+from pypy.objspace.flow.model import checkgraph, Block, mkentrymap
 from pypy.objspace.flow.model import summary
 from pypy.rpython.llinterp import LLInterpreter, LLException
 from pypy.rpython.lltypesystem import lltype, llmemory, lloperation
@@ -33,8 +33,7 @@
     def check_malloc_removed(cls, graph, expected_mallocs, expected_calls):
         count_mallocs = 0
         count_calls = 0
-        for node in flatten(graph):
-            if isinstance(node, Block):
+        for node in graph.iterblocks():
                 for op in node.operations:
                     if op.opname == 'malloc':
                         count_mallocs += 1
@@ -54,7 +53,7 @@
         if option.view:
             t.view()
         self.original_graph_count = len(t.graphs)
-        # to detect missing keepalives and broken intermediate graphs,
+        # to detect broken intermediate graphs,
         # we do the loop ourselves instead of calling remove_simple_mallocs()
         maxiter = 100
         mallocv = MallocVirtualizer(t.graphs, t.rtyper, verbose=True)
@@ -557,36 +556,6 @@
     type_system = 'lltype'
     #MallocRemover = LLTypeMallocRemover
 
-    def test_with_keepalive(self):
-        from pypy.rlib.objectmodel import keepalive_until_here
-        def fn1(x, y):
-            if x > 0:
-                t = x+y, x-y
-            else:
-                t = x-y, x+y
-            s, d = t
-            keepalive_until_here(t)
-            return s*d
-        self.check(fn1, [int, int], [15, 10], 125)
-
-    def test_add_keepalives(self):
-        class A:
-            pass
-        SMALL = lltype.Struct('SMALL', ('x', lltype.Signed))
-        BIG = lltype.GcStruct('BIG', ('z', lltype.Signed), ('s', SMALL))
-        def fn7(i):
-            big = lltype.malloc(BIG)
-            a = A()
-            a.big = big
-            a.small = big.s
-            a.small.x = 0
-            while i > 0:
-                a.small.x += i
-                i -= 1
-            return a.small.x
-        self.check(fn7, [int], [10], 55,
-                   expected_mallocs=1)   # no support for interior structs
-
     def test_getsubstruct(self):
         SMALL = lltype.Struct('SMALL', ('x', lltype.Signed))
         BIG = lltype.GcStruct('BIG', ('z', lltype.Signed), ('s', SMALL))
@@ -770,39 +739,6 @@
             return x.u1.b * x.u2.a
         self.check(fn, [], [], DONT_CHECK_RESULT)
 
-    def test_keep_all_keepalives(self):
-        SIZE = llmemory.sizeof(lltype.Signed)
-        PARRAY = lltype.Ptr(lltype.FixedSizeArray(lltype.Signed, 1))
-        class A:
-            def __init__(self):
-                self.addr = llmemory.raw_malloc(SIZE)
-            def __del__(self):
-                llmemory.raw_free(self.addr)
-        class B:
-            pass
-        def myfunc():
-            b = B()
-            b.keep = A()
-            b.data = llmemory.cast_adr_to_ptr(b.keep.addr, PARRAY)
-            b.data[0] = 42
-            ptr = b.data
-            # normally 'b' could go away as early as here, which would free
-            # the memory held by the instance of A in b.keep...
-            res = ptr[0]
-            # ...so we explicitly keep 'b' alive until here
-            objectmodel.keepalive_until_here(b)
-            return res
-        graph = self.check(myfunc, [], [], 42,
-                           expected_mallocs=1,    # 'A' instance left
-                           expected_calls=1)      # to A.__init__()
-
-        # there is a getarrayitem near the end of the graph of myfunc.
-        # However, the memory it accesses must still be protected by the
-        # following keepalive, even after malloc removal
-        entrymap = mkentrymap(graph)
-        [link] = entrymap[graph.returnblock]
-        assert link.prevblock.operations[-1].opname == 'keepalive'
-
     def test_nested_struct(self):
         S = lltype.GcStruct("S", ('x', lltype.Signed))
         T = lltype.GcStruct("T", ('s', S))

diff --git a/pypy/rpython/llinterp.py b/pypy/rpython/llinterp.py
--- a/pypy/rpython/llinterp.py
+++ b/pypy/rpython/llinterp.py
@@ -857,6 +857,9 @@
     def op_gc_adr_of_nursery_free(self):
         raise NotImplementedError
 
+    def op_gc_adr_of_root_stack_top(self):
+        raise NotImplementedError
+
     def op_gc_call_rtti_destructor(self, rtti, addr):
         if hasattr(rtti._obj, 'destructor_funcptr'):
             d = rtti._obj.destructor_funcptr


diff --git a/pypy/rpython/test/test_rstr.py b/pypy/rpython/test/test_rstr.py
--- a/pypy/rpython/test/test_rstr.py
+++ b/pypy/rpython/test/test_rstr.py
@@ -576,20 +576,56 @@
                 res = self.interpret(f, [i, newlines])
                 assert res == f(i, newlines)
 
-    def test_split(self):
+    def _make_split_test(self, split_fn):
         const = self.const
         def fn(i):
             s = [const(''), const('0.1.2.4.8'), const('.1.2'), const('1.2.'), const('.1.2.4.')][i]
-            l = s.split(const('.'))
+            l = getattr(s, split_fn)(const('.'))
             sum = 0
             for num in l:
-                 if len(num):
-                     sum += ord(num[0]) - ord(const('0')[0])
+                if len(num):
+                    sum += ord(num[0]) - ord(const('0')[0])
             return sum + len(l) * 100
+        return fn
+
+    def test_split(self):
+        fn = self._make_split_test('split')
         for i in range(5):
             res = self.interpret(fn, [i])
             assert res == fn(i)
 
+    def test_rsplit(self):
+        fn = self._make_split_test('rsplit')
+        for i in range(5):
+            res = self.interpret(fn, [i])
+            assert res == fn(i)
+
+    def _make_split_limit_test(self, split_fn):
+        const = self.const
+        def fn(i, j):
+            s = [const(''), const('0.1.2.4.8'), const('.1.2'), const('1.2.'), const('.1.2.4.')][i]
+            l = getattr(s, split_fn)(const('.'), j)
+            sum = 0
+            for num in l:
+                if len(num):
+                    sum += ord(num[0]) - ord(const('0')[0])
+            return sum + len(l) * 100
+        return fn
+
+    def test_split_limit(self):
+        fn = self._make_split_limit_test('split')
+        for i in range(5):
+            for j in range(4):
+                res = self.interpret(fn, [i, j])
+                assert res == fn(i, j)
+
+    def test_rsplit_limit(self):
+        fn = self._make_split_limit_test('rsplit')
+        for i in range(5):
+            for j in range(4):
+                res = self.interpret(fn, [i, j])
+                assert res == fn(i, j)
+
     def test_contains(self):
         const = self.const
         constchar = self.constchar

diff --git a/pypy/rlib/test/test__jit_vref.py b/pypy/rlib/test/test__jit_vref.py
--- a/pypy/rlib/test/test__jit_vref.py
+++ b/pypy/rlib/test/test__jit_vref.py
@@ -6,8 +6,12 @@
 from pypy.annotation.annrpython import RPythonAnnotator
 from pypy.rpython.test.test_llinterp import interpret
 from pypy.rpython.lltypesystem.rclass import OBJECTPTR
+from pypy.rpython.ootypesystem.rclass import OBJECT
 from pypy.rpython.lltypesystem import lltype
 
+from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin
+
+from pypy.rpython.ootypesystem import ootype
 
 class X(object):
     pass
@@ -79,37 +83,48 @@
     assert s.s_instance.can_be_None
     assert s.s_instance.classdef == a.bookkeeper.getuniqueclassdef(X)
 
-def test_rtype_1():
-    def f():
-        return virtual_ref(X())
-    x = interpret(f, [])
-    assert lltype.typeOf(x) == OBJECTPTR
+class BaseTestVRef(BaseRtypingTest):
+    def test_rtype_1(self):
+        def f():
+            return virtual_ref(X())
+        x = self.interpret(f, [])
+        assert lltype.typeOf(x) == self.OBJECTTYPE
 
-def test_rtype_2():
-    def f():
-        x1 = X()
-        vref = virtual_ref(x1)
-        x2 = vref()
-        virtual_ref_finish(x2)
-        return x2
-    x = interpret(f, [])
-    assert lltype.castable(OBJECTPTR, lltype.typeOf(x)) > 0
+    def test_rtype_2(self):
+        def f():
+            x1 = X()
+            vref = virtual_ref(x1)
+            x2 = vref()
+            virtual_ref_finish(x2)
+            return x2
+        x = self.interpret(f, [])
+        assert self.castable(self.OBJECTTYPE, x)
 
-def test_rtype_3():
-    def f(n):
-        if n > 0:
-            return virtual_ref(Y())
-        else:
-            return non_virtual_ref(Z())
-    x = interpret(f, [-5])
-    assert lltype.typeOf(x) == OBJECTPTR
+    def test_rtype_3(self):
+        def f(n):
+            if n > 0:
+                return virtual_ref(Y())
+            else:
+                return non_virtual_ref(Z())
+        x = self.interpret(f, [-5])
+        assert lltype.typeOf(x) == self.OBJECTTYPE
 
-def test_rtype_4():
-    def f(n):
-        if n > 0:
-            return virtual_ref(X())
-        else:
-            return vref_None
-    x = interpret(f, [-5])
-    assert lltype.typeOf(x) == OBJECTPTR
-    assert not x
+    def test_rtype_4(self):
+        def f(n):
+            if n > 0:
+                return virtual_ref(X())
+            else:
+                return vref_None
+        x = self.interpret(f, [-5])
+        assert lltype.typeOf(x) == self.OBJECTTYPE
+        assert not x
+
+class TestLLtype(BaseTestVRef, LLRtypeMixin):
+    OBJECTTYPE = OBJECTPTR
+    def castable(self, TO, var):
+        return lltype.castable(TO, lltype.typeOf(var)) > 0
+
+class TestOOtype(BaseTestVRef, OORtypeMixin):
+    OBJECTTYPE = OBJECT 
+    def castable(self, TO, var):
+        return ootype.isSubclass(lltype.typeOf(var), TO)

diff --git a/dotviewer/conftest.py b/dotviewer/conftest.py
--- a/dotviewer/conftest.py
+++ b/dotviewer/conftest.py
@@ -6,4 +6,6 @@
         dest="pygame", default=False, 
         help="allow interactive tests using Pygame")
 
-option = py.test.config.option
+def pytest_configure(config):
+    global option
+    option = config.option

diff --git a/.hgsub b/.hgsub
deleted file mode 100644
--- a/.hgsub
+++ /dev/null
@@ -1,2 +0,0 @@
-greenlet = [svn]http://codespeak.net/svn/greenlet/trunk/c
-lib_pypy/pyrepl = [svn]http://codespeak.net/svn/pyrepl/trunk/pyrepl/pyrepl


diff --git a/pypy/translator/c/gcc/trackgcroot.py b/pypy/translator/c/gcc/trackgcroot.py
--- a/pypy/translator/c/gcc/trackgcroot.py
+++ b/pypy/translator/c/gcc/trackgcroot.py
@@ -1645,11 +1645,11 @@
                      darwin64='')
             print >> output, "%s:" % _globalname('pypy_asm_stackwalk')
 
-            print >> output, """\
+            s = """\
             /* See description in asmgcroot.py */
             .cfi_startproc
-            movq\t%rdi, %rdx\t/* 1st argument, which is the callback */
-            movq\t%rsi, %rcx\t/* 2nd argument, which is gcrootanchor */
+            /* %rdi is the 1st argument, which is the callback */
+            /* %rsi is the 2nd argument, which is gcrootanchor */
             movq\t%rsp, %rax\t/* my frame top address */
             pushq\t%rax\t\t/* ASM_FRAMEDATA[8] */
             pushq\t%rbp\t\t/* ASM_FRAMEDATA[7] */
@@ -1662,15 +1662,15 @@
             /* Add this ASM_FRAMEDATA to the front of the circular linked */
             /* list.  Let's call it 'self'.                               */
 
-            movq\t8(%rcx), %rax\t/* next = gcrootanchor->next */
+            movq\t8(%rsi), %rax\t/* next = gcrootanchor->next */
             pushq\t%rax\t\t\t\t/* self->next = next */
-            pushq\t%rcx\t\t\t/* self->prev = gcrootanchor */
-            movq\t%rsp, 8(%rcx)\t/* gcrootanchor->next = self */
+            pushq\t%rsi\t\t\t/* self->prev = gcrootanchor */
+            movq\t%rsp, 8(%rsi)\t/* gcrootanchor->next = self */
             movq\t%rsp, 0(%rax)\t\t\t/* next->prev = self */
             .cfi_def_cfa_offset 80\t/* 9 pushes + the retaddr = 80 bytes */
 
             /* note: the Mac OS X 16 bytes aligment must be respected. */
-            call\t*%rdx\t\t/* invoke the callback */
+            call\t*%rdi\t\t/* invoke the callback */
 
             /* Detach this ASM_FRAMEDATA from the circular linked list */
             popq\t%rsi\t\t/* prev = self->prev */
@@ -1687,10 +1687,16 @@
             popq\t%rcx\t\t/* ignored      ASM_FRAMEDATA[8] */
 
             /* the return value is the one of the 'call' above, */
-            /* because %rax (and possibly %rdx) are unmodified  */
+            /* because %rax is unmodified  */
             ret
             .cfi_endproc
             """
+            if self.format == 'darwin64':
+                # obscure.  gcc there seems not to support .cfi_...
+                # hack it out...
+                s = re.sub(r'([.]cfi_[^/\n]+)([/\n])',
+                           r'/* \1 disabled on darwin */\2', s)
+            print >> output, s
             _variant(elf64='.size pypy_asm_stackwalk, .-pypy_asm_stackwalk',
                      darwin64='')
         else:

diff --git a/pypy/rpython/memory/gc/env.py b/pypy/rpython/memory/gc/env.py
--- a/pypy/rpython/memory/gc/env.py
+++ b/pypy/rpython/memory/gc/env.py
@@ -259,7 +259,7 @@
 get_L2cache = globals().get('get_L2cache_' + sys.platform,
                             lambda: -1)     # implement me for other platforms
 
-NURSERY_SIZE_UNKNOWN_CACHE = 1024*1024*1024
+NURSERY_SIZE_UNKNOWN_CACHE = 1024*1024
 # arbitrary 1M. better than default of 131k for most cases
 # in case it didn't work
 

diff --git a/pypy/translator/backendopt/malloc.py b/pypy/translator/backendopt/malloc.py
--- a/pypy/translator/backendopt/malloc.py
+++ b/pypy/translator/backendopt/malloc.py
@@ -1,5 +1,5 @@
 from pypy.objspace.flow.model import Variable, Constant, Block, Link
-from pypy.objspace.flow.model import SpaceOperation, traverse
+from pypy.objspace.flow.model import SpaceOperation
 from pypy.tool.algo.unionfind import UnionFind
 from pypy.rpython.lltypesystem import lltype
 from pypy.rpython.ootypesystem import ootype
@@ -67,7 +67,6 @@
         # in this 'block', follow where the 'var' goes to and replace
         # it by a flattened-out family of variables.  This family is given
         # by newvarsmap, whose keys are the 'flatnames'.
-        self.last_removed_access = None
 
         def list_newvars():
             return [newvarsmap[key] for key in self.flatnames]
@@ -115,7 +114,6 @@
                     newargs.append(arg)
             link.args[:] = newargs
 
-        self.insert_keepalives(list_newvars())
         block.operations[:] = self.newops
 
     def compute_lifetimes(self, graph):
@@ -149,8 +147,7 @@
         set_use_point(graph.exceptblock, graph.exceptblock.inputargs[0], "except")
         set_use_point(graph.exceptblock, graph.exceptblock.inputargs[1], "except")
 
-        def visit(node):
-            if isinstance(node, Block):
+        for node in graph.iterblocks():
                 for op in node.operations:
                     if op.opname in self.IDENTITY_OPS:
                         # special-case these operations to identify their input
@@ -167,7 +164,7 @@
                 if isinstance(node.exitswitch, Variable):
                     set_use_point(node, node.exitswitch, "exitswitch", node)
 
-            if isinstance(node, Link):
+        for node in graph.iterlinks():
                 if isinstance(node.last_exception, Variable):
                     set_creation_point(node.prevblock, node.last_exception,
                                        "last_exception")
@@ -187,7 +184,6 @@
                         else:
                             d[arg] = True
 
-        traverse(visit, graph)
         return lifetimes.infos()
 
     def _try_inline_malloc(self, info):
@@ -213,7 +209,7 @@
         STRUCT = self.get_STRUCT(lltypes.keys()[0])
 
         # must be only ever accessed via getfield/setfield/getsubstruct/
-        # direct_fieldptr, or touched by keepalive or ptr_iszero/ptr_nonzero.
+        # direct_fieldptr, or touched by ptr_iszero/ptr_nonzero.
         # Note that same_as and cast_pointer are not recorded in usepoints.
         self.accessed_substructs = {}
 
@@ -333,7 +329,6 @@
     MALLOC_OP = "malloc"
     FIELD_ACCESS =     dict.fromkeys(["getfield",
                                       "setfield",
-                                      "keepalive",
                                       "ptr_iszero",
                                       "ptr_nonzero",
                                       "getarrayitem",
@@ -484,7 +479,6 @@
                                        [newvarsmap[key]],
                                        op.result)
             self.newops.append(newop)
-            self.last_removed_access = len(self.newops)
         elif op.opname in ("setfield", "setarrayitem"):
             S = op.args[0].concretetype.TO
             fldname = op.args[1].value
@@ -500,15 +494,12 @@
                 self.newops.append(newop)
             else:
                 newvarsmap[key] = op.args[2]
-                self.last_removed_access = len(self.newops)
         elif op.opname in ("same_as", "cast_pointer"):
             vars[op.result] = True
             # Consider the two pointers (input and result) as
             # equivalent.  We can, and indeed must, use the same
             # flattened list of variables for both, as a "setfield"
             # via one pointer must be reflected in the other.
-        elif op.opname == 'keepalive':
-            self.last_removed_access = len(self.newops)
         elif op.opname in ("getsubstruct", "getarraysubstruct",
                            "direct_fieldptr"):
             S = op.args[0].concretetype.TO
@@ -546,18 +537,6 @@
         else:
             raise AssertionError, op.opname
 
-        
-    def insert_keepalives(self, newvars):
-        if self.last_removed_access is not None:
-            keepalives = []
-            for v in newvars:
-                T = v.concretetype
-                if isinstance(T, lltype.Ptr) and T._needsgc():
-                    v0 = Variable()
-                    v0.concretetype = lltype.Void
-                    newop = SpaceOperation('keepalive', [v], v0)
-                    keepalives.append(newop)
-            self.newops[self.last_removed_access:self.last_removed_access] = keepalives
 
 class OOTypeMallocRemover(BaseMallocRemover):
 
@@ -616,14 +595,12 @@
                                    [newvarsmap[key]],
                                    op.result)
             self.newops.append(newop)
-            last_removed_access = len(self.newops)
         elif op.opname == "oosetfield":
             S = op.args[0].concretetype
             fldname = op.args[1].value
             key = self.key_for_field_access(S, fldname)
             assert key in newvarsmap
             newvarsmap[key] = op.args[2]
-            last_removed_access = len(self.newops)
         elif op.opname in ("same_as", "oodowncast", "ooupcast"):
             vars[op.result] = True
             # Consider the two pointers (input and result) as
@@ -639,8 +616,6 @@
         else:
             raise AssertionError, op.opname
 
-    def insert_keepalives(self, newvars):
-        pass
 
 def remove_simple_mallocs(graph, type_system='lltypesystem', verbose=True):
     if type_system == 'lltypesystem':

diff --git a/pypy/interpreter/gateway.py b/pypy/interpreter/gateway.py
--- a/pypy/interpreter/gateway.py
+++ b/pypy/interpreter/gateway.py
@@ -1126,7 +1126,7 @@
     """
     if not isinstance(source, str):
         source = py.std.inspect.getsource(source).lstrip()
-        while source.startswith('@py.test.mark.'):
+        while source.startswith(('@py.test.mark.', '@pytest.mark.')):
             # these decorators are known to return the same function
             # object, we may ignore them
             assert '\n' in source

diff --git a/pypy/jit/backend/x86/test/test_zrpy_gc.py b/pypy/jit/backend/x86/test/test_zrpy_gc.py
--- a/pypy/jit/backend/x86/test/test_zrpy_gc.py
+++ b/pypy/jit/backend/x86/test/test_zrpy_gc.py
@@ -5,8 +5,8 @@
 soon as possible (at least in a simple case).
 """
 
-import weakref
-import py
+import weakref, random
+import py, os
 from pypy.annotation import policy as annpolicy
 from pypy.rlib import rgc
 from pypy.rpython.lltypesystem import lltype, llmemory, rffi
@@ -67,6 +67,20 @@
     return entrypoint
 
 
+def get_functions_to_patch():
+    from pypy.jit.backend.llsupport import gc
+    #
+    can_inline_malloc1 = gc.GcLLDescr_framework.can_inline_malloc
+    def can_inline_malloc2(*args):
+        try:
+            if os.environ['PYPY_NO_INLINE_MALLOC']:
+                return False
+        except KeyError:
+            pass
+        return can_inline_malloc1(*args)
+    #
+    return {(gc.GcLLDescr_framework, 'can_inline_malloc'): can_inline_malloc2}
+
 def compile(f, gc, enable_opts='', **kwds):
     from pypy.annotation.listdef import s_list_of_strings
     from pypy.translator.translator import TranslationContext
@@ -82,8 +96,21 @@
     ann = t.buildannotator(policy=annpolicy.StrictAnnotatorPolicy())
     ann.build_types(f, [s_list_of_strings], main_entry_point=True)
     t.buildrtyper().specialize()
+
     if kwds['jit']:
-        apply_jit(t, enable_opts=enable_opts)
+        patch = get_functions_to_patch()
+        old_value = {}
+        try:
+            for (obj, attr), value in patch.items():
+                old_value[obj, attr] = getattr(obj, attr)
+                setattr(obj, attr, value)
+            #
+            apply_jit(t, enable_opts=enable_opts)
+            #
+        finally:
+            for (obj, attr), oldvalue in old_value.items():
+                setattr(obj, attr, oldvalue)
+
     cbuilder = genc.CStandaloneBuilder(t, f, t.config)
     cbuilder.generate_source(defines=cbuilder.DEBUG_DEFINES)
     cbuilder.compile()
@@ -122,7 +149,7 @@
 
 # ______________________________________________________________________
 
-class TestCompileFramework(object):
+class CompileFrameworkTests(object):
     # Test suite using (so far) the minimark GC.
     def setup_class(cls):
         funcs = []
@@ -173,15 +200,21 @@
         try:
             GcLLDescr_framework.DEBUG = True
             cls.cbuilder = compile(get_entry(allfuncs), DEFL_GC,
-                                   gcrootfinder="asmgcc", jit=True)
+                                   gcrootfinder=cls.gcrootfinder, jit=True)
         finally:
             GcLLDescr_framework.DEBUG = OLD_DEBUG
 
+    def _run(self, name, n, env):
+        res = self.cbuilder.cmdexec("%s %d" %(name, n), env=env)
+        assert int(res) == 20
+
     def run(self, name, n=2000):
         pypylog = udir.join('TestCompileFramework.log')
-        res = self.cbuilder.cmdexec("%s %d" %(name, n),
-                                    env={'PYPYLOG': ':%s' % pypylog})
-        assert int(res) == 20
+        env = {'PYPYLOG': ':%s' % pypylog,
+               'PYPY_NO_INLINE_MALLOC': '1'}
+        self._run(name, n, env)
+        env['PYPY_NO_INLINE_MALLOC'] = ''
+        self._run(name, n, env)
 
     def run_orig(self, name, n, x):
         self.main_allfuncs(name, n, x)
@@ -635,3 +668,10 @@
                           gcrootfinder="asmgcc", jit=True,
                           enable_opts=ALL_OPTS_NAMES)
     assert int(res) == 20
+
+
+class TestShadowStack(CompileFrameworkTests):
+    gcrootfinder = "shadowstack"
+
+class TestAsmGcc(CompileFrameworkTests):
+    gcrootfinder = "asmgcc"

diff --git a/pypy/module/thread/test/test_thread.py b/pypy/module/thread/test/test_thread.py
--- a/pypy/module/thread/test/test_thread.py
+++ b/pypy/module/thread/test/test_thread.py
@@ -214,3 +214,21 @@
         assert res == 1024*1024
         res = thread.stack_size(0)
         assert res == 2*1024*1024
+
+    def test_interrupt_main(self):
+        import thread, time
+        import signal
+
+        def f():
+            time.sleep(0.5)
+            thread.interrupt_main()
+
+        def busy_wait():
+            for x in range(1000):
+                time.sleep(0.01)
+
+        # This is normally called by app_main.py
+        signal.signal(signal.SIGINT, signal.default_int_handler)
+
+        thread.start_new_thread(f, ())
+        raises(KeyboardInterrupt, busy_wait)

diff --git a/pypy/interpreter/function.py b/pypy/interpreter/function.py
--- a/pypy/interpreter/function.py
+++ b/pypy/interpreter/function.py
@@ -22,13 +22,21 @@
     return func.code
 
 class Defaults(object):
-    _immutable_fields_ = ["items[*]"]
+    _immutable_fields_ = ["items[*]", "promote"]
 
-    def __init__(self, items):
+    def __init__(self, items, promote=False):
         self.items = items
+        self.promote = promote
 
     def getitems(self):
-        return jit.hint(self, promote=True).items
+        # an idea - we want to promote only items that we know won't change
+        # too often. this is the case for builtin functions and functions
+        # with known constant defaults. Otherwise we don't want to promote
+        # this so lambda a=a won't create a new trace each time it's
+        # encountered
+        if self.promote:
+            return jit.hint(self, promote=True).items
+        return self.items
 
     def getitem(self, idx):
         return self.getitems()[idx]
@@ -44,14 +52,15 @@
     can_change_code = True
 
     def __init__(self, space, code, w_globals=None, defs_w=[], closure=None,
-                 forcename=None):
+                 forcename=None, promote_defs=False):
         self.space = space
         self.name = forcename or code.co_name
         self.w_doc = None   # lazily read from code.getdocstring()
         self.code = code       # Code instance
         self.w_func_globals = w_globals  # the globals dictionary
         self.closure   = closure    # normally, list of Cell instances or None
-        self.defs = Defaults(defs_w)     # wrapper around list of w_default's
+        self.defs = Defaults(defs_w, promote=promote_defs)
+        # wrapper around list of w_default's
         self.w_func_dict = None # filled out below if needed
         self.w_module = None
 
@@ -620,7 +629,8 @@
     def __init__(self, func):
         assert isinstance(func, Function)
         Function.__init__(self, func.space, func.code, func.w_func_globals,
-                          func.defs.getitems(), func.closure, func.name)
+                          func.defs.getitems(), func.closure, func.name,
+                          promote_defs=True)
         self.w_doc = func.w_doc
         self.w_func_dict = func.w_func_dict
         self.w_module = func.w_module

diff --git a/lib_pypy/pyrepl/module_lister.py b/lib_pypy/pyrepl/module_lister.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/module_lister.py
@@ -0,0 +1,70 @@
+#   Copyright 2000-2004 Michael Hudson-Doyle <micahel at gmail.com>
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+from pyrepl.completing_reader import uniqify
+import os, sys
+
+# for the completion support.
+# this is all quite nastily written.
+_packages = {}
+
+def _make_module_list_dir(dir, suffs, prefix=''):
+    l = []
+    for fname in os.listdir(dir):
+        file = os.path.join(dir, fname)
+        if os.path.isfile(file):
+            for suff in suffs:
+                if fname.endswith(suff):
+                    l.append( prefix + fname[:-len(suff)] )
+                    break
+        elif os.path.isdir(file) \
+             and os.path.exists(os.path.join(file, "__init__.py")):
+            l.append( prefix + fname )
+            _packages[prefix + fname] = _make_module_list_dir(
+                file, suffs, prefix + fname + '.' )
+    l = uniqify(l)
+    l.sort()
+    return l
+
+def _make_module_list():
+    import imp
+    suffs = [x[0] for x in imp.get_suffixes() if x[0] != '.pyc']
+    def compare(x, y):
+        c = -cmp(len(x), len(y))
+        if c:
+            return c
+        else:
+            return -cmp(x, y)
+    suffs.sort(compare)
+    _packages[''] = list(sys.builtin_module_names)
+    for dir in sys.path:
+        if dir == '':
+            dir = '.'
+        if os.path.isdir(dir):
+            _packages[''] += _make_module_list_dir(dir, suffs)
+    _packages[''].sort()
+
+def find_modules(stem):
+    l = stem.split('.')
+    pack = '.'.join(l[:-1])
+    try:
+        mods = _packages[pack]
+    except KeyError:
+        raise ImportError, "can't find \"%s\" package"%pack
+    return [mod for mod in mods if mod.startswith(stem)]

diff --git a/pypy/module/cpyext/unicodeobject.py b/pypy/module/cpyext/unicodeobject.py
--- a/pypy/module/cpyext/unicodeobject.py
+++ b/pypy/module/cpyext/unicodeobject.py
@@ -7,15 +7,16 @@
     bootstrap_function, PyObjectFields, cpython_struct, CONST_STRING,
     CONST_WSTRING)
 from pypy.module.cpyext.pyerrors import PyErr_BadArgument
-from pypy.module.cpyext.pyobject import PyObject, from_ref, make_typedescr
+from pypy.module.cpyext.pyobject import (
+    PyObject, PyObjectP, Py_DecRef, make_ref, from_ref, track_reference,
+    make_typedescr, get_typedescr)
 from pypy.module.cpyext.stringobject import PyString_Check
 from pypy.module.sys.interp_encoding import setdefaultencoding
 from pypy.objspace.std import unicodeobject, unicodetype
 from pypy.rlib import runicode
 import sys
 
-## See comment in stringobject.py.  PyUnicode_FromUnicode(NULL, size) is not
-## yet supported.
+## See comment in stringobject.py.
 
 PyUnicodeObjectStruct = lltype.ForwardReference()
 PyUnicodeObject = lltype.Ptr(PyUnicodeObjectStruct)
@@ -28,7 +29,8 @@
     make_typedescr(space.w_unicode.instancetypedef,
                    basestruct=PyUnicodeObject.TO,
                    attach=unicode_attach,
-                   dealloc=unicode_dealloc)
+                   dealloc=unicode_dealloc,
+                   realize=unicode_realize)
 
 # Buffer for the default encoding (used by PyUnicde_GetDefaultEncoding)
 DEFAULT_ENCODING_SIZE = 100
@@ -39,12 +41,39 @@
 
 Py_UNICODE = lltype.UniChar
 
+def new_empty_unicode(space, length):
+    """
+    Allocatse a PyUnicodeObject and its buffer, but without a corresponding
+    interpreter object.  The buffer may be mutated, until unicode_realize() is
+    called.
+    """
+    typedescr = get_typedescr(space.w_unicode.instancetypedef)
+    py_obj = typedescr.allocate(space, space.w_unicode)
+    py_uni = rffi.cast(PyUnicodeObject, py_obj)
+
+    buflen = length + 1
+    py_uni.c_size = length
+    py_uni.c_buffer = lltype.malloc(rffi.CWCHARP.TO, buflen,
+                                    flavor='raw', zero=True)
+    return py_uni
+
 def unicode_attach(space, py_obj, w_obj):
     "Fills a newly allocated PyUnicodeObject with a unicode string"
     py_unicode = rffi.cast(PyUnicodeObject, py_obj)
     py_unicode.c_size = len(space.unicode_w(w_obj))
     py_unicode.c_buffer = lltype.nullptr(rffi.CWCHARP.TO)
 
+def unicode_realize(space, py_obj):
+    """
+    Creates the unicode in the interpreter. The PyUnicodeObject buffer must not
+    be modified after this call.
+    """
+    py_uni = rffi.cast(PyUnicodeObject, py_obj)
+    s = rffi.wcharpsize2unicode(py_uni.c_buffer, py_uni.c_size)
+    w_obj = space.wrap(s)
+    track_reference(space, py_obj, w_obj)
+    return w_obj
+
 @cpython_api([PyObject], lltype.Void, external=False)
 def unicode_dealloc(space, py_obj):
     py_unicode = rffi.cast(PyUnicodeObject, py_obj)
@@ -128,7 +157,9 @@
 def PyUnicode_AsUnicode(space, ref):
     """Return a read-only pointer to the Unicode object's internal Py_UNICODE
     buffer, NULL if unicode is not a Unicode object."""
-    if not PyUnicode_Check(space, ref):
+    # Don't use PyUnicode_Check, it will realize the object :-(
+    w_type = from_ref(space, rffi.cast(PyObject, ref.c_ob_type))
+    if not space.is_true(space.issubtype(w_type, space.w_unicode)):
         raise OperationError(space.w_TypeError,
                              space.wrap("expected unicode object"))
     return PyUnicode_AS_UNICODE(space, ref)
@@ -237,10 +268,11 @@
     object. If the buffer is not NULL, the return value might be a shared object.
     Therefore, modification of the resulting Unicode object is only allowed when u
     is NULL."""
-    if not wchar_p:
-        raise NotImplementedError
-    s = rffi.wcharpsize2unicode(wchar_p, length)
-    return space.wrap(s)
+    if wchar_p:
+        s = rffi.wcharpsize2unicode(wchar_p, length)
+        return make_ref(space, space.wrap(s))
+    else:
+        return rffi.cast(PyObject, new_empty_unicode(space, length))
 
 @cpython_api([CONST_WSTRING, Py_ssize_t], PyObject)
 def PyUnicode_FromWideChar(space, wchar_p, length):
@@ -330,6 +362,29 @@
     w_str = space.wrap(rffi.charpsize2str(s, size))
     return space.call_method(w_str, 'decode', space.wrap("utf-8"))
 
+ at cpython_api([PyObjectP, Py_ssize_t], rffi.INT_real, error=-1)
+def PyUnicode_Resize(space, ref, newsize):
+    # XXX always create a new string so far
+    py_uni = rffi.cast(PyUnicodeObject, ref[0])
+    if not py_uni.c_buffer:
+        raise OperationError(space.w_SystemError, space.wrap(
+            "PyUnicode_Resize called on already created string"))
+    try:
+        py_newuni = new_empty_unicode(space, newsize)
+    except MemoryError:
+        Py_DecRef(space, ref[0])
+        ref[0] = lltype.nullptr(PyObject.TO)
+        raise
+    to_cp = newsize
+    oldsize = py_uni.c_size
+    if oldsize < newsize:
+        to_cp = oldsize
+    for i in range(to_cp):
+        py_newuni.c_buffer[i] = py_uni.c_buffer[i]
+    Py_DecRef(space, ref[0])
+    ref[0] = rffi.cast(PyObject, py_newuni)
+    return 0
+
 @cpython_api([PyObject], PyObject)
 def PyUnicode_AsUTF8String(space, w_unicode):
     """Encode a Unicode object using UTF-8 and return the result as Python string

diff --git a/pypy/module/cpyext/include/pythonrun.h b/pypy/module/cpyext/include/pythonrun.h
--- a/pypy/module/cpyext/include/pythonrun.h
+++ b/pypy/module/cpyext/include/pythonrun.h
@@ -11,6 +11,8 @@
 /* the -3 option will probably not be implemented */
 #define Py_Py3kWarningFlag 0
 
+#define Py_FrozenFlag 0
+
 #ifdef __cplusplus
 }
 #endif

diff --git a/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py b/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py
--- a/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py
@@ -487,6 +487,7 @@
         """)
 
     def test_range_iter(self):
+        py.test.skip("until we fix defaults")
         def main(n):
             def g(n):
                 return range(n)
@@ -539,7 +540,7 @@
         i12 = int_sub_ovf(i3, 1)
         guard_no_overflow(descr=<Guard5>)
         --TICK--
-        jump(p0, p1, p2, i12, p4, descr=<Loop0>)
+        jump(p0, p1, p2, i12, descr=<Loop0>)
         """)
 
     def test_exception_inside_loop_2(self):
@@ -585,7 +586,7 @@
             --EXC-TICK--
             i14 = int_add(i4, 1)
             --TICK--
-            jump(p0, p1, p2, p3, i14, i5, p6, descr=<Loop0>)
+            jump(p0, p1, p2, p3, i14, i5, descr=<Loop0>)
         """)
 
     def test_chain_of_guards(self):
@@ -685,13 +686,13 @@
         assert log.result == 500
         loop, = log.loops_by_id('import')
         assert loop.match_by_id('import', """
-            p14 = call(ConstClass(ll_split_chr__GcStruct_listLlT_rpy_stringPtr_Char), p8, 46, descr=<GcPtrCallDescr>)
+            p14 = call(ConstClass(ll_split_chr), p8, 46, -1, descr=<GcPtrCallDescr>)
             guard_no_exception(descr=<Guard4>)
             guard_nonnull(p14, descr=<Guard5>)
             i15 = getfield_gc(p14, descr=<SignedFieldDescr list.length .*>)
             i16 = int_is_true(i15)
             guard_true(i16, descr=<Guard6>)
-            p18 = call(ConstClass(ll_pop_default__dum_nocheckConst_listPtr), p14, descr=<GcPtrCallDescr>)
+            p18 = call(ConstClass(ll_pop_default), p14, descr=<GcPtrCallDescr>)
             guard_no_exception(descr=<Guard7>)
             i19 = getfield_gc(p14, descr=<SignedFieldDescr list.length .*>)
             i20 = int_is_true(i19)
@@ -1009,10 +1010,11 @@
         """)
 
     def test_func_defaults(self):
+        py.test.skip("skipped until we fix defaults")
         def main(n):
             i = 1
             while i < n:
-                i += len(xrange(i)) / i
+                i += len(xrange(i+1)) - i
             return i
 
         log = self.run(main, [10000])
@@ -1023,19 +1025,18 @@
             guard_true(i10, descr=<Guard3>)
             # This can be improved if the JIT realized the lookup of i5 produces
             # a constant and thus can be removed entirely
-            i12 = int_sub(i5, 1)
-            i13 = uint_floordiv(i12, i7)
+            i120 = int_add(i5, 1)
+            i140 = int_lt(0, i120)
+            guard_true(i140, descr=<Guard4>)
+            i13 = uint_floordiv(i5, i7)
             i15 = int_add(i13, 1)
             i17 = int_lt(i15, 0)
-            guard_false(i17, descr=<Guard4>)
-            i18 = int_floordiv(i15, i5)
-            i19 = int_xor(i15, i5)
-            i20 = int_mod(i15, i5)
-            i21 = int_is_true(i20)
-            i22 = int_add_ovf(i5, i18)
-            guard_no_overflow(descr=<Guard5>)
+            guard_false(i17, descr=<Guard5>)
+            i20 = int_sub(i15, i5)
+            i21 = int_add_ovf(i5, i20)
+            guard_no_overflow(descr=<Guard6>)
             --TICK--
-            jump(p0, p1, p2, p3, p4, i22, i6, i7, p8, p9, descr=<Loop0>)
+            jump(p0, p1, p2, p3, p4, i21, i6, i7, p8, p9, descr=<Loop0>)
         """)
 
     def test__ffi_call_releases_gil(self):
@@ -1044,16 +1045,16 @@
             import time
             from threading import Thread
             from _ffi import CDLL, types
-            ###
+            #
             libc = CDLL(libc_name)
             sleep = libc.getfunc('sleep', [types.uint], types.uint)
             delays = [0]*n + [1]
-            ###
+            #
             def loop_of_sleeps(i, delays):
                 import time
                 for delay in delays:
                     sleep(delay)    # ID: sleep
-            ###
+            #
             threads = [Thread(target=loop_of_sleeps, args=[i, delays]) for i in range(5)]
             start = time.time()
             for i, thread in enumerate(threads):
@@ -1061,10 +1062,42 @@
             for thread in threads:
                 thread.join()
             end = time.time()
-            ###
             return end - start
-        ###
+        #
         log = self.run(main, [get_libc_name(), 200], threshold=150)
         assert 1 <= log.result <= 1.5 # at most 0.5 seconds of overhead
         loops = log.loops_by_id('sleep')
         assert len(loops) == 1 # make sure that we actually JITted the loop
+
+    def test_unpack_iterable_non_list_tuple(self):
+        def main(n):
+            import array
+
+            items = [array.array("i", [1])] * n
+            total = 0
+            for a, in items:
+                total += a
+            return total
+
+        log = self.run(main, [1000000])
+        assert log.result == 1000000
+        loop, = log.loops_by_filename(self.filepath)
+        assert loop.match("""
+            i16 = int_ge(i12, i13)
+            guard_false(i16, descr=<Guard3>)
+            p17 = getarrayitem_gc(p15, i12, descr=<GcPtrArrayDescr>)
+            i19 = int_add(i12, 1)
+            setfield_gc(p4, i19, descr=<SignedFieldDescr .*W_AbstractSeqIterObject.inst_index .*>)
+            guard_nonnull_class(p17, 146982464, descr=<Guard4>)
+            i21 = getfield_gc(p17, descr=<SignedFieldDescr .*W_ArrayTypei.inst_len .*>)
+            i23 = int_lt(0, i21)
+            guard_true(i23, descr=<Guard5>)
+            i24 = getfield_gc(p17, descr=<NonGcPtrFieldDescr .*W_ArrayTypei.inst_buffer .*>)
+            i25 = getarrayitem_raw(i24, 0, descr=<SignedArrayNoLengthDescr>)
+            i27 = int_lt(1, i21)
+            guard_false(i27, descr=<Guard6>)
+            i28 = int_add_ovf(i10, i25)
+            guard_no_overflow(descr=<Guard7>)
+            --TICK--
+            jump(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, i28, i25, i19, i13, p14, p15, descr=<Loop0>)
+        """)

diff --git a/pypy/objspace/flow/test/test_model.py b/pypy/objspace/flow/test/test_model.py
--- a/pypy/objspace/flow/test/test_model.py
+++ b/pypy/objspace/flow/test/test_model.py
@@ -71,19 +71,6 @@
                                        pieces.headerblock.exits[1],
                                        pieces.whileblock.exits[0]]
 
-def test_traverse():
-    lst = []
-    traverse(lst.append, graph)
-    assert lst == [pieces.startblock,
-                   pieces.startblock.exits[0],
-                   pieces.headerblock,
-                   pieces.headerblock.exits[0],
-                   graph.returnblock,
-                   pieces.headerblock.exits[1],
-                   pieces.whileblock,
-                   pieces.whileblock.exits[0]]
-    assert flatten(graph) == lst
-
 def test_mkentrymap():
     entrymap = mkentrymap(graph)
     startlink = entrymap[graph.startblock][0]

diff --git a/pypy/translator/jvm/test/test_list.py b/pypy/translator/jvm/test/test_list.py
--- a/pypy/translator/jvm/test/test_list.py
+++ b/pypy/translator/jvm/test/test_list.py
@@ -6,7 +6,10 @@
     def test_recursive(self):
         py.test.skip("JVM doesn't support recursive lists")
     
-    def test_getitem_exc(self):
+    def test_getitem_exc_1(self):
+        py.test.skip('fixme!')
+
+    def test_getitem_exc_2(self):
         py.test.skip('fixme!')
 
     def test_r_short_list(self):

diff --git a/pypy/module/thread/os_lock.py b/pypy/module/thread/os_lock.py
--- a/pypy/module/thread/os_lock.py
+++ b/pypy/module/thread/os_lock.py
@@ -113,7 +113,4 @@
 def allocate_lock(space):
     """Create a new lock object.  (allocate() is an obsolete synonym.)
 See LockType.__doc__ for information about locks."""
-    return space.wrap(Lock(space))
-
-def getlocktype(space):
-    return space.gettypeobject(Lock.typedef)
+    return space.wrap(Lock(space))
\ No newline at end of file

diff --git a/lib_pypy/pyrepl/fancy_termios.py b/lib_pypy/pyrepl/fancy_termios.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/fancy_termios.py
@@ -0,0 +1,52 @@
+#   Copyright 2000-2004 Michael Hudson-Doyle <micahel at gmail.com>
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+import termios
+
+class TermState:
+    def __init__(self, tuples):
+        self.iflag, self.oflag, self.cflag, self.lflag, \
+                    self.ispeed, self.ospeed, self.cc = tuples
+    def as_list(self):
+        return [self.iflag, self.oflag, self.cflag, self.lflag,
+                self.ispeed, self.ospeed, self.cc]
+
+    def copy(self):
+        return self.__class__(self.as_list())
+
+def tcgetattr(fd):
+    return TermState(termios.tcgetattr(fd))
+
+def tcsetattr(fd, when, attrs):
+    termios.tcsetattr(fd, when, attrs.as_list())
+
+class Term(TermState):
+    TS__init__ = TermState.__init__
+    def __init__(self, fd=0):
+        self.TS__init__(termios.tcgetattr(fd))
+        self.fd = fd
+        self.stack = []
+    def save(self):
+        self.stack.append( self.as_list() )
+    def set(self, when=termios.TCSANOW):
+        termios.tcsetattr(self.fd, when, self.as_list())
+    def restore(self):
+        self.TS__init__(self.stack.pop())
+        self.set()
+        

diff --git a/pypy/jit/backend/x86/test/test_assembler.py b/pypy/jit/backend/x86/test/test_assembler.py
--- a/pypy/jit/backend/x86/test/test_assembler.py
+++ b/pypy/jit/backend/x86/test/test_assembler.py
@@ -140,7 +140,7 @@
     xmmregisters = lltype.malloc(rffi.LONGP.TO, 16+ACTUAL_CPU.NUM_REGS+1,
                                  flavor='raw', immortal=True)
     registers = rffi.ptradd(xmmregisters, 16)
-    stacklen = baseloc + 10
+    stacklen = baseloc + 30
     stack = lltype.malloc(rffi.LONGP.TO, stacklen, flavor='raw',
                           immortal=True)
     expected_ints = [0] * len(content)

diff --git a/pypy/translator/cli/src/ll_math.cs b/pypy/translator/cli/src/ll_math.cs
--- a/pypy/translator/cli/src/ll_math.cs
+++ b/pypy/translator/cli/src/ll_math.cs
@@ -224,5 +224,25 @@
         {
             return Math.Tanh(x);
         }
+
+        static public bool ll_math_isnan(double x)
+        {
+            return double.IsNaN(x);
+        }
+
+        static public bool ll_math_isinf(double x)
+        {
+            return double.IsInfinity(x);
+        }
+
+        static public double ll_math_copysign(double x, double y)
+        {
+            if (x < 0.0)
+                x = -x;
+            if (y > 0.0 || (y == 0.0 && Math.Atan2(y, -1.0) > 0.0))
+                return x;
+            else
+                return -x;
+        }
     }
 }

diff --git a/pypy/tool/jitlogparser/test/test_parser.py b/pypy/tool/jitlogparser/test/test_parser.py
--- a/pypy/tool/jitlogparser/test/test_parser.py
+++ b/pypy/tool/jitlogparser/test/test_parser.py
@@ -114,11 +114,11 @@
     fname = str(py.path.local(__file__).join('..', 'x.py'))
     ops = parse('''
     [i0, i1]
-    debug_merge_point("<code object f, file '%(fname)s', line 5> #9 LOAD_FAST", 0)
-    debug_merge_point("<code object f, file '%(fname)s', line 5> #12 LOAD_CONST", 0)
-    debug_merge_point("<code object f, file '%(fname)s', line 5> #22 LOAD_CONST", 0)
-    debug_merge_point("<code object f, file '%(fname)s', line 5> #28 LOAD_CONST", 0)
-    debug_merge_point("<code object f, file '%(fname)s', line 5> #6 SETUP_LOOP", 0)
+    debug_merge_point("<code object g, file '%(fname)s', line 5> #9 LOAD_FAST", 0)
+    debug_merge_point("<code object g, file '%(fname)s', line 5> #12 LOAD_CONST", 0)
+    debug_merge_point("<code object g, file '%(fname)s', line 5> #22 LOAD_CONST", 0)
+    debug_merge_point("<code object g, file '%(fname)s', line 5> #28 LOAD_CONST", 0)
+    debug_merge_point("<code object g, file '%(fname)s', line 5> #6 SETUP_LOOP", 0)
     ''' % locals())
     res = Function.from_operations(ops.operations, LoopStorage())
     assert res.linerange == (7, 9)

diff --git a/pypy/module/cpyext/import_.py b/pypy/module/cpyext/import_.py
--- a/pypy/module/cpyext/import_.py
+++ b/pypy/module/cpyext/import_.py
@@ -1,8 +1,10 @@
 from pypy.interpreter import module
 from pypy.module.cpyext.api import (
     generic_cpy_call, cpython_api, PyObject, CONST_STRING)
+from pypy.module.cpyext.pyobject import borrow_from
 from pypy.rpython.lltypesystem import rffi
 from pypy.interpreter.error import OperationError
+from pypy.interpreter.module import Module
 
 @cpython_api([PyObject], PyObject)
 def PyImport_Import(space, w_name):
@@ -45,3 +47,29 @@
     space.warn('PyImport_ImportModuleNoBlock() is not non-blocking',
                space.w_RuntimeWarning)
     return PyImport_Import(space, space.wrap(rffi.charp2str(name)))
+
+ at cpython_api([PyObject], PyObject)
+def PyImport_ReloadModule(space, w_mod):
+    from pypy.module.imp.importing import reload
+    return reload(space, w_mod)
+
+ at cpython_api([CONST_STRING], PyObject)
+def PyImport_AddModule(space, name):
+    """Return the module object corresponding to a module name.  The name
+    argument may be of the form package.module. First check the modules
+    dictionary if there's one there, and if not, create a new one and insert
+    it in the modules dictionary. Return NULL with an exception set on
+    failure.
+
+    This function does not load or import the module; if the module wasn't
+    already loaded, you will get an empty module object. Use
+    PyImport_ImportModule() or one of its variants to import a module.
+    Package structures implied by a dotted name for name are not created if
+    not already present."""
+    from pypy.module.imp.importing import check_sys_modules_w
+    modulename = rffi.charp2str(name)
+    w_mod = check_sys_modules_w(space, modulename)
+    if not w_mod or space.is_w(w_mod, space.w_None):
+        w_mod = Module(space, space.wrap(modulename))
+    return borrow_from(None, w_mod)
+


diff --git a/pypy/translator/exceptiontransform.py b/pypy/translator/exceptiontransform.py
--- a/pypy/translator/exceptiontransform.py
+++ b/pypy/translator/exceptiontransform.py
@@ -229,7 +229,6 @@
             n_need_exc_matching_blocks += need_exc_matching
             n_gen_exc_checks           += gen_exc_checks
         cleanup_graph(graph)
-        removenoops.remove_superfluous_keep_alive(graph)
         return n_need_exc_matching_blocks, n_gen_exc_checks
 
     def replace_stack_unwind(self, block):

diff --git a/pypy/module/cpyext/pystate.py b/pypy/module/cpyext/pystate.py
--- a/pypy/module/cpyext/pystate.py
+++ b/pypy/module/cpyext/pystate.py
@@ -1,5 +1,5 @@
-from pypy.module.cpyext.api import cpython_api, generic_cpy_call, CANNOT_FAIL,\
-        cpython_struct
+from pypy.module.cpyext.api import (
+    cpython_api, generic_cpy_call, CANNOT_FAIL, CConfig, cpython_struct)
 from pypy.rpython.lltypesystem import rffi, lltype
 
 PyInterpreterState = lltype.Ptr(cpython_struct("PyInterpreterState", ()))
@@ -77,6 +77,52 @@
     state = space.fromcache(InterpreterState)
     return state.get_thread_state(space)
 
+ at cpython_api([PyThreadState], PyThreadState, error=CANNOT_FAIL)
+def PyThreadState_Swap(space, tstate):
+    """Swap the current thread state with the thread state given by the argument
+    tstate, which may be NULL.  The global interpreter lock must be held."""
+    # All cpyext calls release and acquire the GIL, so this function has no
+    # side-effects
+    if tstate:
+        return lltype.nullptr(PyThreadState.TO)
+    else:
+        state = space.fromcache(InterpreterState)
+        return state.get_thread_state(space)
+
+ at cpython_api([PyThreadState], lltype.Void)
+def PyEval_AcquireThread(space, tstate):
+    """Acquire the global interpreter lock and set the current thread state to
+    tstate, which should not be NULL.  The lock must have been created earlier.
+    If this thread already has the lock, deadlock ensues.  This function is not
+    available when thread support is disabled at compile time."""
+    # All cpyext calls release and acquire the GIL, so this is not necessary.
+    pass
+
+ at cpython_api([PyThreadState], lltype.Void)
+def PyEval_ReleaseThread(space, tstate):
+    """Reset the current thread state to NULL and release the global interpreter
+    lock.  The lock must have been created earlier and must be held by the current
+    thread.  The tstate argument, which must not be NULL, is only used to check
+    that it represents the current thread state --- if it isn't, a fatal error is
+    reported. This function is not available when thread support is disabled at
+    compile time."""
+    # All cpyext calls release and acquire the GIL, so this is not necessary.
+    pass
+
+PyGILState_STATE = rffi.COpaquePtr('PyGILState_STATE',
+                                   typedef='PyGILState_STATE',
+                                   compilation_info=CConfig._compilation_info_)
+
+ at cpython_api([], PyGILState_STATE, error=CANNOT_FAIL)
+def PyGILState_Ensure(space):
+    # All cpyext calls release and acquire the GIL, so this is not necessary.
+    return 0
+
+ at cpython_api([PyGILState_STATE], lltype.Void)
+def PyGILState_Release(space, state):
+    # All cpyext calls release and acquire the GIL, so this is not necessary.
+    return
+
 @cpython_api([], PyInterpreterState, error=CANNOT_FAIL)
 def PyInterpreterState_Head(space):
     """Return the interpreter state object at the head of the list of all such objects.

diff --git a/pypy/jit/metainterp/optimizeopt/virtualize.py b/pypy/jit/metainterp/optimizeopt/virtualize.py
--- a/pypy/jit/metainterp/optimizeopt/virtualize.py
+++ b/pypy/jit/metainterp/optimizeopt/virtualize.py
@@ -4,6 +4,8 @@
 from pypy.jit.metainterp.optimizeutil import descrlist_dict
 from pypy.rlib.objectmodel import we_are_translated
 from pypy.jit.metainterp.optimizeopt import optimizer
+from pypy.jit.metainterp.executor import execute
+from pypy.jit.codewriter.heaptracker import vtable2descr
 
 
 class AbstractVirtualValue(optimizer.OptValue):
@@ -72,28 +74,53 @@
         assert isinstance(fieldvalue, optimizer.OptValue)
         self._fields[ofs] = fieldvalue
 
+    def _get_descr(self):
+        raise NotImplementedError
+
+    def _is_immutable_and_filled_with_constants(self):
+        count = self._get_descr().count_fields_if_immutable()
+        if count != len(self._fields):    # always the case if count == -1
+            return False
+        for value in self._fields.itervalues():
+            subbox = value.force_box()
+            if not isinstance(subbox, Const):
+                return False
+        return True
+
     def _really_force(self):
-        assert self.source_op is not None
+        op = self.source_op
+        assert op is not None
         # ^^^ This case should not occur any more (see test_bug_3).
         #
         if not we_are_translated():
-            self.source_op.name = 'FORCE ' + self.source_op.name
-        newoperations = self.optimizer.newoperations
-        newoperations.append(self.source_op)
-        self.box = box = self.source_op.result
-        #
-        iteritems = self._fields.iteritems()
-        if not we_are_translated(): #random order is fine, except for tests
-            iteritems = list(iteritems)
-            iteritems.sort(key = lambda (x,y): x.sort_key())
-        for ofs, value in iteritems:
-            if value.is_null():
-                continue
-            subbox = value.force_box()
-            op = ResOperation(rop.SETFIELD_GC, [box, subbox], None,
-                              descr=ofs)
+            op.name = 'FORCE ' + self.source_op.name
+
+        if self._is_immutable_and_filled_with_constants():
+            box = self.optimizer.constant_fold(op)
+            self.make_constant(box)
+            for ofs, value in self._fields.iteritems():
+                subbox = value.force_box()
+                assert isinstance(subbox, Const)
+                execute(self.optimizer.cpu, None, rop.SETFIELD_GC,
+                        ofs, box, subbox)
+            # keep self._fields, because it's all immutable anyway
+        else:
+            newoperations = self.optimizer.newoperations
             newoperations.append(op)
-        self._fields = None
+            self.box = box = op.result
+            #
+            iteritems = self._fields.iteritems()
+            if not we_are_translated(): #random order is fine, except for tests
+                iteritems = list(iteritems)
+                iteritems.sort(key = lambda (x,y): x.sort_key())
+            for ofs, value in iteritems:
+                if value.is_null():
+                    continue
+                subbox = value.force_box()
+                op = ResOperation(rop.SETFIELD_GC, [box, subbox], None,
+                                  descr=ofs)
+                newoperations.append(op)
+            self._fields = None
 
     def _get_field_descr_list(self):
         _cached_sorted_fields = self._cached_sorted_fields
@@ -168,6 +195,9 @@
         fielddescrs = self._get_field_descr_list()
         return modifier.make_virtual(self.known_class, fielddescrs)
 
+    def _get_descr(self):
+        return vtable2descr(self.optimizer.cpu, self.known_class.getint())
+
     def __repr__(self):
         cls_name = self.known_class.value.adr.ptr._obj._TYPE._name
         if self._fields is None:
@@ -185,6 +215,9 @@
         fielddescrs = self._get_field_descr_list()
         return modifier.make_vstruct(self.structdescr, fielddescrs)
 
+    def _get_descr(self):
+        return self.structdescr
+
 class VArrayValue(AbstractVirtualValue):
 
     def __init__(self, optimizer, arraydescr, size, keybox, source_op=None):
@@ -286,7 +319,6 @@
         vrefinfo = self.optimizer.metainterp_sd.virtualref_info
         c_cls = vrefinfo.jit_virtual_ref_const_class
         descr_virtual_token = vrefinfo.descr_virtual_token
-        descr_virtualref_index = vrefinfo.descr_virtualref_index
         #
         # Replace the VIRTUAL_REF operation with a virtual structure of type
         # 'jit_virtual_ref'.  The jit_virtual_ref structure may be forced soon,
@@ -296,7 +328,6 @@
         tokenbox = BoxInt()
         self.emit_operation(ResOperation(rop.FORCE_TOKEN, [], tokenbox))
         vrefvalue.setfield(descr_virtual_token, self.getvalue(tokenbox))
-        vrefvalue.setfield(descr_virtualref_index, self.getvalue(indexbox))
 
     def optimize_VIRTUAL_REF_FINISH(self, op):
         # Set the 'forced' field of the virtual_ref.

diff --git a/pypy/jit/backend/x86/test/test_rx86.py b/pypy/jit/backend/x86/test/test_rx86.py
--- a/pypy/jit/backend/x86/test/test_rx86.py
+++ b/pypy/jit/backend/x86/test/test_rx86.py
@@ -206,3 +206,8 @@
     s = CodeBuilder64()
     s.MOV_rm(edx, (edi, -1))
     assert s.getvalue() == '\x48\x8B\x57\xFF'
+
+def test_movsd_xj_64():
+    s = CodeBuilder64()
+    s.MOVSD_xj(xmm2, 0x01234567)
+    assert s.getvalue() == '\xF2\x0F\x10\x14\x25\x67\x45\x23\x01'

diff --git a/pypy/module/cpyext/stubsactive.py b/pypy/module/cpyext/stubsactive.py
--- a/pypy/module/cpyext/stubsactive.py
+++ b/pypy/module/cpyext/stubsactive.py
@@ -34,43 +34,7 @@
     PyThreadState_Clear()."""
     raise NotImplementedError
 
- at cpython_api([PyThreadState], PyThreadState, error=CANNOT_FAIL)
-def PyThreadState_Swap(space, tstate):
-    """Swap the current thread state with the thread state given by the argument
-    tstate, which may be NULL.  The global interpreter lock must be held."""
-    raise NotImplementedError
-
- at cpython_api([PyThreadState], lltype.Void)
-def PyEval_AcquireThread(space, tstate):
-    """Acquire the global interpreter lock and set the current thread state to
-    tstate, which should not be NULL.  The lock must have been created earlier.
-    If this thread already has the lock, deadlock ensues.  This function is not
-    available when thread support is disabled at compile time."""
-    raise NotImplementedError
-
- at cpython_api([PyThreadState], lltype.Void)
-def PyEval_ReleaseThread(space, tstate):
-    """Reset the current thread state to NULL and release the global interpreter
-    lock.  The lock must have been created earlier and must be held by the current
-    thread.  The tstate argument, which must not be NULL, is only used to check
-    that it represents the current thread state --- if it isn't, a fatal error is
-    reported. This function is not available when thread support is disabled at
-    compile time."""
-    raise NotImplementedError
-
 @cpython_api([], rffi.INT_real, error=CANNOT_FAIL)
 def Py_MakePendingCalls(space):
     return 0
 
-PyGILState_STATE = rffi.COpaquePtr('PyGILState_STATE',
-                                   typedef='PyGILState_STATE',
-                                   compilation_info=CConfig._compilation_info_)
-
- at cpython_api([], PyGILState_STATE, error=CANNOT_FAIL)
-def PyGILState_Ensure(space):
-    return 0
-
- at cpython_api([PyGILState_STATE], lltype.Void)
-def PyGILState_Release(space, state):
-    return
-

diff --git a/pypy/rlib/_rweakkeydict.py b/pypy/rlib/_rweakkeydict.py
--- a/pypy/rlib/_rweakkeydict.py
+++ b/pypy/rlib/_rweakkeydict.py
@@ -123,7 +123,7 @@
 @jit.dont_look_inside
 def ll_get(d, llkey):
     hash = compute_identity_hash(llkey)
-    i = rdict.ll_dict_lookup(d, llkey, hash)
+    i = rdict.ll_dict_lookup(d, llkey, hash) & rdict.MASK
     #llop.debug_print(lltype.Void, i, 'get', hex(hash),
     #                 ll_debugrepr(d.entries[i].key),
     #                 ll_debugrepr(d.entries[i].value))
@@ -143,7 +143,7 @@
 def ll_set_nonnull(d, llkey, llvalue):
     hash = compute_identity_hash(llkey)
     keyref = weakref_create(llkey)    # GC effects here, before the rest
-    i = rdict.ll_dict_lookup(d, llkey, hash)
+    i = rdict.ll_dict_lookup(d, llkey, hash) & rdict.MASK
     everused = d.entries.everused(i)
     d.entries[i].key = keyref
     d.entries[i].value = llvalue
@@ -160,7 +160,7 @@
 @jit.dont_look_inside
 def ll_set_null(d, llkey):
     hash = compute_identity_hash(llkey)
-    i = rdict.ll_dict_lookup(d, llkey, hash)
+    i = rdict.ll_dict_lookup(d, llkey, hash) & rdict.MASK
     if d.entries.everused(i):
         # If the entry was ever used, clean up its key and value.
         # We don't store a NULL value, but a dead weakref, because

diff --git a/pypy/module/cpyext/src/sysmodule.c b/pypy/module/cpyext/src/sysmodule.c
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/src/sysmodule.c
@@ -0,0 +1,103 @@
+#include <Python.h>
+
+/* Reimplementation of PyFile_WriteString() no calling indirectly
+   PyErr_CheckSignals(): avoid the call to PyObject_Str(). */
+
+static int
+sys_pyfile_write_unicode(PyObject *unicode, PyObject *file)
+{
+    PyObject *writer = NULL, *args = NULL, *result = NULL;
+    int err;
+
+    if (file == NULL)
+        return -1;
+
+    writer = PyObject_GetAttrString(file, "write");
+    if (writer == NULL)
+        goto error;
+
+    args = PyTuple_Pack(1, unicode);
+    if (args == NULL)
+        goto error;
+
+    result = PyEval_CallObject(writer, args);
+    if (result == NULL) {
+        goto error;
+    } else {
+        err = 0;
+        goto finally;
+    }
+
+error:
+    err = -1;
+finally:
+    Py_XDECREF(writer);
+    Py_XDECREF(args);
+    Py_XDECREF(result);
+    return err;
+}
+
+static int
+sys_pyfile_write(const char *text, PyObject *file)
+{
+    PyObject *unicode = NULL;
+    int err;
+
+    if (file == NULL)
+        return -1;
+
+    unicode = PyUnicode_FromString(text);
+    if (unicode == NULL)
+        return -1;
+
+    err = sys_pyfile_write_unicode(unicode, file);
+    Py_DECREF(unicode);
+    return err;
+}
+
+/* APIs to write to sys.stdout or sys.stderr using a printf-like interface.
+ */
+
+static void
+sys_write(char *name, FILE *fp, const char *format, va_list va)
+{
+    PyObject *file;
+    PyObject *error_type, *error_value, *error_traceback;
+    char buffer[1001];
+    int written;
+
+    PyErr_Fetch(&error_type, &error_value, &error_traceback);
+    file = PySys_GetObject(name);
+    written = vsnprintf(buffer, sizeof(buffer), format, va);
+    if (sys_pyfile_write(buffer, file) != 0) {
+        PyErr_Clear();
+        fputs(buffer, fp);
+    }
+    if (written < 0 || (size_t)written >= sizeof(buffer)) {
+        const char *truncated = "... truncated";
+        if (sys_pyfile_write(truncated, file) != 0)
+            fputs(truncated, fp);
+    }
+    PyErr_Restore(error_type, error_value, error_traceback);
+}
+
+void
+PySys_WriteStdout(const char *format, ...)
+{
+    va_list va;
+
+    va_start(va, format);
+    sys_write("stdout", stdout, format, va);
+    va_end(va);
+}
+
+void
+PySys_WriteStderr(const char *format, ...)
+{
+    va_list va;
+
+    va_start(va, format);
+    sys_write("stderr", stderr, format, va);
+    va_end(va);
+}
+

diff --git a/pypy/module/_io/test/test_bufferedio.py b/pypy/module/_io/test/test_bufferedio.py
--- a/pypy/module/_io/test/test_bufferedio.py
+++ b/pypy/module/_io/test/test_bufferedio.py
@@ -191,6 +191,10 @@
         f = _io.BufferedReader(raw)
         assert repr(f) == '<_io.BufferedReader name=%r>' % (self.tmpfile,)
 
+class AppTestBufferedReaderWithThreads(AppTestBufferedReader):
+    spaceconfig = dict(usemodules=['_io', 'thread'])
+
+
 class AppTestBufferedWriter:
     def setup_class(cls):
         cls.space = gettestobjspace(usemodules=['_io'])

diff --git a/lib_pypy/pyrepl/commands.py b/lib_pypy/pyrepl/commands.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/commands.py
@@ -0,0 +1,385 @@
+#   Copyright 2000-2010 Michael Hudson-Doyle <micahel at gmail.com>
+#                       Antonio Cuni
+#                       Armin Rigo
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+import sys, os
+
+# Catgories of actions:
+#  killing
+#  yanking
+#  motion
+#  editing
+#  history
+#  finishing
+# [completion]
+
+class Command(object):
+    finish = 0
+    kills_digit_arg = 1
+    def __init__(self, reader, (event_name, event)):
+        self.reader = reader
+        self.event = event
+        self.event_name = event_name
+    def do(self):
+        pass
+
+class KillCommand(Command):
+    def kill_range(self, start, end):
+        if start == end:
+            return
+        r = self.reader
+        b = r.buffer
+        text = b[start:end]
+        del b[start:end]
+        if is_kill(r.last_command):
+            if start < r.pos:
+                r.kill_ring[-1] = text + r.kill_ring[-1]
+            else:
+                r.kill_ring[-1] = r.kill_ring[-1] + text
+        else:
+            r.kill_ring.append(text)
+        r.pos = start
+        r.dirty = 1
+
+class YankCommand(Command):
+    pass
+
+class MotionCommand(Command):
+    pass
+
+class EditCommand(Command):
+    pass
+
+class FinishCommand(Command):
+    finish = 1
+    pass
+
+def is_kill(command):
+    return command and issubclass(command, KillCommand)
+
+def is_yank(command):
+    return command and issubclass(command, YankCommand)
+
+# etc
+
+class digit_arg(Command):
+    kills_digit_arg = 0
+    def do(self):
+        r = self.reader
+        c = self.event[-1]
+        if c == "-":
+            if r.arg is not None:
+                r.arg = -r.arg
+            else:
+                r.arg = -1
+        else:
+            d = int(c)
+            if r.arg is None:
+                r.arg = d
+            else:
+                if r.arg < 0:
+                    r.arg = 10*r.arg - d
+                else:
+                    r.arg = 10*r.arg + d
+        r.dirty = 1
+
+class clear_screen(Command):
+    def do(self):
+        r = self.reader
+        r.console.clear()
+        r.dirty = 1
+
+class refresh(Command):
+    def do(self):
+        self.reader.dirty = 1
+
+class repaint(Command):
+    def do(self):
+        self.reader.dirty = 1
+        self.reader.console.repaint_prep()
+
+class kill_line(KillCommand):
+    def do(self):
+        r = self.reader
+        b = r.buffer
+        eol = r.eol()
+        for c in b[r.pos:eol]:
+            if not c.isspace():
+                self.kill_range(r.pos, eol)
+                return
+        else:
+            self.kill_range(r.pos, eol+1)
+
+class unix_line_discard(KillCommand):
+    def do(self):
+        r = self.reader
+        self.kill_range(r.bol(), r.pos)
+
+# XXX unix_word_rubout and backward_kill_word should actually
+# do different things...
+
+class unix_word_rubout(KillCommand):
+    def do(self):
+        r = self.reader
+        for i in range(r.get_arg()):
+            self.kill_range(r.bow(), r.pos)
+
+class kill_word(KillCommand):
+    def do(self):
+        r = self.reader
+        for i in range(r.get_arg()):
+            self.kill_range(r.pos, r.eow())
+
+class backward_kill_word(KillCommand):
+    def do(self):
+        r = self.reader
+        for i in range(r.get_arg()):
+            self.kill_range(r.bow(), r.pos)
+
+class yank(YankCommand):
+    def do(self):
+        r = self.reader
+        if not r.kill_ring:
+            r.error("nothing to yank")
+            return
+        r.insert(r.kill_ring[-1])
+
+class yank_pop(YankCommand):
+    def do(self):
+        r = self.reader
+        b = r.buffer
+        if not r.kill_ring:
+            r.error("nothing to yank")
+            return
+        if not is_yank(r.last_command):
+            r.error("previous command was not a yank")
+            return
+        repl = len(r.kill_ring[-1])
+        r.kill_ring.insert(0, r.kill_ring.pop())
+        t = r.kill_ring[-1]
+        b[r.pos - repl:r.pos] = t
+        r.pos = r.pos - repl + len(t)
+        r.dirty = 1
+
+class interrupt(FinishCommand):
+    def do(self):
+        import signal
+        self.reader.console.finish()
+        os.kill(os.getpid(), signal.SIGINT)
+
+class suspend(Command):
+    def do(self):
+        import signal
+        r = self.reader
+        p = r.pos
+        r.console.finish()
+        os.kill(os.getpid(), signal.SIGSTOP)
+        ## this should probably be done
+        ## in a handler for SIGCONT?
+        r.console.prepare()
+        r.pos = p
+        r.posxy = 0, 0
+        r.dirty = 1
+        r.console.screen = []
+
+class up(MotionCommand):
+    def do(self):
+        r = self.reader
+        for i in range(r.get_arg()):
+            bol1 = r.bol()
+            if bol1 == 0:
+                if r.historyi > 0:
+                    r.select_item(r.historyi - 1)
+                    return
+                r.pos = 0
+                r.error("start of buffer")
+                return
+            bol2 = r.bol(bol1-1)
+            line_pos = r.pos - bol1
+            if line_pos > bol1 - bol2 - 1:
+                r.sticky_y = line_pos
+                r.pos = bol1 - 1
+            else:
+                r.pos = bol2 + line_pos
+
+class down(MotionCommand):
+    def do(self):
+        r = self.reader
+        b = r.buffer
+        for i in range(r.get_arg()):
+            bol1 = r.bol()
+            eol1 = r.eol()
+            if eol1 == len(b):
+                if r.historyi < len(r.history):
+                    r.select_item(r.historyi + 1)
+                    r.pos = r.eol(0)
+                    return
+                r.pos = len(b)
+                r.error("end of buffer")
+                return
+            eol2 = r.eol(eol1+1)
+            if r.pos - bol1 > eol2 - eol1 - 1:
+                r.pos = eol2
+            else:
+                r.pos = eol1 + (r.pos - bol1) + 1
+
+class left(MotionCommand):
+    def do(self):
+        r = self.reader
+        for i in range(r.get_arg()):        
+            p = r.pos - 1
+            if p >= 0:
+                r.pos = p
+            else:
+                self.reader.error("start of buffer")
+
+class right(MotionCommand):
+    def do(self):
+        r = self.reader
+        b = r.buffer
+        for i in range(r.get_arg()):
+            p = r.pos + 1
+            if p <= len(b):
+                r.pos = p
+            else:
+                self.reader.error("end of buffer")
+
+class beginning_of_line(MotionCommand):
+    def do(self):
+        self.reader.pos = self.reader.bol()
+
+class end_of_line(MotionCommand):
+    def do(self):
+        r = self.reader
+        self.reader.pos = self.reader.eol()
+
+class home(MotionCommand):
+    def do(self):
+        self.reader.pos = 0
+        
+class end(MotionCommand):
+    def do(self):
+        self.reader.pos = len(self.reader.buffer)
+        
+class forward_word(MotionCommand):
+    def do(self):
+        r = self.reader
+        for i in range(r.get_arg()):
+            r.pos = r.eow()
+    
+class backward_word(MotionCommand):
+    def do(self):
+        r = self.reader
+        for i in range(r.get_arg()):
+            r.pos = r.bow()
+
+class self_insert(EditCommand):
+    def do(self):
+        r = self.reader
+        r.insert(self.event * r.get_arg())
+
+class insert_nl(EditCommand):
+    def do(self):
+        r = self.reader
+        r.insert("\n" * r.get_arg())
+
+class transpose_characters(EditCommand):
+    def do(self):
+        r = self.reader
+        b = r.buffer
+        s = r.pos - 1
+        if s < 0:
+            r.error("cannot transpose at start of buffer")
+        else:
+            if s == len(b):
+                s -= 1
+            t = min(s + r.get_arg(), len(b) - 1)
+            c = b[s]
+            del b[s]
+            b.insert(t, c)
+            r.pos = t
+            r.dirty = 1
+
+class backspace(EditCommand):
+    def do(self):
+        r = self.reader
+        b = r.buffer
+        for i in range(r.get_arg()):
+            if r.pos > 0:
+                r.pos -= 1
+                del b[r.pos]
+                r.dirty = 1
+            else:
+                self.reader.error("can't backspace at start")
+
+class delete(EditCommand):
+    def do(self):
+        r = self.reader
+        b = r.buffer
+        if  ( r.pos == 0 and len(b) == 0 # this is something of a hack
+              and self.event[-1] == "\004"):
+            r.update_screen()
+            r.console.finish()
+            raise EOFError
+        for i in range(r.get_arg()):
+            if r.pos != len(b):
+                del b[r.pos]
+                r.dirty = 1
+            else:
+                self.reader.error("end of buffer")
+
+class accept(FinishCommand):
+    def do(self):
+        pass
+
+class help(Command):
+    def do(self):
+        self.reader.msg = self.reader.help_text
+        self.reader.dirty = 1
+
+class invalid_key(Command):
+    def do(self):
+        pending = self.reader.console.getpending()
+        s = ''.join(self.event) + pending.data
+        self.reader.error("`%r' not bound"%s)
+
+class invalid_command(Command):
+    def do(self):
+        s = self.event_name
+        self.reader.error("command `%s' not known"%s)
+
+class qIHelp(Command):
+    def do(self):
+        r = self.reader
+        r.insert((self.event + r.console.getpending().data) * r.get_arg())
+        r.pop_input_trans()
+
+from pyrepl import input
+
+class QITrans(object):
+    def push(self, evt):
+        self.evt = evt
+    def get(self):
+        return ('qIHelp', self.evt.raw)
+
+class quoted_insert(Command):
+    kills_digit_arg = 0
+    def do(self):
+        self.reader.push_input_trans(QITrans())

diff --git a/pypy/module/cpyext/test/foo.c b/pypy/module/cpyext/test/foo.c
--- a/pypy/module/cpyext/test/foo.c
+++ b/pypy/module/cpyext/test/foo.c
@@ -435,14 +435,6 @@
     return (PyObject *)foop;
 }
 
-/* List of functions exported by this module */
-
-static PyMethodDef foo_functions[] = {
-    {"new",        (PyCFunction)foo_new, METH_NOARGS, NULL},
-    {NULL,        NULL}    /* Sentinel */
-};
-
-
 static int initerrtype_init(PyObject *self, PyObject *args, PyObject *kwargs) {
     PyErr_SetString(PyExc_ValueError, "init raised an error!");
     return -1;
@@ -592,6 +584,41 @@
     0           /*tp_weaklist*/
 };
 
+/* A type with a custom allocator */
+static void custom_dealloc(PyObject *ob)
+{
+    free(ob);
+}
+
+static PyTypeObject CustomType;
+
+static PyObject *newCustom(PyObject *self, PyObject *args)
+{
+    PyObject *obj = calloc(1, sizeof(PyObject));
+    obj->ob_type = &CustomType;
+    _Py_NewReference(obj);
+    return obj;
+}
+
+static PyTypeObject CustomType = {
+    PyObject_HEAD_INIT(NULL)
+    0,
+    "foo.Custom",            /*tp_name*/
+    sizeof(PyObject),        /*tp_size*/
+    0,                       /*tp_itemsize*/
+    /* methods */
+    (destructor)custom_dealloc, /*tp_dealloc*/
+};
+
+
+/* List of functions exported by this module */
+
+static PyMethodDef foo_functions[] = {
+    {"new",        (PyCFunction)foo_new, METH_NOARGS, NULL},
+    {"newCustom",  (PyCFunction)newCustom, METH_NOARGS, NULL},
+    {NULL,        NULL}    /* Sentinel */
+};
+
 
 /* Initialize this module. */
 
@@ -616,7 +643,10 @@
     if (PyType_Ready(&InitErrType) < 0)
         return;
     if (PyType_Ready(&SimplePropertyType) < 0)
-	return;
+        return;
+    CustomType.ob_type = &MetaType;
+    if (PyType_Ready(&CustomType) < 0)
+        return;
     m = Py_InitModule("foo", foo_functions);
     if (m == NULL)
         return;
@@ -635,4 +665,6 @@
         return;
     if (PyDict_SetItemString(d, "Property", (PyObject *) &SimplePropertyType) < 0)
         return;
+    if (PyDict_SetItemString(d, "Custom", (PyObject *) &CustomType) < 0)
+        return;
 }

diff --git a/pypy/module/cpyext/typeobject.py b/pypy/module/cpyext/typeobject.py
--- a/pypy/module/cpyext/typeobject.py
+++ b/pypy/module/cpyext/typeobject.py
@@ -3,14 +3,14 @@
 
 from pypy.rpython.lltypesystem import rffi, lltype
 from pypy.rpython.annlowlevel import llhelper
-from pypy.interpreter.baseobjspace import DescrMismatch
+from pypy.interpreter.baseobjspace import W_Root, DescrMismatch
 from pypy.objspace.std.typeobject import W_TypeObject
 from pypy.interpreter.typedef import GetSetProperty
 from pypy.module.cpyext.api import (
-    cpython_api, cpython_struct, bootstrap_function, Py_ssize_t,
+    cpython_api, cpython_struct, bootstrap_function, Py_ssize_t, Py_ssize_tP,
     generic_cpy_call, Py_TPFLAGS_READY, Py_TPFLAGS_READYING,
     Py_TPFLAGS_HEAPTYPE, METH_VARARGS, METH_KEYWORDS, CANNOT_FAIL,
-    PyBufferProcs, build_type_checkers)
+    build_type_checkers)
 from pypy.module.cpyext.pyobject import (
     PyObject, make_ref, create_ref, from_ref, get_typedescr, make_typedescr,
     track_reference, RefcountState, borrow_from)
@@ -24,7 +24,7 @@
 from pypy.module.cpyext.structmember import PyMember_GetOne, PyMember_SetOne
 from pypy.module.cpyext.typeobjectdefs import (
     PyTypeObjectPtr, PyTypeObject, PyGetSetDef, PyMemberDef, newfunc,
-    PyNumberMethods, PySequenceMethods)
+    PyNumberMethods, PySequenceMethods, PyBufferProcs)
 from pypy.module.cpyext.slotdefs import (
     slotdefs_for_tp_slots, slotdefs_for_wrappers, get_slot_tp_function)
 from pypy.interpreter.error import OperationError
@@ -287,11 +287,17 @@
 
         W_TypeObject.__init__(self, space, extension_name,
             bases_w or [space.w_object], dict_w)
-        self.flag_cpytype = True
+        if not space.is_true(space.issubtype(self, space.w_type)):
+            self.flag_cpytype = True
         self.flag_heaptype = False
 
 @bootstrap_function
 def init_typeobject(space):
+    # Probably a hack
+    space.model.typeorder[W_PyCTypeObject] = [(W_PyCTypeObject, None),
+                                              (W_TypeObject, None),
+                                              (W_Root, None)]
+
     make_typedescr(space.w_type.instancetypedef,
                    basestruct=PyTypeObject,
                    attach=type_attach,
@@ -355,14 +361,14 @@
     # hopefully this does not clash with the memory model assumed in
     # extension modules
 
- at cpython_api([PyObject, rffi.INTP], lltype.Signed, external=False,
+ at cpython_api([PyObject, Py_ssize_tP], lltype.Signed, external=False,
              error=CANNOT_FAIL)
 def str_segcount(space, w_obj, ref):
     if ref:
-        ref[0] = rffi.cast(rffi.INT, space.len_w(w_obj))
+        ref[0] = space.len_w(w_obj)
     return 1
 
- at cpython_api([PyObject, lltype.Signed, rffi.VOIDPP], lltype.Signed,
+ at cpython_api([PyObject, Py_ssize_t, rffi.VOIDPP], lltype.Signed,
              external=False, error=-1)
 def str_getreadbuffer(space, w_str, segment, ref):
     from pypy.module.cpyext.stringobject import PyString_AsString
@@ -375,7 +381,7 @@
     Py_DecRef(space, pyref)
     return space.len_w(w_str)
 
- at cpython_api([PyObject, lltype.Signed, rffi.CCHARPP], lltype.Signed,
+ at cpython_api([PyObject, Py_ssize_t, rffi.CCHARPP], lltype.Signed,
              external=False, error=-1)
 def str_getcharbuffer(space, w_str, segment, ref):
     from pypy.module.cpyext.stringobject import PyString_AsString
@@ -472,14 +478,19 @@
 def PyType_Ready(space, pto):
     if pto.c_tp_flags & Py_TPFLAGS_READY:
         return 0
+    type_realize(space, rffi.cast(PyObject, pto))
+    return 0
+
+def type_realize(space, py_obj):
+    pto = rffi.cast(PyTypeObjectPtr, py_obj)
     assert pto.c_tp_flags & Py_TPFLAGS_READYING == 0
     pto.c_tp_flags |= Py_TPFLAGS_READYING
     try:
-        type_realize(space, rffi.cast(PyObject, pto))
-        pto.c_tp_flags |= Py_TPFLAGS_READY
+        w_obj = _type_realize(space, py_obj)
     finally:
         pto.c_tp_flags &= ~Py_TPFLAGS_READYING
-    return 0
+    pto.c_tp_flags |= Py_TPFLAGS_READY
+    return w_obj
 
 def solid_base(space, w_type):
     typedef = w_type.instancetypedef
@@ -535,7 +546,7 @@
     finally:
         Py_DecRef(space, base_pyo)
 
-def type_realize(space, py_obj):
+def _type_realize(space, py_obj):
     """
     Creates an interpreter type from a PyTypeObject structure.
     """
@@ -554,7 +565,9 @@
 
     finish_type_1(space, py_type)
 
-    w_obj = space.allocate_instance(W_PyCTypeObject, space.w_type)
+    w_metatype = from_ref(space, rffi.cast(PyObject, py_type.c_ob_type))
+
+    w_obj = space.allocate_instance(W_PyCTypeObject, w_metatype)
     track_reference(space, py_obj, w_obj)
     w_obj.__init__(space, py_type)
     w_obj.ready()

diff --git a/pypy/module/test_lib_pypy/test_stackless.py b/pypy/module/test_lib_pypy/test_stackless.py
--- a/pypy/module/test_lib_pypy/test_stackless.py
+++ b/pypy/module/test_lib_pypy/test_stackless.py
@@ -3,6 +3,8 @@
 class AppTest_Stackless:
 
     def setup_class(cls):
+        import py.test
+        py.test.importorskip('greenlet')
         space = gettestobjspace(usemodules=('_stackless', '_socket'))
         cls.space = space
         # cannot test the unpickle part on top of py.py

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
@@ -205,7 +205,8 @@
         if dirname == search:
             # not found!  let's hope that the compiled-in path is ok
             print >> sys.stderr, ('debug: WARNING: library path not found, '
-                                  'using compiled-in sys.path')
+                                  'using compiled-in sys.path '
+                                  'and sys.prefix will be unset')
             newpath = sys.path[:]
             break
         newpath = sys.pypy_initial_path(dirname)

diff --git a/pypy/module/cpyext/object.py b/pypy/module/cpyext/object.py
--- a/pypy/module/cpyext/object.py
+++ b/pypy/module/cpyext/object.py
@@ -2,14 +2,12 @@
 from pypy.module.cpyext.api import (
     cpython_api, generic_cpy_call, CANNOT_FAIL, Py_ssize_t, Py_ssize_tP,
     PyVarObject, Py_TPFLAGS_HEAPTYPE, Py_LT, Py_LE, Py_EQ, Py_NE, Py_GT,
-    Py_GE, CONST_STRING, FILEP, fwrite, build_type_checkers)
+    Py_GE, CONST_STRING, FILEP, fwrite)
 from pypy.module.cpyext.pyobject import (
     PyObject, PyObjectP, create_ref, from_ref, Py_IncRef, Py_DecRef,
-    track_reference, get_typedescr, RefcountState)
+    track_reference, get_typedescr, _Py_NewReference, RefcountState)
 from pypy.module.cpyext.typeobject import PyTypeObjectPtr
 from pypy.module.cpyext.pyerrors import PyErr_NoMemory, PyErr_BadInternalCall
-from pypy.module._file.interp_file import W_File
-from pypy.objspace.std.objectobject import W_ObjectObject
 from pypy.objspace.std.typeobject import W_TypeObject
 from pypy.interpreter.error import OperationError
 import pypy.module.__builtin__.operation as operation
@@ -185,26 +183,17 @@
     return 0
 
 @cpython_api([PyObject, PyTypeObjectPtr], PyObject)
-def PyObject_Init(space, py_obj, type):
+def PyObject_Init(space, obj, type):
     """Initialize a newly-allocated object op with its type and initial
     reference.  Returns the initialized object.  If type indicates that the
     object participates in the cyclic garbage detector, it is added to the
     detector's set of observed objects. Other fields of the object are not
     affected."""
-    if not py_obj:
+    if not obj:
         PyErr_NoMemory(space)
-    py_obj.c_ob_type = type
-    py_obj.c_ob_refcnt = 1
-    w_type = from_ref(space, rffi.cast(PyObject, type))
-    assert isinstance(w_type, W_TypeObject)
-    if w_type.is_cpytype():
-        w_obj = space.allocate_instance(W_ObjectObject, w_type)
-        track_reference(space, py_obj, w_obj)
-        state = space.fromcache(RefcountState)
-        state.set_lifeline(w_obj, py_obj)
-    else:
-        assert False, "Please add more cases in PyObject_Init"
-    return py_obj
+    obj.c_ob_type = type
+    _Py_NewReference(space, obj)
+    return obj
 
 @cpython_api([PyVarObject, PyTypeObjectPtr, Py_ssize_t], PyObject)
 def PyObject_InitVar(space, py_obj, type, size):
@@ -256,6 +245,16 @@
     expression cmp(o1, o2)."""
     return space.int_w(space.cmp(w_o1, w_o2))
 
+ at cpython_api([PyObject, PyObject, rffi.INTP], rffi.INT_real, error=-1)
+def PyObject_Cmp(space, w_o1, w_o2, result):
+    """Compare the values of o1 and o2 using a routine provided by o1, if one
+    exists, otherwise with a routine provided by o2.  The result of the
+    comparison is returned in result.  Returns -1 on failure.  This is the
+    equivalent of the Python statement result = cmp(o1, o2)."""
+    res = space.int_w(space.cmp(w_o1, w_o2))
+    result[0] = rffi.cast(rffi.INT, res)
+    return 0
+
 @cpython_api([PyObject, PyObject, rffi.INT_real], PyObject)
 def PyObject_RichCompare(space, w_o1, w_o2, opid_int):
     """Compare the values of o1 and o2 using the operation specified by opid,
@@ -396,7 +395,7 @@
         raise OperationError(space.w_TypeError, space.wrap(
             "expected a character buffer object"))
     if generic_cpy_call(space, pb.c_bf_getsegcount,
-                        obj, lltype.nullptr(rffi.INTP.TO)) != 1:
+                        obj, lltype.nullptr(Py_ssize_tP.TO)) != 1:
         raise OperationError(space.w_TypeError, space.wrap(
             "expected a single-segment buffer object"))
     size = generic_cpy_call(space, pb.c_bf_getcharbuffer,
@@ -429,40 +428,3 @@
         rffi.free_nonmovingbuffer(data, buf)
     return 0
 
-PyFile_Check, PyFile_CheckExact = build_type_checkers("File", W_File)
-
- at cpython_api([PyObject, rffi.INT_real], PyObject)
-def PyFile_GetLine(space, w_obj, n):
-    """
-    Equivalent to p.readline([n]), this function reads one line from the
-    object p.  p may be a file object or any object with a readline()
-    method.  If n is 0, exactly one line is read, regardless of the length of
-    the line.  If n is greater than 0, no more than n bytes will be read
-    from the file; a partial line can be returned.  In both cases, an empty string
-    is returned if the end of the file is reached immediately.  If n is less than
-    0, however, one line is read regardless of length, but EOFError is
-    raised if the end of the file is reached immediately."""
-    try:
-        w_readline = space.getattr(w_obj, space.wrap('readline'))
-    except OperationError:
-        raise OperationError(
-            space.w_TypeError, space.wrap(
-            "argument must be a file, or have a readline() method."))
-
-    n = rffi.cast(lltype.Signed, n)
-    if space.is_true(space.gt(space.wrap(n), space.wrap(0))):
-        return space.call_function(w_readline, space.wrap(n))
-    elif space.is_true(space.lt(space.wrap(n), space.wrap(0))):
-        return space.call_function(w_readline)
-    else:
-        # XXX Raise EOFError as specified
-        return space.call_function(w_readline)
- at cpython_api([CONST_STRING, CONST_STRING], PyObject)
-def PyFile_FromString(space, filename, mode):
-    """
-    On success, return a new file object that is opened on the file given by
-    filename, with a file mode given by mode, where mode has the same
-    semantics as the standard C routine fopen().  On failure, return NULL."""
-    w_filename = space.wrap(rffi.charp2str(filename))
-    w_mode = space.wrap(rffi.charp2str(mode))
-    return space.call_method(space.builtin, 'file', w_filename, w_mode)

diff --git a/pypy/objspace/std/dictmultiobject.py b/pypy/objspace/std/dictmultiobject.py
--- a/pypy/objspace/std/dictmultiobject.py
+++ b/pypy/objspace/std/dictmultiobject.py
@@ -108,6 +108,11 @@
         #return w_value or None
         return None
 
+    def impl_setdefault(self, w_key, w_default):
+        # here the dict is always empty
+        self._as_rdict().impl_fallback_setitem(w_key, w_default)
+        return w_default
+
     def impl_setitem(self, w_key, w_value):
         self._as_rdict().impl_fallback_setitem(w_key, w_value)
 
@@ -181,6 +186,9 @@
     # _________________________________________________________________
     # fallback implementation methods
 
+    def impl_fallback_setdefault(self, w_key, w_default):
+        return self.r_dict_content.setdefault(w_key, w_default)
+
     def impl_fallback_setitem(self, w_key, w_value):
         self.r_dict_content[w_key] = w_value
 
@@ -227,6 +235,7 @@
     ("length", 0),
     ("setitem_str", 2),
     ("setitem", 2),
+    ("setdefault", 2),
     ("delitem", 1),
     ("iter", 0),
     ("items", 0),
@@ -317,6 +326,14 @@
     def impl_setitem_str(self, key, w_value):
         self.content[key] = w_value
 
+    def impl_setdefault(self, w_key, w_default):
+        space = self.space
+        if space.is_w(space.type(w_key), space.w_str):
+            return self.content.setdefault(space.str_w(w_key), w_default)
+        else:
+            return self._as_rdict().impl_fallback_setdefault(w_key, w_default)
+
+
     def impl_delitem(self, w_key):
         space = self.space
         w_key_type = space.type(w_key)
@@ -787,13 +804,7 @@
         return w_default
 
 def dict_setdefault__DictMulti_ANY_ANY(space, w_dict, w_key, w_default):
-    # XXX should be more efficient, with only one dict lookup
-    w_value = w_dict.getitem(w_key)
-    if w_value is not None:
-        return w_value
-    else:
-        w_dict.setitem(w_key, w_default)
-        return w_default
+    return w_dict.setdefault(w_key, w_default)
 
 def dict_pop__DictMulti_ANY(space, w_dict, w_key, defaults_w):
     len_defaults = len(defaults_w)

diff --git a/pypy/translator/backendopt/test/test_inline.py b/pypy/translator/backendopt/test/test_inline.py
--- a/pypy/translator/backendopt/test/test_inline.py
+++ b/pypy/translator/backendopt/test/test_inline.py
@@ -1,7 +1,7 @@
 # XXX clean up these tests to use more uniform helpers
 import py
 import os
-from pypy.objspace.flow.model import traverse, Block, Link, Variable, Constant
+from pypy.objspace.flow.model import Block, Link, Variable, Constant
 from pypy.objspace.flow.model import last_exception, checkgraph
 from pypy.translator.backendopt import canraise
 from pypy.translator.backendopt.inline import simple_inline_function, CannotInline
@@ -20,29 +20,27 @@
 from pypy.translator.backendopt import removenoops
 from pypy.objspace.flow.model import summary
 
-def no_missing_concretetype(node):
-    if isinstance(node, Block):
-        for v in node.inputargs:
-            assert hasattr(v, 'concretetype')
-        for op in node.operations:
-            for v in op.args:
-                assert hasattr(v, 'concretetype')
-            assert hasattr(op.result, 'concretetype')
-    if isinstance(node, Link):
-        if node.exitcase is not None:
-            assert hasattr(node, 'llexitcase')
-        for v in node.args:
-            assert hasattr(v, 'concretetype')
-        if isinstance(node.last_exception, (Variable, Constant)):
-            assert hasattr(node.last_exception, 'concretetype')
-        if isinstance(node.last_exc_value, (Variable, Constant)):
-            assert hasattr(node.last_exc_value, 'concretetype')
-
 def sanity_check(t):
     # look for missing '.concretetype'
     for graph in t.graphs:
         checkgraph(graph)
-        traverse(no_missing_concretetype, graph)
+        for node in graph.iterblocks():
+            for v in node.inputargs:
+                assert hasattr(v, 'concretetype')
+            for op in node.operations:
+                for v in op.args:
+                    assert hasattr(v, 'concretetype')
+                assert hasattr(op.result, 'concretetype')
+        for node in graph.iterlinks():
+            if node.exitcase is not None:
+                assert hasattr(node, 'llexitcase')
+            for v in node.args:
+                assert hasattr(v, 'concretetype')
+            if isinstance(node.last_exception, (Variable, Constant)):
+                assert hasattr(node.last_exception, 'concretetype')
+            if isinstance(node.last_exc_value, (Variable, Constant)):
+                assert hasattr(node.last_exc_value, 'concretetype')
+
 
 class CustomError1(Exception):
     def __init__(self):

diff --git a/lib_pypy/pyrepl/tests/bugs.py b/lib_pypy/pyrepl/tests/bugs.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/tests/bugs.py
@@ -0,0 +1,36 @@
+#   Copyright 2000-2004 Michael Hudson-Doyle <micahel at gmail.com>
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+from pyrepl.console import Event
+from pyrepl.tests.infrastructure import ReaderTestCase, EA, run_testcase
+
+# this test case should contain as-verbatim-as-possible versions of
+# (applicable) bug reports
+
+class BugsTestCase(ReaderTestCase):
+
+    def test_transpose_at_start(self):
+        self.run_test([( 'transpose', [EA, '']),
+                       ( 'accept',    [''])])
+
+def test():
+    run_testcase(BugsTestCase)
+
+if __name__ == '__main__':
+    test()

diff --git a/pypy/rpython/rint.py b/pypy/rpython/rint.py
--- a/pypy/rpython/rint.py
+++ b/pypy/rpython/rint.py
@@ -212,52 +212,48 @@
         # cpython, and rpython, assumed that integer division truncates
         # towards -infinity.  however, in C99 and most (all?) other
         # backends, integer division truncates towards 0.  so assuming
-        # that, we can generate scary code that applies the necessary
+        # that, we call a helper function that applies the necessary
         # correction in the right cases.
-        # paper and pencil are encouraged for this :)
-
-        from pypy.rpython.rbool import bool_repr
-        assert isinstance(repr.lowleveltype, Number)
-        c_zero = inputconst(repr.lowleveltype, repr.lowleveltype._default)
 
         op = func.split('_', 1)[0]
 
         if op == 'floordiv':
-            # return (x/y) - (((x^y)<0)&((x%y)!=0));
-            v_xor = hop.genop(prefix + 'xor', vlist,
-                            resulttype=repr)
-            v_xor_le = hop.genop(prefix + 'lt', [v_xor, c_zero],
-                                 resulttype=Bool)
-            v_xor_le = hop.llops.convertvar(v_xor_le, bool_repr, repr)
-            v_mod = hop.genop(prefix + 'mod', vlist,
-                            resulttype=repr)
-            v_mod_ne = hop.genop(prefix + 'ne', [v_mod, c_zero],
-                               resulttype=Bool)
-            v_mod_ne = hop.llops.convertvar(v_mod_ne, bool_repr, repr)
-            v_corr = hop.genop(prefix + 'and', [v_xor_le, v_mod_ne],
-                             resulttype=repr)
-            v_res = hop.genop(prefix + 'sub', [v_res, v_corr],
-                              resulttype=repr)
+            llfunc = globals()['ll_correct_' + prefix + 'floordiv']
+            v_res = hop.gendirectcall(llfunc, vlist[0], vlist[1], v_res)
         elif op == 'mod':
-            # return r + y*(((x^y)<0)&(r!=0));
-            v_xor = hop.genop(prefix + 'xor', vlist,
-                            resulttype=repr)
-            v_xor_le = hop.genop(prefix + 'lt', [v_xor, c_zero],
-                               resulttype=Bool)
-            v_xor_le = hop.llops.convertvar(v_xor_le, bool_repr, repr)
-            v_mod_ne = hop.genop(prefix + 'ne', [v_res, c_zero],
-                               resulttype=Bool)
-            v_mod_ne = hop.llops.convertvar(v_mod_ne, bool_repr, repr)
-            v_corr1 = hop.genop(prefix + 'and', [v_xor_le, v_mod_ne],
-                             resulttype=repr)
-            v_corr = hop.genop(prefix + 'mul', [v_corr1, vlist[1]],
-                             resulttype=repr)
-            v_res = hop.genop(prefix + 'add', [v_res, v_corr],
-                              resulttype=repr)
+            llfunc = globals()['ll_correct_' + prefix + 'mod']
+            v_res = hop.gendirectcall(llfunc, vlist[1], v_res)
+
     v_res = hop.llops.convertvar(v_res, repr, r_result)
     return v_res
 
 
+INT_BITS_1 = r_int.BITS - 1
+LLONG_BITS_1 = r_longlong.BITS - 1
+
+def ll_correct_int_floordiv(x, y, r):
+    p = r * y
+    if y < 0: u = p - x
+    else:     u = x - p
+    return r + (u >> INT_BITS_1)
+
+def ll_correct_llong_floordiv(x, y, r):
+    p = r * y
+    if y < 0: u = p - x
+    else:     u = x - p
+    return r + (u >> LLONG_BITS_1)
+
+def ll_correct_int_mod(y, r):
+    if y < 0: u = -r
+    else:     u = r
+    return r + (y & (u >> INT_BITS_1))
+
+def ll_correct_llong_mod(y, r):
+    if y < 0: u = -r
+    else:     u = r
+    return r + (y & (u >> LLONG_BITS_1))
+
+
 #Helper functions for comparisons
 
 def _rtype_compare_template(hop, func):

diff --git a/pypy/tool/jitlogparser/module_finder.py b/pypy/tool/jitlogparser/module_finder.py
--- a/pypy/tool/jitlogparser/module_finder.py
+++ b/pypy/tool/jitlogparser/module_finder.py
@@ -6,7 +6,7 @@
     more = [code]
     while more:
         next = more.pop()
-        res[next.co_firstlineno] = next
+        res[(next.co_firstlineno, next.co_name)] = next
         more += [co for co in next.co_consts
                  if isinstance(co, types.CodeType)]
     return res

diff --git a/pypy/module/imp/__init__.py b/pypy/module/imp/__init__.py
--- a/pypy/module/imp/__init__.py
+++ b/pypy/module/imp/__init__.py
@@ -19,6 +19,7 @@
         'load_module':     'interp_imp.load_module',
         'load_source':     'interp_imp.load_source',
         'load_compiled':   'interp_imp.load_compiled',
+        'load_dynamic':    'interp_imp.load_dynamic',
         '_run_compiled_module': 'interp_imp._run_compiled_module',   # pypy
         '_getimporter':    'importing._getimporter',                 # pypy
         #'run_module':      'interp_imp.run_module',
@@ -36,7 +37,6 @@
         }
 
     appleveldefs = {
-        'load_dynamic':    'app_imp.load_dynamic',
         }
 
     def __init__(self, space, *args):

diff --git a/pypy/translator/oosupport/test_template/builtin.py b/pypy/translator/oosupport/test_template/builtin.py
--- a/pypy/translator/oosupport/test_template/builtin.py
+++ b/pypy/translator/oosupport/test_template/builtin.py
@@ -227,6 +227,17 @@
         assert res == ord('a')
 
 
+    def test_rlocale(self):
+        from pypy.rlib.rlocale import isupper, islower, isalpha, isalnum, tolower
+        def fn():
+            assert isupper(ord("A"))
+            assert islower(ord("a"))
+            assert not isalpha(ord(" "))
+            assert isalnum(ord("1"))
+            assert tolower(ord("A")) == ord("a")
+        self.interpret(fn, [])
+
+
 class BaseTestTime(llBaseTestTime):
 
     def test_time_clock(self):

diff --git a/pypy/translator/goal/targetrpystonedalone.py b/pypy/translator/goal/targetrpystonedalone.py
--- a/pypy/translator/goal/targetrpystonedalone.py
+++ b/pypy/translator/goal/targetrpystonedalone.py
@@ -2,11 +2,11 @@
 from pypy.translator.test import rpystone
 from pypy.translator.goal import richards
 import pypy.interpreter.gateway # needed before sys, order of imports !!!
-from pypy.module.sys.version import svn_revision
+from pypy.tool.version import get_repo_version_info
 
 # __________  Entry point  __________
 
-VERSION = svn_revision()
+VERSION = get_repo_version_info()[2]
 
 # note that we have %f but no length specifiers in RPython
 

diff --git a/pypy/module/signal/interp_signal.py b/pypy/module/signal/interp_signal.py
--- a/pypy/module/signal/interp_signal.py
+++ b/pypy/module/signal/interp_signal.py
@@ -146,6 +146,15 @@
                     self.pending_signals[n] = None
                     self.reissue_signal_action.fire_after_thread_switch()
 
+    def set_interrupt(self):
+        "Simulates the effect of a SIGINT signal arriving"
+        n = cpy_signal.SIGINT
+        if self.reissue_signal_action is None:
+            self.report_signal(n)
+        else:
+            self.pending_signals[n] = None
+            self.reissue_signal_action.fire_after_thread_switch()
+
     def report_signal(self, n):
         try:
             w_handler = self.handlers_w[n]

diff --git a/pypy/translator/jvm/opcodes.py b/pypy/translator/jvm/opcodes.py
--- a/pypy/translator/jvm/opcodes.py
+++ b/pypy/translator/jvm/opcodes.py
@@ -106,6 +106,10 @@
     'debug_catch_exception':    Ignore,
     'debug_reraise_traceback':  Ignore,
     'debug_print_traceback':    Ignore,
+    'debug_start':              Ignore,
+    'debug_stop':               Ignore,
+    'debug_print':              Ignore,
+    'keepalive':                Ignore,
 
     # __________ numeric operations __________
 
@@ -144,6 +148,7 @@
     'int_xor_ovf':              jvm.IXOR,
     'int_floordiv_ovf_zer':     jvm.IFLOORDIVZEROVF,
     'int_mod_ovf_zer':          _check_zer(jvm.IREMOVF),
+    'int_between':              jvm.PYPYINTBETWEEN,
 
     'uint_invert':              'bitwise_negate',
 
@@ -185,8 +190,8 @@
     'llong_mod_zer':            _check_zer(jvm.LREM),
     'llong_and':                jvm.LAND,
     'llong_or':                 jvm.LOR,
-    'llong_lshift':             [PushAllArgs, jvm.L2I, jvm.LSHL, StoreResult],
-    'llong_rshift':             [PushAllArgs, jvm.L2I, jvm.LSHR, StoreResult],
+    'llong_lshift':             [PushAllArgs, jvm.LSHL, StoreResult],
+    'llong_rshift':             [PushAllArgs, jvm.LSHR, StoreResult],
     'llong_xor':                jvm.LXOR,
     'llong_floordiv_ovf':       jvm.LFLOORDIVOVF,
     'llong_floordiv_ovf_zer':   jvm.LFLOORDIVZEROVF,    
@@ -202,9 +207,11 @@
     'ullong_truediv':           None, # TODO
     'ullong_floordiv':          jvm.LDIV, # valid?
     'ullong_mod':               jvm.PYPYULONGMOD,
-    'ullong_lshift':            [PushAllArgs, jvm.L2I, jvm.LSHL, StoreResult],
-    'ullong_rshift':            [PushAllArgs, jvm.L2I, jvm.LUSHR, StoreResult],
+    'ullong_lshift':            [PushAllArgs, jvm.LSHL, StoreResult],
+    'ullong_rshift':            [PushAllArgs, jvm.LUSHR, StoreResult],
     'ullong_mod_zer':           jvm.PYPYULONGMOD,
+    'ullong_or':                jvm.LOR,
+    'ullong_and':               jvm.LAND,
 
     # when casting from bool we want that every truth value is casted
     # to 1: we can't simply DoNothing, because the CLI stack could
@@ -227,5 +234,8 @@
     'cast_float_to_uint':       jvm.PYPYDOUBLETOUINT,
     'truncate_longlong_to_int': jvm.L2I,
     'cast_longlong_to_float':   jvm.L2D,
+    'cast_float_to_ulonglong':  jvm.PYPYDOUBLETOULONG,
+    'cast_ulonglong_to_float':  jvm.PYPYULONGTODOUBLE,
     'cast_primitive':           [PushAllArgs, CastPrimitive, StoreResult],
+    'force_cast':               [PushAllArgs, CastPrimitive, StoreResult],
 })

diff --git a/pypy/interpreter/pyframe.py b/pypy/interpreter/pyframe.py
--- a/pypy/interpreter/pyframe.py
+++ b/pypy/interpreter/pyframe.py
@@ -46,15 +46,15 @@
     w_f_trace                = None
     # For tracing
     instr_lb                 = 0
-    instr_ub                 = -1
-    instr_prev               = -1
+    instr_ub                 = 0
+    instr_prev_plus_one      = 0
     is_being_profiled        = False
 
     def __init__(self, space, code, w_globals, closure):
         self = hint(self, access_directly=True, fresh_virtualizable=True)
         assert isinstance(code, pycode.PyCode)
         self.pycode = code
-        eval.Frame.__init__(self, space, w_globals, code.co_nlocals)
+        eval.Frame.__init__(self, space, w_globals)
         self.valuestack_w = [None] * code.co_stacksize
         self.valuestackdepth = 0
         self.lastblock = None
@@ -63,7 +63,7 @@
         # regular functions always have CO_OPTIMIZED and CO_NEWLOCALS.
         # class bodies only have CO_NEWLOCALS.
         self.initialize_frame_scopes(closure, code)
-        self.fastlocals_w = [None]*self.numlocals
+        self.fastlocals_w = [None] * code.co_nlocals
         make_sure_not_resized(self.fastlocals_w)
         self.f_lineno = code.co_firstlineno
 
@@ -335,7 +335,7 @@
 
             w(self.instr_lb), #do we need these three (that are for tracing)
             w(self.instr_ub),
-            w(self.instr_prev),
+            w(self.instr_prev_plus_one),
             w_cells,
             ]
 
@@ -349,7 +349,7 @@
         args_w = space.unpackiterable(w_args)
         w_f_back, w_builtin, w_pycode, w_valuestack, w_blockstack, w_exc_value, w_tb,\
             w_globals, w_last_instr, w_finished, w_f_lineno, w_fastlocals, w_f_locals, \
-            w_f_trace, w_instr_lb, w_instr_ub, w_instr_prev, w_cells = args_w
+            w_f_trace, w_instr_lb, w_instr_ub, w_instr_prev_plus_one, w_cells = args_w
 
         new_frame = self
         pycode = space.interp_w(PyCode, w_pycode)
@@ -397,7 +397,7 @@
 
         new_frame.instr_lb = space.int_w(w_instr_lb)   #the three for tracing
         new_frame.instr_ub = space.int_w(w_instr_ub)
-        new_frame.instr_prev = space.int_w(w_instr_prev)
+        new_frame.instr_prev_plus_one = space.int_w(w_instr_prev_plus_one)
 
         self._setcellvars(cellvars)
         # XXX what if the frame is in another thread??
@@ -430,7 +430,10 @@
         """Initialize cellvars from self.fastlocals_w
         This is overridden in nestedscope.py"""
         pass
-    
+
+    def getfastscopelength(self):
+        return self.pycode.co_nlocals
+
     def getclosure(self):
         return None
 

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,12 +25,13 @@
 class Descr(history.AbstractDescr):
 
     def __init__(self, ofs, typeinfo, extrainfo=None, name=None,
-                 arg_types=None):
+                 arg_types=None, count_fields_if_immut=-1):
         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
 
     def get_arg_types(self):
         return self.arg_types
@@ -63,6 +64,9 @@
     def as_vtable_size_descr(self):
         return self
 
+    def count_fields_if_immutable(self):
+        return self.count_fields_if_immut
+
     def __lt__(self, other):
         raise TypeError("cannot use comparison on Descrs")
     def __le__(self, other):
@@ -109,12 +113,14 @@
         return False
 
     def getdescr(self, ofs, typeinfo='?', extrainfo=None, name=None,
-                 arg_types=None):
-        key = (ofs, typeinfo, extrainfo, name, arg_types)
+                 arg_types=None, count_fields_if_immut=-1):
+        key = (ofs, typeinfo, extrainfo, name, arg_types,
+               count_fields_if_immut)
         try:
             return self._descrs[key]
         except KeyError:
-            descr = Descr(ofs, typeinfo, extrainfo, name, arg_types)
+            descr = Descr(ofs, typeinfo, extrainfo, name, arg_types,
+                          count_fields_if_immut)
             self._descrs[key] = descr
             return descr
 
@@ -284,7 +290,8 @@
 
     def sizeof(self, S):
         assert not isinstance(S, lltype.Ptr)
-        return self.getdescr(symbolic.get_size(S))
+        count = heaptracker.count_fields_if_immutable(S)
+        return self.getdescr(symbolic.get_size(S), count_fields_if_immut=count)
 
 
 class LLtypeCPU(BaseCPU):

diff --git a/pypy/module/cpyext/typeobjectdefs.py b/pypy/module/cpyext/typeobjectdefs.py
--- a/pypy/module/cpyext/typeobjectdefs.py
+++ b/pypy/module/cpyext/typeobjectdefs.py
@@ -1,9 +1,8 @@
 from pypy.rpython.lltypesystem import rffi, lltype
 from pypy.rpython.lltypesystem.lltype import Ptr, FuncType, Void
-from pypy.module.cpyext.api import cpython_struct, \
-    PyVarObjectFields, Py_ssize_t, Py_TPFLAGS_READYING, \
-    Py_TPFLAGS_READY, Py_TPFLAGS_HEAPTYPE, \
-    PyTypeObject, PyTypeObjectPtr, PyBufferProcs, FILEP
+from pypy.module.cpyext.api import (cpython_struct, Py_ssize_t, Py_ssize_tP,
+    PyVarObjectFields, PyTypeObject, PyTypeObjectPtr, FILEP,
+    Py_TPFLAGS_READYING, Py_TPFLAGS_READY, Py_TPFLAGS_HEAPTYPE)
 from pypy.module.cpyext.pyobject import PyObject, make_ref, from_ref
 from pypy.module.cpyext.modsupport import PyMethodDef
 
@@ -55,6 +54,14 @@
 wrapperfunc = P(FT([PyO, PyO, rffi.VOIDP], PyO))
 wrapperfunc_kwds = P(FT([PyO, PyO, rffi.VOIDP, PyO], PyO))
 
+readbufferproc = P(FT([PyO, Py_ssize_t, rffi.VOIDPP], Py_ssize_t))
+writebufferproc = P(FT([PyO, Py_ssize_t, rffi.VOIDPP], Py_ssize_t))
+segcountproc = P(FT([PyO, Py_ssize_tP], Py_ssize_t))
+charbufferproc = P(FT([PyO, Py_ssize_t, rffi.CCHARPP], Py_ssize_t))
+## We don't support new buffer interface for now
+getbufferproc = rffi.VOIDP
+releasebufferproc = rffi.VOIDP
+
 
 PyGetSetDef = cpython_struct("PyGetSetDef", (
     ("name", rffi.CCHARP),
@@ -127,7 +134,6 @@
     ("mp_ass_subscript", objobjargproc),
 ))
 
-"""
 PyBufferProcs = cpython_struct("PyBufferProcs", (
     ("bf_getreadbuffer", readbufferproc),
     ("bf_getwritebuffer", writebufferproc),
@@ -136,7 +142,6 @@
     ("bf_getbuffer", getbufferproc),
     ("bf_releasebuffer", releasebufferproc),
 ))
-"""
 
 PyMemberDef = cpython_struct("PyMemberDef", (
     ("name", rffi.CCHARP),

diff --git a/lib_pypy/pyrepl/keymap.py b/lib_pypy/pyrepl/keymap.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/keymap.py
@@ -0,0 +1,186 @@
+#   Copyright 2000-2008 Michael Hudson-Doyle <micahel at gmail.com>
+#                       Armin Rigo
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+"""
+functions for parsing keyspecs
+
+Support for turning keyspecs into appropriate sequences.
+
+pyrepl uses it's own bastardized keyspec format, which is meant to be
+a strict superset of readline's \"KEYSEQ\" format (which is to say
+that if you can come up with a spec readline accepts that this
+doesn't, you've found a bug and should tell me about it).
+
+Note that this is the `\\C-o' style of readline keyspec, not the
+`Control-o' sort.
+
+A keyspec is a string representing a sequence of keypresses that can
+be bound to a command.
+
+All characters other than the backslash represent themselves.  In the
+traditional manner, a backslash introduces a escape sequence.
+
+The extension to readline is that the sequence \\<KEY> denotes the
+sequence of charaters produced by hitting KEY.
+
+Examples:
+
+`a'     - what you get when you hit the `a' key
+`\\EOA'  - Escape - O - A (up, on my terminal)
+`\\<UP>' - the up arrow key
+`\\<up>' - ditto (keynames are case insensitive)
+`\\C-o', `\\c-o'  - control-o
+`\\M-.'  - meta-period
+`\\E.'   - ditto (that's how meta works for pyrepl)
+`\\<tab>', `\\<TAB>', `\\t', `\\011', '\\x09', '\\X09', '\\C-i', '\\C-I'
+   - all of these are the tab character.  Can you think of any more?
+"""
+
+_escapes = {
+    '\\':'\\',
+    "'":"'",
+    '"':'"',
+    'a':'\a',
+    'b':'\h',
+    'e':'\033',
+    'f':'\f',
+    'n':'\n',
+    'r':'\r',
+    't':'\t',
+    'v':'\v'
+    }
+
+_keynames = {
+    'backspace': 'backspace',
+    'delete':    'delete',
+    'down':      'down',
+    'end':       'end',
+    'enter':     '\r',
+    'escape':    '\033',
+    'f1' : 'f1',   'f2' : 'f2',   'f3' : 'f3',   'f4' : 'f4',
+    'f5' : 'f5',   'f6' : 'f6',   'f7' : 'f7',   'f8' : 'f8',
+    'f9' : 'f9',   'f10': 'f10',  'f11': 'f11',  'f12': 'f12',
+    'f13': 'f13',  'f14': 'f14',  'f15': 'f15',  'f16': 'f16',
+    'f17': 'f17',  'f18': 'f18',  'f19': 'f19',  'f20': 'f20',
+    'home':      'home',
+    'insert':    'insert',
+    'left':      'left',
+    'page down': 'page down',
+    'page up':   'page up',
+    'return':    '\r',
+    'right':     'right',
+    'space':     ' ',
+    'tab':       '\t',
+    'up':        'up',
+    }
+
+class KeySpecError(Exception):
+    pass
+
+def _parse_key1(key, s):
+    ctrl = 0
+    meta = 0
+    ret = ''
+    while not ret and s < len(key):
+        if key[s] == '\\':
+            c = key[s+1].lower()
+            if _escapes.has_key(c):
+                ret = _escapes[c]
+                s += 2
+            elif c == "c":
+                if key[s + 2] != '-':
+                    raise KeySpecError, \
+                              "\\C must be followed by `-' (char %d of %s)"%(
+                        s + 2, repr(key))
+                if ctrl:
+                    raise KeySpecError, "doubled \\C- (char %d of %s)"%(
+                        s + 1, repr(key))
+                ctrl = 1
+                s += 3
+            elif c == "m":
+                if key[s + 2] != '-':
+                    raise KeySpecError, \
+                              "\\M must be followed by `-' (char %d of %s)"%(
+                        s + 2, repr(key))
+                if meta:
+                    raise KeySpecError, "doubled \\M- (char %d of %s)"%(
+                        s + 1, repr(key))
+                meta = 1
+                s += 3
+            elif c.isdigit():
+                n = key[s+1:s+4]
+                ret = chr(int(n, 8))
+                s += 4
+            elif c == 'x':
+                n = key[s+2:s+4]
+                ret = chr(int(n, 16))
+                s += 4
+            elif c == '<':
+                t = key.find('>', s)
+                if t == -1:
+                    raise KeySpecError, \
+                              "unterminated \\< starting at char %d of %s"%(
+                        s + 1, repr(key))                        
+                ret = key[s+2:t].lower()
+                if ret not in _keynames:
+                    raise KeySpecError, \
+                              "unrecognised keyname `%s' at char %d of %s"%(
+                        ret, s + 2, repr(key))
+                ret = _keynames[ret]
+                s = t + 1
+            else:
+                raise KeySpecError, \
+                          "unknown backslash escape %s at char %d of %s"%(
+                    `c`, s + 2, repr(key))
+        else:
+            ret = key[s]
+            s += 1
+    if ctrl:
+        if len(ret) > 1:
+            raise KeySpecError, "\\C- must be followed by a character"
+        ret = chr(ord(ret) & 0x1f)   # curses.ascii.ctrl()
+    if meta:
+        ret = ['\033', ret]
+    else:
+        ret = [ret]
+    return ret, s
+
+def parse_keys(key):
+    s = 0
+    r = []
+    while s < len(key):
+        k, s = _parse_key1(key, s)
+        r.extend(k)
+    return r
+
+def compile_keymap(keymap, empty=''):
+    r = {}
+    for key, value in keymap.items():
+        r.setdefault(key[0], {})[key[1:]] = value
+    for key, value in r.items():
+        if empty in value:
+            if len(value) <> 1:
+                raise KeySpecError, \
+                      "key definitions for %s clash"%(value.values(),)
+            else:
+                r[key] = value[empty]
+        else:
+            r[key] = compile_keymap(value, empty)
+    return r

diff --git a/pypy/translator/platform/posix.py b/pypy/translator/platform/posix.py
--- a/pypy/translator/platform/posix.py
+++ b/pypy/translator/platform/posix.py
@@ -113,11 +113,16 @@
         m.eci = eci
 
         def pypyrel(fpath):
-            rel = py.path.local(fpath).relto(pypypath)
+            lpath = py.path.local(fpath)
+            rel = lpath.relto(pypypath)
             if rel:
                 return os.path.join('$(PYPYDIR)', rel)
-            else:
-                return fpath
+            m_dir = m.makefile_dir
+            if m_dir == lpath:
+                return '.'
+            if m_dir.dirpath() == lpath:
+                return '..'
+            return fpath
 
         rel_cfiles = [m.pathrel(cfile) for cfile in cfiles]
         rel_ofiles = [rel_cfile[:-2]+'.o' for rel_cfile in rel_cfiles]

diff --git a/pypy/module/_winreg/interp_winreg.py b/pypy/module/_winreg/interp_winreg.py
--- a/pypy/module/_winreg/interp_winreg.py
+++ b/pypy/module/_winreg/interp_winreg.py
@@ -261,7 +261,8 @@
 
                 if ret != 0:
                     raiseWindowsError(space, ret, 'RegQueryValue')
-                return space.wrap(rffi.charp2strn(buf, bufsize_p[0] - 1))
+                length = intmask(bufsize_p[0] - 1)
+                return space.wrap(rffi.charp2strn(buf, length))
 
 def convert_to_regdata(space, w_value, typ):
     buf = None
@@ -445,9 +446,10 @@
                         continue
                     if ret != 0:
                         raiseWindowsError(space, ret, 'RegQueryValueEx')
+                    length = intmask(retDataSize[0])
                     return space.newtuple([
                         convert_from_regdata(space, databuf,
-                                             retDataSize[0], retType[0]),
+                                             length, retType[0]),
                         space.wrap(retType[0]),
                         ])
 
@@ -595,11 +597,11 @@
                             if ret != 0:
                                 raiseWindowsError(space, ret, 'RegEnumValue')
 
+                            length = intmask(retDataSize[0])
                             return space.newtuple([
                                 space.wrap(rffi.charp2str(valuebuf)),
                                 convert_from_regdata(space, databuf,
-                                                     retDataSize[0],
-                                                     retType[0]),
+                                                     length, retType[0]),
                                 space.wrap(retType[0]),
                                 ])
 

diff --git a/pypy/module/cpyext/include/longintrepr.h b/pypy/module/cpyext/include/longintrepr.h
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/include/longintrepr.h
@@ -0,0 +1,1 @@
+/* empty */

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
@@ -3,8 +3,102 @@
 from pypy.jit.metainterp.resoperation import rop, ResOperation
 from pypy.rlib.objectmodel import we_are_translated
 from pypy.jit.metainterp.jitexc import JitException
+from pypy.jit.metainterp.optimizeopt.optimizer import Optimization
 
-from pypy.jit.metainterp.optimizeopt.optimizer import Optimization
+
+class CachedField(object):
+    def __init__(self):
+        # Cache information for a field descr.  It can be in one
+        # of two states:
+        #
+        #   1. 'cached_fields' is a dict mapping OptValues of structs
+        #      to OptValues of fields.  All fields on-heap are
+        #      synchronized with the values stored in the cache.
+        #
+        #   2. we just did one setfield, which is delayed (and thus
+        #      not synchronized).  'lazy_setfield' is the delayed
+        #      ResOperation.  In this state, 'cached_fields' contains
+        #      out-of-date information.  More precisely, the field
+        #      value pending in the ResOperation is *not* visible in
+        #      'cached_fields'.
+        #
+        self._cached_fields = {}
+        self._lazy_setfield = None
+        self._lazy_setfield_registered = False
+
+    def do_setfield(self, optheap, op):
+        # Update the state with the SETFIELD_GC operation 'op'.
+        structvalue = optheap.getvalue(op.getarg(0))
+        fieldvalue  = optheap.getvalue(op.getarg(1))
+        if self.possible_aliasing(optheap, structvalue):
+            self.force_lazy_setfield(optheap)
+            assert not self.possible_aliasing(optheap, structvalue)
+        cached_fieldvalue = self._cached_fields.get(structvalue, None)
+        if cached_fieldvalue is not fieldvalue:
+            # common case: store the 'op' as lazy_setfield, and register
+            # myself in the optheap's _lazy_setfields list
+            self._lazy_setfield = op
+            if not self._lazy_setfield_registered:
+                optheap._lazy_setfields.append(self)
+                self._lazy_setfield_registered = True
+        else:
+            # this is the case where the pending setfield ends up
+            # storing precisely the value that is already there,
+            # as proved by 'cached_fields'.  In this case, we don't
+            # need any _lazy_setfield: the heap value is already right.
+            # Note that this may reset to None a non-None lazy_setfield,
+            # cancelling its previous effects with no side effect.
+            self._lazy_setfield = None
+
+    def possible_aliasing(self, optheap, structvalue):
+        # If lazy_setfield is set and contains a setfield on a different
+        # structvalue, then we are annoyed, because it may point to either
+        # the same or a different structure at runtime.
+        return (self._lazy_setfield is not None
+                and (optheap.getvalue(self._lazy_setfield.getarg(0))
+                     is not structvalue))
+
+    def getfield_from_cache(self, optheap, structvalue):
+        # Returns the up-to-date field's value, or None if not cached.
+        if self.possible_aliasing(optheap, structvalue):
+            self.force_lazy_setfield(optheap)
+        if self._lazy_setfield is not None:
+            op = self._lazy_setfield
+            assert optheap.getvalue(op.getarg(0)) is structvalue
+            return optheap.getvalue(op.getarg(1))
+        else:
+            return self._cached_fields.get(structvalue, None)
+
+    def remember_field_value(self, structvalue, fieldvalue):
+        assert self._lazy_setfield is None
+        self._cached_fields[structvalue] = fieldvalue
+
+    def force_lazy_setfield(self, optheap):
+        op = self._lazy_setfield
+        if op is not None:
+            # This is the way _lazy_setfield is usually reset to None.
+            # Now we clear _cached_fields, because actually doing the
+            # setfield might impact any of the stored result (because of
+            # possible aliasing).
+            self._cached_fields.clear()
+            self._lazy_setfield = None
+            optheap.next_optimization.propagate_forward(op)
+            # Once it is done, we can put at least one piece of information
+            # back in the cache: the value of this particular structure's
+            # field.
+            structvalue = optheap.getvalue(op.getarg(0))
+            fieldvalue  = optheap.getvalue(op.getarg(1))
+            self.remember_field_value(structvalue, fieldvalue)
+
+    def get_reconstructed(self, optimizer, valuemap):
+        assert self._lazy_setfield is None
+        cf = CachedField()
+        for structvalue, fieldvalue in self._cached_fields.iteritems():
+            structvalue2 = structvalue.get_reconstructed(optimizer, valuemap)
+            fieldvalue2  = fieldvalue .get_reconstructed(optimizer, valuemap)
+            cf._cached_fields[structvalue2] = fieldvalue2
+        return cf
+
 
 class CachedArrayItems(object):
     def __init__(self):
@@ -20,40 +114,23 @@
     """Cache repeated heap accesses"""
     
     def __init__(self):
-        # cached fields:  {descr: {OptValue_instance: OptValue_fieldvalue}}
+        # cached fields:  {descr: CachedField}
         self.cached_fields = {}
-        self.known_heap_fields = {}
+        self._lazy_setfields = []
         # cached array items:  {descr: CachedArrayItems}
         self.cached_arrayitems = {}
-        # lazily written setfields (at most one per descr):  {descr: op}
-        self.lazy_setfields = {}
-        self.lazy_setfields_descrs = []     # keys (at least) of previous dict
 
     def reconstruct_for_next_iteration(self, optimizer, valuemap):
         new = OptHeap()
 
         if True:
             self.force_all_lazy_setfields()
-            assert not self.lazy_setfields_descrs
-            assert not self.lazy_setfields
         else:
-            new.lazy_setfields_descrs = self.lazy_setfields_descrs
-            new.lazy_setfields = self.lazy_setfields
+            assert 0   # was: new.lazy_setfields = self.lazy_setfields
         
         for descr, d in self.cached_fields.items():
-            newd = {}
-            new.cached_fields[descr] = newd
-            for value, fieldvalue in d.items():
-                newd[value.get_reconstructed(optimizer, valuemap)] = \
-                                       fieldvalue.get_reconstructed(optimizer, valuemap)
-            
-        for descr, d in self.known_heap_fields.items():
-            newd = {}
-            new.known_heap_fields[descr] = newd
-            for value, fieldvalue in d.items():
-                newd[value.get_reconstructed(optimizer, valuemap)] = \
-                                       fieldvalue.get_reconstructed(optimizer, valuemap)
-            
+            new.cached_fields[descr] = d.get_reconstructed(optimizer, valuemap)
+
         new.cached_arrayitems = {}
         for descr, d in self.cached_arrayitems.items():
             newd = {}
@@ -74,30 +151,16 @@
         return new
 
     def clean_caches(self):
+        del self._lazy_setfields[:]
         self.cached_fields.clear()
-        self.known_heap_fields.clear()
         self.cached_arrayitems.clear()
 
-    def cache_field_value(self, descr, value, fieldvalue, write=False):
-        if write:
-            # when seeing a setfield, we have to clear the cache for the same
-            # field on any other structure, just in case they are aliasing
-            # each other
-            d = self.cached_fields[descr] = {}
-        else:
-            d = self.cached_fields.setdefault(descr, {})
-        d[value] = fieldvalue
-
-    def read_cached_field(self, descr, value):
-        # XXX self.cached_fields and self.lazy_setfields should probably
-        # be merged somehow
-        d = self.cached_fields.get(descr, None)
-        if d is None:
-            op = self.lazy_setfields.get(descr, None)
-            if op is None:
-                return None
-            return self.getvalue(op.getarg(1))
-        return d.get(value, None)
+    def field_cache(self, descr):
+        try:
+            cf = self.cached_fields[descr]
+        except KeyError:
+            cf = self.cached_fields[descr] = CachedField()
+        return cf
 
     def cache_arrayitem_value(self, descr, value, indexvalue, fieldvalue, write=False):
         d = self.cached_arrayitems.get(descr, None)
@@ -157,11 +220,15 @@
             self.optimizer.pendingfields = self.force_lazy_setfields_for_guard()
             return
         opnum = op.getopnum()
-        if (opnum == rop.SETFIELD_GC or
-            opnum == rop.SETFIELD_RAW or
-            opnum == rop.SETARRAYITEM_GC or
-            opnum == rop.SETARRAYITEM_RAW or
-            opnum == rop.DEBUG_MERGE_POINT):
+        if (opnum == rop.SETFIELD_GC or        # handled specially
+            opnum == rop.SETFIELD_RAW or       # no effect on GC struct/array
+            opnum == rop.SETARRAYITEM_GC or    # handled specially
+            opnum == rop.SETARRAYITEM_RAW or   # no effect on GC struct
+            opnum == rop.STRSETITEM or         # no effect on GC struct/array
+            opnum == rop.UNICODESETITEM or     # no effect on GC struct/array
+            opnum == rop.DEBUG_MERGE_POINT or  # no effect whatsoever
+            opnum == rop.COPYSTRCONTENT or     # no effect on GC struct/array
+            opnum == rop.COPYUNICODECONTENT):  # no effect on GC struct/array
             return
         assert opnum != rop.CALL_PURE
         if (opnum == rop.CALL or
@@ -180,8 +247,8 @@
                 for fielddescr in effectinfo.write_descrs_fields:
                     self.force_lazy_setfield(fielddescr)
                     try:
-                        del self.cached_fields[fielddescr]
-                        del self.known_heap_fields[fielddescr]
+                        cf = self.cached_fields[fielddescr]
+                        cf._cached_fields.clear()
                     except KeyError:
                         pass
                 for arraydescr in effectinfo.write_descrs_arrays:
@@ -195,10 +262,7 @@
                     # ^^^ we only need to force this field; the other fields
                     # of virtualref_info and virtualizable_info are not gcptrs.
                 return
-            self.force_all_lazy_setfields()
-        elif op.is_final() or (not we_are_translated() and
-                               op.getopnum() < 0):   # escape() operations
-            self.force_all_lazy_setfields()
+        self.force_all_lazy_setfields()
         self.clean_caches()
 
 
@@ -206,58 +270,54 @@
         assert value.is_constant()
         newvalue = self.getvalue(value.box)
         if value is not newvalue:
-            for d in self.cached_fields.values():
-                if value in d:
-                    d[newvalue] = d[value]
-        # FIXME: Update the other caches too?
-        
-        
-    def force_lazy_setfield(self, descr, before_guard=False):
+            for cf in self.cached_fields.itervalues():
+                if value in cf._cached_fields:
+                    cf._cached_fields[newvalue] = cf._cached_fields[value]
+
+    def force_lazy_setfield(self, descr):
         try:
-            op = self.lazy_setfields[descr]
+            cf = self.cached_fields[descr]
         except KeyError:
             return
-        del self.lazy_setfields[descr]
-        value = self.getvalue(op.getarg(0))
-        fieldvalue = self.getvalue(op.getarg(1))
-        try:
-            heapvalue = self.known_heap_fields[op.getdescr()][value]
-            if fieldvalue is heapvalue:
-                return
-        except KeyError:
-            pass
-        self.next_optimization.propagate_forward(op)
+        cf.force_lazy_setfield(self)
 
+    def fixup_guard_situation(self):
         # hackish: reverse the order of the last two operations if it makes
         # sense to avoid a situation like "int_eq/setfield_gc/guard_true",
         # which the backend (at least the x86 backend) does not handle well.
         newoperations = self.optimizer.newoperations
-        if before_guard and len(newoperations) >= 2:
-            lastop = newoperations[-1]
-            prevop = newoperations[-2]
-            # - is_comparison() for cases like "int_eq/setfield_gc/guard_true"
-            # - CALL_MAY_FORCE: "call_may_force/setfield_gc/guard_not_forced"
-            # - is_ovf(): "int_add_ovf/setfield_gc/guard_no_overflow"
-            opnum = prevop.getopnum()
-            lastop_args = lastop.getarglist()
-            if ((prevop.is_comparison() or opnum == rop.CALL_MAY_FORCE
-                 or opnum == rop.CALL_RELEASE_GIL or prevop.is_ovf())
-                and prevop.result not in lastop_args):
-                newoperations[-2] = lastop
-                newoperations[-1] = prevop
+        if len(newoperations) < 2:
+            return
+        lastop = newoperations[-1]
+        if (lastop.getopnum() != rop.SETFIELD_GC and
+            lastop.getopnum() != rop.SETARRAYITEM_GC):
+            return
+        # - is_comparison() for cases like "int_eq/setfield_gc/guard_true"
+        # - CALL_MAY_FORCE: "call_may_force/setfield_gc/guard_not_forced"
+        # - is_ovf(): "int_add_ovf/setfield_gc/guard_no_overflow"
+        prevop = newoperations[-2]
+        opnum = prevop.getopnum()
+        if not (prevop.is_comparison() or opnum == rop.CALL_MAY_FORCE
+                or prevop.is_ovf()):
+            return
+        if prevop.result in lastop.getarglist():
+            return
+        newoperations[-2] = lastop
+        newoperations[-1] = prevop
 
     def force_all_lazy_setfields(self):
-        if len(self.lazy_setfields_descrs) > 0:
-            for descr in self.lazy_setfields_descrs:
-                self.force_lazy_setfield(descr)
-            del self.lazy_setfields_descrs[:]
+        for cf in self._lazy_setfields:
+            if not we_are_translated():
+                assert cf in self.cached_fields.values()
+            cf.force_lazy_setfield(self)
 
     def force_lazy_setfields_for_guard(self):
         pendingfields = []
-        for descr in self.lazy_setfields_descrs:
-            try:
-                op = self.lazy_setfields[descr]
-            except KeyError:
+        for cf in self._lazy_setfields:
+            if not we_are_translated():
+                assert cf in self.cached_fields.values()
+            op = cf._lazy_setfield
+            if op is None:
                 continue
             # the only really interesting case that we need to handle in the
             # guards' resume data is that of a virtual object that is stored
@@ -267,41 +327,27 @@
             fieldvalue = self.getvalue(op.getarg(1))
             if fieldvalue.is_virtual():
                 # this is the case that we leave to resume.py
-                pendingfields.append((descr, value.box,
+                pendingfields.append((op.getdescr(), value.box,
                                       fieldvalue.get_key_box()))
             else:
-                self.force_lazy_setfield(descr, before_guard=True)
+                cf.force_lazy_setfield(self)
+                self.fixup_guard_situation()
         return pendingfields
 
-    def force_lazy_setfield_if_necessary(self, op, value, write=False):
-        try:
-            op1 = self.lazy_setfields[op.getdescr()]
-        except KeyError:
-            if write:
-                self.lazy_setfields_descrs.append(op.getdescr())
-        else:
-            if self.getvalue(op1.getarg(0)) is not value:
-                self.force_lazy_setfield(op.getdescr())
-
     def optimize_GETFIELD_GC(self, op):
-        value = self.getvalue(op.getarg(0))
-        self.force_lazy_setfield_if_necessary(op, value)
-        # check if the field was read from another getfield_gc just before
-        # or has been written to recently
-        fieldvalue = self.read_cached_field(op.getdescr(), value)
+        structvalue = self.getvalue(op.getarg(0))
+        cf = self.field_cache(op.getdescr())
+        fieldvalue = cf.getfield_from_cache(self, structvalue)
         if fieldvalue is not None:
             self.make_equal_to(op.result, fieldvalue)
             return
         # default case: produce the operation
-        value.ensure_nonnull()
+        structvalue.ensure_nonnull()
         ###self.optimizer.optimize_default(op)
         self.emit_operation(op)
         # then remember the result of reading the field
         fieldvalue = self.getvalue(op.result)
-        self.cache_field_value(op.getdescr(), value, fieldvalue)
-        # keep track of what's on the heap
-        d = self.known_heap_fields.setdefault(op.getdescr(), {})
-        d[value] = fieldvalue
+        cf.remember_field_value(structvalue, fieldvalue)
 
     def optimize_SETFIELD_GC(self, op):
         if self.has_pure_result(rop.GETFIELD_GC_PURE, [op.getarg(0)],
@@ -310,14 +356,8 @@
                      (op.getdescr().repr_of_descr()))
             raise BogusPureField
         #
-        value = self.getvalue(op.getarg(0))
-        fieldvalue = self.getvalue(op.getarg(1))
-        cached_fieldvalue = self.read_cached_field(op.getdescr(), value)
-        if fieldvalue is not cached_fieldvalue:
-            self.force_lazy_setfield_if_necessary(op, value, write=True)
-            self.lazy_setfields[op.getdescr()] = op
-            # remember the result of future reads of the field
-            self.cache_field_value(op.getdescr(), value, fieldvalue, write=True)
+        cf = self.field_cache(op.getdescr())
+        cf.do_setfield(self, op)
 
     def optimize_GETARRAYITEM_GC(self, op):
         value = self.getvalue(op.getarg(0))

diff --git a/pypy/module/cpyext/funcobject.py b/pypy/module/cpyext/funcobject.py
--- a/pypy/module/cpyext/funcobject.py
+++ b/pypy/module/cpyext/funcobject.py
@@ -14,6 +14,10 @@
     (("func_name", PyObject),)
 cpython_struct("PyFunctionObject", PyFunctionObjectFields, PyFunctionObjectStruct)
 
+PyCodeObjectStruct = lltype.ForwardReference()
+PyCodeObject = lltype.Ptr(PyCodeObjectStruct)
+cpython_struct("PyCodeObject", PyObjectFields, PyCodeObjectStruct)
+
 @bootstrap_function
 def init_functionobject(space):
     make_typedescr(Function.typedef,
@@ -65,7 +69,36 @@
     assert isinstance(w_method, Method)
     return borrow_from(w_method, w_method.w_class)
 
- at cpython_api([CONST_STRING, CONST_STRING, rffi.INT_real], PyObject)
+def unwrap_list_of_strings(space, w_list):
+    return [space.str_w(w_item) for w_item in space.fixedview(w_list)]
+
+ at cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real,
+              PyObject, PyObject, PyObject, PyObject, PyObject, PyObject,
+              PyObject, PyObject, rffi.INT_real, PyObject], PyCodeObject)
+def PyCode_New(space, argcount, nlocals, stacksize, flags,
+               w_code, w_consts, w_names, w_varnames, w_freevars, w_cellvars,
+               w_filename, w_funcname, firstlineno, w_lnotab):
+    """Return a new code object.  If you need a dummy code object to
+    create a frame, use PyCode_NewEmpty() instead.  Calling
+    PyCode_New() directly can bind you to a precise Python
+    version since the definition of the bytecode changes often."""
+    return space.wrap(PyCode(space,
+                             argcount=rffi.cast(lltype.Signed, argcount),
+                             nlocals=rffi.cast(lltype.Signed, nlocals),
+                             stacksize=rffi.cast(lltype.Signed, stacksize),
+                             flags=rffi.cast(lltype.Signed, flags),
+                             code=space.str_w(w_code),
+                             consts=space.fixedview(w_consts),
+                             names=unwrap_list_of_strings(space, w_names),
+                             varnames=unwrap_list_of_strings(space, w_varnames),
+                             filename=space.str_w(w_filename),
+                             name=space.str_w(w_funcname),
+                             firstlineno=rffi.cast(lltype.Signed, firstlineno),
+                             lnotab=space.str_w(w_lnotab),
+                             freevars=unwrap_list_of_strings(space, w_freevars),
+                             cellvars=unwrap_list_of_strings(space, w_cellvars)))
+
+ at cpython_api([CONST_STRING, CONST_STRING, rffi.INT_real], PyCodeObject)
 def PyCode_NewEmpty(space, filename, funcname, firstlineno):
     """Creates a new empty code object with the specified source location."""
     return space.wrap(PyCode(space,

diff --git a/pypy/translator/c/src/dtoa.c b/pypy/translator/c/src/dtoa.c
--- a/pypy/translator/c/src/dtoa.c
+++ b/pypy/translator/c/src/dtoa.c
@@ -116,7 +116,6 @@
 
 /* Begin PYPY hacks */
 /* #include "Python.h" */
-#define DOUBLE_IS_LITTLE_ENDIAN_IEEE754
 #define HAVE_UINT32_T
 #define HAVE_INT32_T
 #define HAVE_UINT64_T

diff --git a/pypy/module/imp/interp_imp.py b/pypy/module/imp/interp_imp.py
--- a/pypy/module/imp/interp_imp.py
+++ b/pypy/module/imp/interp_imp.py
@@ -126,8 +126,16 @@
     _run_compiled_module(space, w_modulename, filename, w_file, w_mod)
     return w_mod
 
+ at unwrap_spec(filename=str)
+def load_dynamic(space, w_modulename, filename, w_file=None):
+    if not space.config.objspace.usemodules.cpyext:
+        raise OperationError(space.w_ImportError, space.wrap(
+            "Not implemented"))
+    importing.load_c_extension(space, filename, space.str_w(w_modulename))
+    return importing.check_sys_modules(space, w_modulename)
+
 def new_module(space, w_name):
-    return space.wrap(Module(space, w_name))
+    return space.wrap(Module(space, w_name, add_package=False))
 
 def init_builtin(space, w_name):
     name = space.str_w(w_name)

diff --git a/pypy/module/pyexpat/interp_pyexpat.py b/pypy/module/pyexpat/interp_pyexpat.py
--- a/pypy/module/pyexpat/interp_pyexpat.py
+++ b/pypy/module/pyexpat/interp_pyexpat.py
@@ -253,8 +253,10 @@
     except OperationError, e:
         parser._exc_info = e
         XML_StopParser(parser.itself, XML_FALSE)
-        return 0
-    return 1
+        result = 0
+    else:
+        result = 1
+    return rffi.cast(rffi.INT, result)
 callback_type = lltype.Ptr(lltype.FuncType(
     [rffi.VOIDP, rffi.CCHARP, XML_Encoding_Ptr], rffi.INT))
 XML_SetUnknownEncodingHandler = expat_external(

diff --git a/pypy/jit/metainterp/optimizeopt/rewrite.py b/pypy/jit/metainterp/optimizeopt/rewrite.py
--- a/pypy/jit/metainterp/optimizeopt/rewrite.py
+++ b/pypy/jit/metainterp/optimizeopt/rewrite.py
@@ -154,6 +154,24 @@
 
             self.emit_operation(op)
 
+    def optimize_INT_LSHIFT(self, op):
+        v1 = self.getvalue(op.getarg(0))
+        v2 = self.getvalue(op.getarg(1))
+
+        if v2.is_constant() and v2.box.getint() == 0:
+            self.make_equal_to(op.result, v1)
+        else:
+            self.emit_operation(op)
+
+    def optimize_INT_RSHIFT(self, op):
+        v1 = self.getvalue(op.getarg(0))
+        v2 = self.getvalue(op.getarg(1))
+
+        if v2.is_constant() and v2.box.getint() == 0:
+            self.make_equal_to(op.result, v1)
+        else:
+            self.emit_operation(op)
+
     def optimize_CALL_PURE(self, op):
         arg_consts = []
         for i in range(op.numargs()):

diff --git a/lib_pypy/pyrepl/readline.py b/lib_pypy/pyrepl/readline.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/readline.py
@@ -0,0 +1,408 @@
+#   Copyright 2000-2010 Michael Hudson-Doyle <micahel at gmail.com>
+#                       Alex Gaynor
+#                       Antonio Cuni
+#                       Armin Rigo
+#                       Holger Krekel
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+"""A compatibility wrapper reimplementing the 'readline' standard module
+on top of pyrepl.  Not all functionalities are supported.  Contains
+extensions for multiline input.
+"""
+
+import sys, os
+from pyrepl import commands
+from pyrepl.historical_reader import HistoricalReader
+from pyrepl.completing_reader import CompletingReader
+from pyrepl.unix_console import UnixConsole, _error
+
+
+ENCODING = 'latin1'     # XXX hard-coded
+
+__all__ = ['add_history',
+           'clear_history',
+           'get_begidx',
+           'get_completer',
+           'get_completer_delims',
+           'get_current_history_length',
+           'get_endidx',
+           'get_history_item',
+           'get_history_length',
+           'get_line_buffer',
+           'insert_text',
+           'parse_and_bind',
+           'read_history_file',
+           'read_init_file',
+           'redisplay',
+           'remove_history_item',
+           'replace_history_item',
+           'set_completer',
+           'set_completer_delims',
+           'set_history_length',
+           'set_pre_input_hook',
+           'set_startup_hook',
+           'write_history_file',
+           # ---- multiline extensions ----
+           'multiline_input',
+           ]
+
+# ____________________________________________________________
+
+class ReadlineConfig(object):
+    readline_completer = None
+    completer_delims = dict.fromkeys(' \t\n`~!@#$%^&*()-=+[{]}\\|;:\'",<>/?')
+
+class ReadlineAlikeReader(HistoricalReader, CompletingReader):
+
+    assume_immutable_completions = False
+    use_brackets = False
+    sort_in_column = True
+
+    def error(self, msg="none"):
+        pass    # don't show error messages by default
+
+    def get_stem(self):
+        b = self.buffer
+        p = self.pos - 1
+        completer_delims = self.config.completer_delims
+        while p >= 0 and b[p] not in completer_delims:
+            p -= 1
+        return ''.join(b[p+1:self.pos])
+
+    def get_completions(self, stem):
+        result = []
+        function = self.config.readline_completer
+        if function is not None:
+            try:
+                stem = str(stem)   # rlcompleter.py seems to not like unicode
+            except UnicodeEncodeError:
+                pass   # but feed unicode anyway if we have no choice
+            state = 0
+            while True:
+                try:
+                    next = function(stem, state)
+                except:
+                    break
+                if not isinstance(next, str):
+                    break
+                result.append(next)
+                state += 1
+            # emulate the behavior of the standard readline that sorts
+            # the completions before displaying them.
+            result.sort()
+        return result
+
+    def get_trimmed_history(self, maxlength):
+        if maxlength >= 0:
+            cut = len(self.history) - maxlength
+            if cut < 0:
+                cut = 0
+        else:
+            cut = 0
+        return self.history[cut:]
+
+    # --- simplified support for reading multiline Python statements ---
+
+    # This duplicates small parts of pyrepl.python_reader.  I'm not
+    # reusing the PythonicReader class directly for two reasons.  One is
+    # to try to keep as close as possible to CPython's prompt.  The
+    # other is that it is the readline module that we are ultimately
+    # implementing here, and I don't want the built-in raw_input() to
+    # start trying to read multiline inputs just because what the user
+    # typed look like valid but incomplete Python code.  So we get the
+    # multiline feature only when using the multiline_input() function
+    # directly (see _pypy_interact.py).
+
+    more_lines = None
+
+    def collect_keymap(self):
+        return super(ReadlineAlikeReader, self).collect_keymap() + (
+            (r'\n', 'maybe-accept'),)
+
+    def __init__(self, console):
+        super(ReadlineAlikeReader, self).__init__(console)
+        self.commands['maybe_accept'] = maybe_accept
+        self.commands['maybe-accept'] = maybe_accept
+
+    def after_command(self, cmd):
+        super(ReadlineAlikeReader, self).after_command(cmd)
+        if self.more_lines is None:
+            # Force single-line input if we are in raw_input() mode.
+            # Although there is no direct way to add a \n in this mode,
+            # multiline buffers can still show up using various
+            # commands, e.g. navigating the history.
+            try:
+                index = self.buffer.index("\n")
+            except ValueError:
+                pass
+            else:
+                self.buffer = self.buffer[:index]
+                if self.pos > len(self.buffer):
+                    self.pos = len(self.buffer)
+
+class maybe_accept(commands.Command):
+    def do(self):
+        r = self.reader
+        r.dirty = 1 # this is needed to hide the completion menu, if visible
+        #
+        # if there are already several lines and the cursor
+        # is not on the last one, always insert a new \n.
+        text = r.get_unicode()
+        if "\n" in r.buffer[r.pos:]:
+            r.insert("\n")
+        elif r.more_lines is not None and r.more_lines(text):
+            r.insert("\n")
+        else:
+            self.finish = 1
+
+# ____________________________________________________________
+
+class _ReadlineWrapper(object):
+    f_in = 0
+    f_out = 1
+    reader = None
+    saved_history_length = -1
+    startup_hook = None
+    config = ReadlineConfig()
+
+    def get_reader(self):
+        if self.reader is None:
+            console = UnixConsole(self.f_in, self.f_out, encoding=ENCODING)
+            self.reader = ReadlineAlikeReader(console)
+            self.reader.config = self.config
+        return self.reader
+
+    def raw_input(self, prompt=''):
+        try:
+            reader = self.get_reader()
+        except _error:
+            return _old_raw_input(prompt)
+        if self.startup_hook is not None:
+            self.startup_hook()
+        reader.ps1 = prompt
+        return reader.readline()
+
+    def multiline_input(self, more_lines, ps1, ps2):
+        """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.
+        """
+        reader = self.get_reader()
+        saved = reader.more_lines
+        try:
+            reader.more_lines = more_lines
+            reader.ps1 = reader.ps2 = ps1
+            reader.ps3 = reader.ps4 = ps2
+            return reader.readline()
+        finally:
+            reader.more_lines = saved
+
+    def parse_and_bind(self, string):
+        pass  # XXX we don't support parsing GNU-readline-style init files
+
+    def set_completer(self, function=None):
+        self.config.readline_completer = function
+
+    def get_completer(self):
+        return self.config.readline_completer
+
+    def set_completer_delims(self, string):
+        self.config.completer_delims = dict.fromkeys(string)
+
+    def get_completer_delims(self):
+        chars = self.config.completer_delims.keys()
+        chars.sort()
+        return ''.join(chars)
+
+    def _histline(self, line):
+        return unicode(line.rstrip('\n'), ENCODING)
+
+    def get_history_length(self):
+        return self.saved_history_length
+
+    def set_history_length(self, length):
+        self.saved_history_length = length
+
+    def get_current_history_length(self):
+        return len(self.get_reader().history)
+
+    def read_history_file(self, filename='~/.history'):
+        # multiline extension (really a hack) for the end of lines that
+        # are actually continuations inside a single multiline_input()
+        # history item: we use \r\n instead of just \n.  If the history
+        # file is passed to GNU readline, the extra \r are just ignored.
+        history = self.get_reader().history
+        f = open(os.path.expanduser(filename), 'r')
+        buffer = []
+        for line in f:
+            if line.endswith('\r\n'):
+                buffer.append(line)
+            else:
+                line = self._histline(line)
+                if buffer:
+                    line = ''.join(buffer).replace('\r', '') + line
+                    del buffer[:]
+                if line:
+                    history.append(line)
+        f.close()
+
+    def write_history_file(self, filename='~/.history'):
+        maxlength = self.saved_history_length
+        history = self.get_reader().get_trimmed_history(maxlength)
+        f = open(os.path.expanduser(filename), 'w')
+        for entry in history:
+            if isinstance(entry, unicode):
+                entry = entry.encode(ENCODING)
+            entry = entry.replace('\n', '\r\n')   # multiline history support
+            f.write(entry + '\n')
+        f.close()
+
+    def clear_history(self):
+        del self.get_reader().history[:]
+
+    def get_history_item(self, index):
+        history = self.get_reader().history
+        if 1 <= index <= len(history):
+            return history[index-1]
+        else:
+            return None        # blame readline.c for not raising
+
+    def remove_history_item(self, index):
+        history = self.get_reader().history
+        if 0 <= index < len(history):
+            del history[index]
+        else:
+            raise ValueError("No history item at position %d" % index)
+            # blame readline.c for raising ValueError
+
+    def replace_history_item(self, index, line):
+        history = self.get_reader().history
+        if 0 <= index < len(history):
+            history[index] = self._histline(line)
+        else:
+            raise ValueError("No history item at position %d" % index)
+            # blame readline.c for raising ValueError
+
+    def add_history(self, line):
+        self.get_reader().history.append(self._histline(line))
+
+    def set_startup_hook(self, function=None):
+        self.startup_hook = function
+
+    def get_line_buffer(self):
+        return self.get_reader().get_buffer()
+
+    def _get_idxs(self):
+        start = cursor = self.get_reader().pos
+        buf = self.get_line_buffer()
+        for i in xrange(cursor - 1, -1, -1):
+            if buf[i] in self.get_completer_delims():
+                break
+            start = i
+        return start, cursor
+
+    def get_begidx(self):
+        return self._get_idxs()[0]
+
+    def get_endidx(self):
+        return self._get_idxs()[1]
+
+    def insert_text(self, text):
+        return self.get_reader().insert(text)
+
+
+_wrapper = _ReadlineWrapper()
+
+# ____________________________________________________________
+# Public API
+
+parse_and_bind = _wrapper.parse_and_bind
+set_completer = _wrapper.set_completer
+get_completer = _wrapper.get_completer
+set_completer_delims = _wrapper.set_completer_delims
+get_completer_delims = _wrapper.get_completer_delims
+get_history_length = _wrapper.get_history_length
+set_history_length = _wrapper.set_history_length
+get_current_history_length = _wrapper.get_current_history_length
+read_history_file = _wrapper.read_history_file
+write_history_file = _wrapper.write_history_file
+clear_history = _wrapper.clear_history
+get_history_item = _wrapper.get_history_item
+remove_history_item = _wrapper.remove_history_item
+replace_history_item = _wrapper.replace_history_item
+add_history = _wrapper.add_history
+set_startup_hook = _wrapper.set_startup_hook
+get_line_buffer = _wrapper.get_line_buffer
+get_begidx = _wrapper.get_begidx
+get_endidx = _wrapper.get_endidx
+insert_text = _wrapper.insert_text
+
+# Extension
+multiline_input = _wrapper.multiline_input
+
+# Internal hook
+_get_reader = _wrapper.get_reader
+
+# ____________________________________________________________
+# Stubs
+
+def _make_stub(_name, _ret):
+    def stub(*args, **kwds):
+        import warnings
+        warnings.warn("readline.%s() not implemented" % _name, stacklevel=2)
+    stub.func_name = _name
+    globals()[_name] = stub
+
+for _name, _ret in [
+    ('read_init_file', None),
+    ('redisplay', None),
+    ('set_pre_input_hook', None),
+    ]:
+    assert _name not in globals(), _name
+    _make_stub(_name, _ret)
+
+# ____________________________________________________________
+
+def _setup():
+    global _old_raw_input
+    if _old_raw_input is not None:
+        return # don't run _setup twice
+    
+    try:
+        f_in = sys.stdin.fileno()
+        f_out = sys.stdout.fileno()
+    except (AttributeError, ValueError):
+        return
+    if not os.isatty(f_in) or not os.isatty(f_out):
+        return
+
+    _wrapper.f_in = f_in
+    _wrapper.f_out = f_out
+
+    if hasattr(sys, '__raw_input__'):    # PyPy
+        _old_raw_input = sys.__raw_input__
+        sys.__raw_input__ = _wrapper.raw_input
+    else:
+        # this is not really what readline.c does.  Better than nothing I guess
+        import __builtin__
+        _old_raw_input = __builtin__.raw_input
+        __builtin__.raw_input = _wrapper.raw_input
+
+_old_raw_input = None
+_setup()

diff --git a/pypy/module/thread/os_thread.py b/pypy/module/thread/os_thread.py
--- a/pypy/module/thread/os_thread.py
+++ b/pypy/module/thread/os_thread.py
@@ -248,3 +248,8 @@
     """This is synonymous to ``raise SystemExit''.  It will cause the current
 thread to exit silently unless the exception is caught."""
     raise OperationError(space.w_SystemExit, space.w_None)
+
+def interrupt_main(space):
+    """Raise a KeyboardInterrupt in the main thread.
+A subthread can use this function to interrupt the main thread."""
+    space.check_signal_action.set_interrupt()

diff --git a/pypy/module/imp/app_imp.py b/pypy/module/imp/app_imp.py
deleted file mode 100644
--- a/pypy/module/imp/app_imp.py
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-def load_dynamic(name, pathname, file=None):
-    """Always raises ah ImportError on pypy"""
-    raise ImportError('Not implemented')

diff --git a/lib-python/modified-2.7.0/distutils/msvc9compiler.py b/lib-python/modified-2.7.0/distutils/msvc9compiler.py
--- a/lib-python/modified-2.7.0/distutils/msvc9compiler.py
+++ b/lib-python/modified-2.7.0/distutils/msvc9compiler.py
@@ -644,6 +644,7 @@
             temp_manifest = os.path.join(
                     build_temp,
                     os.path.basename(output_filename) + ".manifest")
+            ld_args.append('/MANIFEST')
             ld_args.append('/MANIFESTFILE:' + temp_manifest)
 
             if extra_preargs:

diff --git a/pypy/module/cpyext/longobject.py b/pypy/module/cpyext/longobject.py
--- a/pypy/module/cpyext/longobject.py
+++ b/pypy/module/cpyext/longobject.py
@@ -4,6 +4,8 @@
 from pypy.objspace.std.longobject import W_LongObject
 from pypy.interpreter.error import OperationError
 from pypy.module.cpyext.intobject import PyInt_AsUnsignedLongMask
+from pypy.rlib.rbigint import rbigint
+from pypy.rlib.rarithmetic import intmask
 
 
 PyLong_Check, PyLong_CheckExact = build_type_checkers("Long")
@@ -177,4 +179,31 @@
     assert isinstance(w_long, W_LongObject)
     return w_long.num.sign
 
+UCHARP = rffi.CArrayPtr(rffi.UCHAR)
+ at cpython_api([UCHARP, rffi.SIZE_T, rffi.INT_real, rffi.INT_real], PyObject)
+def _PyLong_FromByteArray(space, bytes, n, little_endian, signed):
+    little_endian = rffi.cast(lltype.Signed, little_endian)
+    signed = rffi.cast(lltype.Signed, signed)
 
+    result = rbigint()
+    negative = False
+
+    for i in range(0, n):
+        if little_endian:
+            c = intmask(bytes[i])
+        else:
+            c = intmask(bytes[n - i - 1])
+        if i == 0 and signed and c & 0x80:
+            negative = True
+        if negative:
+            c = c ^ 0xFF
+        digit = rbigint.fromint(c)
+
+        result = result.lshift(8)
+        result = result.add(digit)
+
+    if negative:
+        result = result.neg()
+
+    return space.newlong_from_rbigint(result)
+


diff --git a/pypy/tool/pytest/appsupport.py b/pypy/tool/pytest/appsupport.py
--- a/pypy/tool/pytest/appsupport.py
+++ b/pypy/tool/pytest/appsupport.py
@@ -196,7 +196,7 @@
     class _ExceptionInfo(object):
         def __init__(self):
             import sys
-            self.type, self.value, _ = sys.exc_info()
+            self.type, self.value, self.traceback = sys.exc_info()
 
     return _ExceptionInfo
 """)    

diff --git a/lib_pypy/pyrepl/pygame_keymap.py b/lib_pypy/pyrepl/pygame_keymap.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/pygame_keymap.py
@@ -0,0 +1,250 @@
+#   Copyright 2000-2008 Michael Hudson-Doyle <micahel at gmail.com>
+#                       Armin Rigo
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+# keyspec parsing for a pygame console.  currently this is simply copy
+# n' change from the unix (ie. trad terminal) variant; probably some
+# refactoring will happen when I work out how it will work best.
+
+# A key is represented as *either*
+
+# a) a (keycode, meta, ctrl) sequence (used for special keys such as
+# f1, the up arrow key, etc)
+# b) a (unichar, meta, ctrl) sequence (used for printable chars)
+
+# Because we allow keystokes like '\\C-xu', I'll use the same trick as
+# the unix keymap module uses.
+
+# '\\C-a' --> (K_a, 0, 1)
+
+# XXX it's actually possible to test this module, so it should have a
+# XXX test suite.
+
+from pygame.locals import *
+
+_escapes = {
+    '\\': K_BACKSLASH,
+    "'" : K_QUOTE,
+    '"' : K_QUOTEDBL,
+#    'a' : '\a',
+    'b' : K_BACKSLASH,
+    'e' : K_ESCAPE,
+#    'f' : '\f',
+    'n' : K_RETURN,
+    'r' : K_RETURN,
+    't' : K_TAB,
+#    'v' : '\v'
+    }
+
+_keynames = {
+    'backspace' : K_BACKSPACE,
+    'delete'    : K_DELETE,
+    'down'      : K_DOWN,
+    'end'       : K_END,
+    'enter'     : K_KP_ENTER,
+    'escape'    : K_ESCAPE,
+    'f1' : K_F1, 'f2' : K_F2, 'f3' : K_F3, 'f4' : K_F4,
+    'f5' : K_F5, 'f6' : K_F6, 'f7' : K_F7, 'f8' : K_F8,
+    'f9' : K_F9, 'f10': K_F10,'f11': K_F11,'f12': K_F12,
+    'f13': K_F13,'f14': K_F14,'f15': K_F15,
+    'home'   : K_HOME,
+    'insert' : K_INSERT,
+    'left'   : K_LEFT,
+    'pgdown' : K_PAGEDOWN, 'page down' : K_PAGEDOWN,
+    'pgup'   : K_PAGEUP,   'page up'   : K_PAGEUP,
+    'return' : K_RETURN,
+    'right'  : K_RIGHT,
+    'space'  : K_SPACE,
+    'tab'    : K_TAB,
+    'up'     : K_UP,
+    }
+
+class KeySpecError(Exception):
+    pass
+
+def _parse_key1(key, s):
+    ctrl = 0
+    meta = 0
+    ret = ''
+    while not ret and s < len(key):
+        if key[s] == '\\':
+            c = key[s+1].lower()
+            if _escapes.has_key(c):
+                ret = _escapes[c]
+                s += 2
+            elif c == "c":
+                if key[s + 2] != '-':
+                    raise KeySpecError, \
+                              "\\C must be followed by `-' (char %d of %s)"%(
+                        s + 2, repr(key))
+                if ctrl:
+                    raise KeySpecError, "doubled \\C- (char %d of %s)"%(
+                        s + 1, repr(key))
+                ctrl = 1
+                s += 3
+            elif c == "m":
+                if key[s + 2] != '-':
+                    raise KeySpecError, \
+                              "\\M must be followed by `-' (char %d of %s)"%(
+                        s + 2, repr(key))
+                if meta:
+                    raise KeySpecError, "doubled \\M- (char %d of %s)"%(
+                        s + 1, repr(key))
+                meta = 1
+                s += 3
+            elif c.isdigit():
+                n = key[s+1:s+4]
+                ret = chr(int(n, 8))
+                s += 4
+            elif c == 'x':
+                n = key[s+2:s+4]
+                ret = chr(int(n, 16))
+                s += 4
+            elif c == '<':
+                t = key.find('>', s)
+                if t == -1:
+                    raise KeySpecError, \
+                              "unterminated \\< starting at char %d of %s"%(
+                        s + 1, repr(key))
+                try:
+                    ret = _keynames[key[s+2:t].lower()]
+                    s = t + 1
+                except KeyError:
+                    raise KeySpecError, \
+                              "unrecognised keyname `%s' at char %d of %s"%(
+                        key[s+2:t], s + 2, repr(key))
+                if ret is None:
+                    return None, s
+            else:
+                raise KeySpecError, \
+                          "unknown backslash escape %s at char %d of %s"%(
+                    `c`, s + 2, repr(key))
+        else:
+            if ctrl:
+                ret = chr(ord(key[s]) & 0x1f)   # curses.ascii.ctrl()
+                ret = unicode(ret)
+            else:
+                ret = unicode(key[s])
+            s += 1
+    return (ret, meta, ctrl), s
+
+def parse_keys(key):
+    s = 0
+    r = []
+    while s < len(key):
+        k, s = _parse_key1(key, s)
+        if k is None:
+            return None
+        r.append(k)
+    return tuple(r)
+
+def _compile_keymap(keymap):
+    r = {}
+    for key, value in keymap.items():
+        r.setdefault(key[0], {})[key[1:]] = value
+    for key, value in r.items():
+        if value.has_key(()):
+            if len(value) <> 1:
+                raise KeySpecError, \
+                          "key definitions for %s clash"%(value.values(),)
+            else:
+                r[key] = value[()]
+        else:
+            r[key] = _compile_keymap(value)
+    return r
+
+def compile_keymap(keymap):
+    r = {}
+    for key, value in keymap:
+        k = parse_keys(key)
+        if value is None and r.has_key(k):
+            del r[k]
+        if k is not None:
+            r[k] = value
+    return _compile_keymap(r)
+
+def keyname(key):
+    longest_match = ''
+    longest_match_name = ''
+    for name, keyseq in keyset.items():
+        if keyseq and key.startswith(keyseq) and \
+               len(keyseq) > len(longest_match):
+            longest_match = keyseq
+            longest_match_name = name
+    if len(longest_match) > 0:
+        return longest_match_name, len(longest_match)
+    else:
+        return None, 0
+
+_unescapes = {'\r':'\\r', '\n':'\\n', '\177':'^?'}
+
+#for k,v in _escapes.items():
+#    _unescapes[v] = k
+
+def unparse_key(keyseq):
+    if not keyseq:
+        return ''
+    name, s = keyname(keyseq)
+    if name:
+        if name <> 'escape' or s == len(keyseq):
+            return '\\<' + name + '>' + unparse_key(keyseq[s:])
+        else:
+            return '\\M-' + unparse_key(keyseq[1:])
+    else:
+        c = keyseq[0]
+        r = keyseq[1:]
+        if c == '\\':
+            p = '\\\\'
+        elif _unescapes.has_key(c):
+            p = _unescapes[c]
+        elif ord(c) < ord(' '):
+            p = '\\C-%s'%(chr(ord(c)+96),)
+        elif ord(' ') <= ord(c) <= ord('~'):
+            p = c
+        else:
+            p = '\\%03o'%(ord(c),)
+        return p + unparse_key(r)
+
+def _unparse_keyf(keyseq):
+    if not keyseq:
+        return []
+    name, s = keyname(keyseq)
+    if name:
+        if name <> 'escape' or s == len(keyseq):
+            return [name] + _unparse_keyf(keyseq[s:])
+        else:
+            rest = _unparse_keyf(keyseq[1:])
+            return ['M-'+rest[0]] + rest[1:]
+    else:
+        c = keyseq[0]
+        r = keyseq[1:]
+        if c == '\\':
+            p = '\\'
+        elif _unescapes.has_key(c):
+            p = _unescapes[c]
+        elif ord(c) < ord(' '):
+            p = 'C-%s'%(chr(ord(c)+96),)
+        elif ord(' ') <= ord(c) <= ord('~'):
+            p = c
+        else:
+            p = '\\%03o'%(ord(c),)
+        return [p] + _unparse_keyf(r)
+
+def unparse_keyf(keyseq):
+    return " ".join(_unparse_keyf(keyseq))

diff --git a/pypy/interpreter/test/test_extmodules.py b/pypy/interpreter/test/test_extmodules.py
new file mode 100644
--- /dev/null
+++ b/pypy/interpreter/test/test_extmodules.py
@@ -0,0 +1,68 @@
+import sys
+import pytest
+
+from pypy.config.pypyoption import get_pypy_config
+from pypy.objspace.std import StdObjSpace
+from pypy.tool.udir import udir
+
+mod_init = """
+from pypy.interpreter.mixedmodule import MixedModule
+
+import time
+
+class Module(MixedModule):
+
+    appleveldefs = {}
+
+    interpleveldefs = {
+    'clock'    : 'interp_time.clock',
+    'time'     : 'interp_time.time_',
+    'sleep'    : 'interp_time.sleep',
+    }
+"""
+
+mod_interp = """
+import time
+
+from pypy.interpreter.gateway import unwrap_spec
+
+def clock(space):
+    return space.wrap(time.clock())
+
+def time_(space):
+    return space.wrap(time.time())
+
+ at unwrap_spec(seconds=float)
+def sleep(space, seconds):
+    time.sleep(seconds)
+"""
+
+old_sys_path = []
+
+def init_extmodule_code():
+    pkg = udir.join("testext")
+    pkg.ensure(dir=True)
+    pkg.join("__init__.py").write("# package")
+    mod = pkg.join("extmod")
+    mod.ensure(dir=True)
+    mod.join("__init__.py").write(mod_init)
+    mod.join("interp_time.py").write(mod_interp)
+
+class AppTestExtModules(object):
+    def setup_class(cls):
+        init_extmodule_code()
+        conf = get_pypy_config()
+        conf.objspace.extmodules = 'testext.extmod'
+        old_sys_path[:] = sys.path[:]
+        sys.path.insert(0, str(udir))
+        space = StdObjSpace(conf)
+        cls.space = space
+
+    def teardown_class(cls):
+        sys.path[:] = old_sys_path
+
+    @pytest.mark.skipif("config.option.runappdirect")
+    def test_import(self):
+        import extmod
+        assert extmod.__file__.endswith('extmod')
+        assert type(extmod.time()) is float

diff --git a/lib_pypy/pyrepl/tests/infrastructure.py b/lib_pypy/pyrepl/tests/infrastructure.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/tests/infrastructure.py
@@ -0,0 +1,82 @@
+#   Copyright 2000-2004 Michael Hudson-Doyle <micahel at gmail.com>
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+from pyrepl.reader import Reader
+from pyrepl.console import Console, Event
+import unittest
+import sys
+
+class EqualsAnything(object):
+    def __eq__(self, other):
+        return True
+EA = EqualsAnything()
+
+class TestConsole(Console):
+    height = 24
+    width = 80
+    encoding = 'utf-8'
+
+    def __init__(self, events, testcase, verbose=False):
+        self.events = events
+        self.next_screen = None
+        self.verbose = verbose
+        self.testcase = testcase
+
+    def refresh(self, screen, xy):
+        if self.next_screen is not None:
+            self.testcase.assertEqual(
+                screen, self.next_screen,
+                "[ %s != %s after %r ]"%(screen, self.next_screen,
+                                         self.last_event_name))
+
+    def get_event(self, block=1):
+        ev, sc = self.events.pop(0)
+        self.next_screen = sc
+        if not isinstance(ev, tuple):
+            ev = (ev,)
+        self.last_event_name = ev[0]
+        if self.verbose:
+            print "event", ev
+        return Event(*ev)
+
+class TestReader(Reader):
+    def get_prompt(self, lineno, cursor_on_line):
+        return ''
+    def refresh(self):
+        Reader.refresh(self)
+        self.dirty = True
+
+class ReaderTestCase(unittest.TestCase):
+    def run_test(self, test_spec, reader_class=TestReader):
+        # remember to finish your test_spec with 'accept' or similar!
+        con = TestConsole(test_spec, self)
+        reader = reader_class(con)
+        reader.readline()
+
+class BasicTestRunner:
+    def run(self, test):
+        result = unittest.TestResult()
+        test(result)
+        return result
+
+def run_testcase(testclass):
+    suite = unittest.makeSuite(testclass)
+    runner = unittest.TextTestRunner(sys.stdout, verbosity=1)
+    result = runner.run(suite)
+    

diff --git a/pypy/module/cpyext/test/test_longobject.py b/pypy/module/cpyext/test/test_longobject.py
--- a/pypy/module/cpyext/test/test_longobject.py
+++ b/pypy/module/cpyext/test/test_longobject.py
@@ -144,3 +144,20 @@
              """),
             ])
         assert module.from_string() == 0x1234
+
+    def test_frombytearray(self):
+        module = self.import_extension('foo', [
+            ("from_bytearray", "METH_VARARGS",
+             """
+                 int little_endian, is_signed;
+                 if (!PyArg_ParseTuple(args, "ii", &little_endian, &is_signed))
+                     return NULL;
+                 return _PyLong_FromByteArray("\x9A\xBC", 2,
+                                              little_endian, is_signed);
+             """),
+            ])
+        assert module.from_bytearray(True, False) == 0x9ABC
+        assert module.from_bytearray(True, True) == -0x6543
+        assert module.from_bytearray(False, False) == 0xBC9A
+        assert module.from_bytearray(False, True) == -0x4365
+


diff --git a/pypy/module/cpyext/frameobject.py b/pypy/module/cpyext/frameobject.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/frameobject.py
@@ -0,0 +1,82 @@
+from pypy.rpython.lltypesystem import rffi, lltype
+from pypy.module.cpyext.api import (
+    cpython_api, bootstrap_function, PyObjectFields, cpython_struct)
+from pypy.module.cpyext.pyobject import (
+    PyObject, Py_DecRef, make_ref, from_ref, track_reference,
+    make_typedescr, get_typedescr)
+from pypy.module.cpyext.state import State
+from pypy.module.cpyext.pystate import PyThreadState
+from pypy.module.cpyext.funcobject import PyCodeObject
+from pypy.interpreter.pyframe import PyFrame
+from pypy.interpreter.pycode import PyCode
+
+PyFrameObjectStruct = lltype.ForwardReference()
+PyFrameObject = lltype.Ptr(PyFrameObjectStruct)
+PyFrameObjectFields = (PyObjectFields +
+    (("f_code", PyCodeObject),
+     ("f_globals", PyObject),
+     ("f_lineno", rffi.INT),
+     ))
+cpython_struct("PyFrameObject", PyFrameObjectFields, PyFrameObjectStruct)
+
+ at bootstrap_function
+def init_frameobject(space):
+    make_typedescr(PyFrame.typedef,
+                   basestruct=PyFrameObject.TO,
+                   attach=frame_attach,
+                   dealloc=frame_dealloc,
+                   realize=frame_realize)
+
+def frame_attach(space, py_obj, w_obj):
+    "Fills a newly allocated PyFrameObject with a frame object"
+    frame = space.interp_w(PyFrame, w_obj)
+    py_frame = rffi.cast(PyFrameObject, py_obj)
+    py_frame.c_f_code = rffi.cast(PyCodeObject, make_ref(space, frame.pycode))
+    py_frame.c_f_globals = make_ref(space, frame.w_globals)
+    rffi.setintfield(py_frame, 'c_f_lineno', frame.f_lineno)
+
+ at cpython_api([PyObject], lltype.Void, external=False)
+def frame_dealloc(space, py_obj):
+    py_frame = rffi.cast(PyFrameObject, py_obj)
+    py_code = rffi.cast(PyObject, py_frame.c_f_code)
+    Py_DecRef(space, py_code)
+    Py_DecRef(space, py_frame.c_f_globals)
+    from pypy.module.cpyext.object import PyObject_dealloc
+    PyObject_dealloc(space, py_obj)
+
+def frame_realize(space, py_obj):
+    """
+    Creates the frame in the interpreter. The PyFrameObject structure must not
+    be modified after this call.
+    """
+    py_frame = rffi.cast(PyFrameObject, py_obj)
+    py_code = rffi.cast(PyObject, py_frame.c_f_code)
+    w_code = from_ref(space, py_code)
+    code = space.interp_w(PyCode, w_code)
+    w_globals = from_ref(space, py_frame.c_f_globals)
+
+    frame = PyFrame(space, code, w_globals, closure=None)
+    frame.f_lineno = py_frame.c_f_lineno
+    w_obj = space.wrap(frame)
+    track_reference(space, py_obj, w_obj)
+    return w_obj
+
+ at cpython_api([PyThreadState, PyCodeObject, PyObject, PyObject], PyFrameObject)
+def PyFrame_New(space, tstate, w_code, w_globals, w_locals):
+    typedescr = get_typedescr(PyFrame.typedef)
+    py_obj = typedescr.allocate(space, space.gettypeobject(PyFrame.typedef))
+    py_frame = rffi.cast(PyFrameObject, py_obj)
+    space.interp_w(PyCode, w_code) # sanity check
+    py_frame.c_f_code = rffi.cast(PyCodeObject, make_ref(space, w_code))
+    py_frame.c_f_globals = make_ref(space, w_globals)
+    return py_frame
+
+ at cpython_api([PyFrameObject], rffi.INT_real, error=-1)
+def PyTraceBack_Here(space, w_frame):
+    from pypy.interpreter.pytraceback import record_application_traceback
+    state = space.fromcache(State)
+    if state.operror is None:
+        return -1
+    frame = space.interp_w(PyFrame, w_frame)
+    record_application_traceback(space, state.operror, frame, 0)
+    return 0

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
@@ -19,6 +19,8 @@
 
     def __init__(self, rtyper, stats, opts=None, translate_support_code=False,
                  gcdescr=None):
+        if gcdescr is not None:
+            gcdescr.force_index_ofs = FORCE_INDEX_OFS
         AbstractLLCPU.__init__(self, rtyper, stats, opts,
                                translate_support_code, gcdescr)
 
@@ -113,10 +115,11 @@
                 LLInterpreter.current_interpreter = prev_interpreter
         return res
 
-    @staticmethod
     def cast_ptr_to_int(x):
         adr = llmemory.cast_ptr_to_adr(x)
         return CPU386.cast_adr_to_int(adr)
+    cast_ptr_to_int._annspecialcase_ = 'specialize:arglltype(0)'
+    cast_ptr_to_int = staticmethod(cast_ptr_to_int)
 
     all_null_registers = lltype.malloc(rffi.LONGP.TO, 24,
                                        flavor='raw', zero=True,
@@ -127,7 +130,7 @@
         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)
-        rffi.cast(TP, addr_of_force_index)[0] = -1
+        rffi.cast(TP, addr_of_force_index)[0] = ~fail_index
         frb = self.assembler._find_failure_recovery_bytecode(faildescr)
         bytecode = rffi.cast(rffi.UCHARP, frb)
         # start of "no gc operation!" block
@@ -147,7 +150,6 @@
     WORD = 4
     NUM_REGS = 8
     CALLEE_SAVE_REGISTERS = [regloc.ebx, regloc.esi, regloc.edi]
-    FRAME_FIXED_SIZE = len(CALLEE_SAVE_REGISTERS) + 2
 
     supports_longlong = True
 
@@ -163,7 +165,6 @@
     WORD = 8
     NUM_REGS = 16
     CALLEE_SAVE_REGISTERS = [regloc.ebx, regloc.r12, regloc.r13, regloc.r14, regloc.r15]
-    FRAME_FIXED_SIZE = len(CALLEE_SAVE_REGISTERS) + 2
 
     def __init__(self, *args, **kwargs):
         assert sys.maxint == (2**63 - 1)

diff --git a/pypy/jit/metainterp/test/test_compile.py b/pypy/jit/metainterp/test/test_compile.py
--- a/pypy/jit/metainterp/test/test_compile.py
+++ b/pypy/jit/metainterp/test/test_compile.py
@@ -89,6 +89,8 @@
     metainterp.history = History()
     metainterp.history.operations = loop.operations[:]
     metainterp.history.inputargs = loop.inputargs[:]
+    cpu._all_size_descrs_with_vtable = (
+        LLtypeMixin.cpu._all_size_descrs_with_vtable)
     #
     loop_tokens = []
     loop_token = compile_new_loop(metainterp, loop_tokens, [], 0, None)

diff --git a/pypy/rpython/lltypesystem/lloperation.py b/pypy/rpython/lltypesystem/lloperation.py
--- a/pypy/rpython/lltypesystem/lloperation.py
+++ b/pypy/rpython/lltypesystem/lloperation.py
@@ -487,7 +487,9 @@
     # ^^^ returns an address of nursery free pointer, for later modifications
     'gc_adr_of_nursery_top' : LLOp(),
     # ^^^ returns an address of pointer, since it can change at runtime
-    
+    'gc_adr_of_root_stack_top': LLOp(),
+    # ^^^ returns the address of gcdata.root_stack_top (for shadowstack only)
+
     # experimental operations in support of thread cloning, only
     # implemented by the Mark&Sweep GC
     'gc_x_swap_pool':       LLOp(canraise=(MemoryError,), canunwindgc=True),

diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -365,7 +365,11 @@
 
     def setbuiltinmodule(self, importname):
         """NOT_RPYTHON. load a lazy pypy/module and put it into sys.modules"""
-        fullname = "pypy.module.%s" % importname
+        if '.' in importname:
+            fullname = importname
+            importname = fullname.rsplit('.', 1)[1]
+        else:
+            fullname = "pypy.module.%s" % importname
 
         Module = __import__(fullname,
                             None, None, ["Module"]).Module
@@ -428,6 +432,11 @@
             if value and name not in modules:
                 modules.append(name)
 
+        if self.config.objspace.extmodules:
+            for name in self.config.objspace.extmodules.split(','):
+                if name not in modules:
+                    modules.append(name)
+
         # a bit of custom logic: time2 or rctime take precedence over time
         # XXX this could probably be done as a "requires" in the config
         if ('time2' in modules or 'rctime' in modules) and 'time' in modules:
@@ -745,7 +754,12 @@
         """Unpack an iterable object into a real (interpreter-level) list.
         Raise an OperationError(w_ValueError) if the length is wrong."""
         w_iterator = self.iter(w_iterable)
-        items = []
+        # If we know the expected length we can preallocate.
+        if expected_length == -1:
+            items = []
+        else:
+            items = [None] * expected_length
+        idx = 0
         while True:
             try:
                 w_item = self.next(w_iterator)
@@ -753,19 +767,22 @@
                 if not e.match(self, self.w_StopIteration):
                     raise
                 break  # done
-            if expected_length != -1 and len(items) == expected_length:
+            if expected_length != -1 and idx == expected_length:
                 raise OperationError(self.w_ValueError,
                                      self.wrap("too many values to unpack"))
-            items.append(w_item)
-        if expected_length != -1 and len(items) < expected_length:
-            i = len(items)
-            if i == 1:
+            if expected_length == -1:
+                items.append(w_item)
+            else:
+                items[idx] = w_item
+            idx += 1
+        if expected_length != -1 and idx < expected_length:
+            if idx == 1:
                 plural = ""
             else:
                 plural = "s"
             raise OperationError(self.w_ValueError,
                       self.wrap("need more than %d value%s to unpack" %
-                                (i, plural)))
+                                (idx, plural)))
         return items
 
     unpackiterable_unroll = jit.unroll_safe(func_with_new_name(unpackiterable,
@@ -1333,6 +1350,11 @@
         pass
     def _freeze_(self):
         return True
+    def __enter__(self):
+        pass
+    def __exit__(self, *args):
+        pass
+
 dummy_lock = DummyLock()
 
 ## Table describing the regular part of the interface of object spaces,

diff --git a/pypy/translator/cli/ilgenerator.py b/pypy/translator/cli/ilgenerator.py
--- a/pypy/translator/cli/ilgenerator.py
+++ b/pypy/translator/cli/ilgenerator.py
@@ -443,8 +443,8 @@
             self.ilasm.opcode('newarr', clitype.itemtype.typename())
     
     def _array_suffix(self, ARRAY, erase_unsigned=False):
-        from pypy.translator.cli.metavm import OOTYPE_TO_MNEMONIC
-        suffix = OOTYPE_TO_MNEMONIC.get(ARRAY.ITEM, 'ref')
+        from pypy.translator.cli.metavm import ootype_to_mnemonic
+        suffix = ootype_to_mnemonic(ARRAY.ITEM, ARRAY.ITEM, 'ref')
         if erase_unsigned:
             suffix = suffix.replace('u', 'i')
         return suffix

diff --git a/pypy/module/cpyext/include/code.h b/pypy/module/cpyext/include/code.h
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/include/code.h
@@ -0,0 +1,12 @@
+#ifndef Py_CODE_H
+#define Py_CODE_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef PyObject PyCodeObject;
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_CODE_H */

diff --git a/pypy/translator/backendopt/ssa.py b/pypy/translator/backendopt/ssa.py
--- a/pypy/translator/backendopt/ssa.py
+++ b/pypy/translator/backendopt/ssa.py
@@ -1,4 +1,4 @@
-from pypy.objspace.flow.model import Variable, mkentrymap, flatten, Block
+from pypy.objspace.flow.model import Variable, mkentrymap, Block
 from pypy.tool.algo.unionfind import UnionFind
 
 class DataFlowFamilyBuilder:

diff --git a/pypy/doc/conf.py b/pypy/doc/conf.py
--- a/pypy/doc/conf.py
+++ b/pypy/doc/conf.py
@@ -45,9 +45,9 @@
 # built documents.
 #
 # The short X.Y version.
-version = '1.4.1'
+version = '1.5'
 # The full version, including alpha/beta/rc tags.
-release = '1.4.1'
+release = '1.5-alpha'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.

diff --git a/pypy/rpython/ootypesystem/rstr.py b/pypy/rpython/ootypesystem/rstr.py
--- a/pypy/rpython/ootypesystem/rstr.py
+++ b/pypy/rpython/ootypesystem/rstr.py
@@ -211,8 +211,11 @@
     def ll_stringslice_minusone(s):
         return s.ll_substring(0, s.ll_strlen()-1)
 
-    def ll_split_chr(RESULT, s, c):
-        return RESULT.ll_convert_from_array(s.ll_split_chr(c))
+    def ll_split_chr(RESULT, s, c, max):
+        return RESULT.ll_convert_from_array(s.ll_split_chr(c, max))
+
+    def ll_rsplit_chr(RESULT, s, c, max):
+        return RESULT.ll_convert_from_array(s.ll_rsplit_chr(c, max))
 
     def ll_int(s, base):
         if not 2 <= base <= 36:

diff --git a/lib_pypy/pyrepl/console.py b/lib_pypy/pyrepl/console.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/console.py
@@ -0,0 +1,93 @@
+#   Copyright 2000-2004 Michael Hudson-Doyle <micahel at gmail.com>
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+class Event:
+    """An Event.  `evt' is 'key' or somesuch."""
+
+    def __init__(self, evt, data, raw=''):
+        self.evt = evt
+        self.data = data
+        self.raw = raw
+
+    def __repr__(self):
+        return 'Event(%r, %r)'%(self.evt, self.data)
+
+class Console:
+    """Attributes:
+
+    screen,
+    height,
+    width,
+    """
+    
+    def refresh(self, screen, xy):
+        pass
+
+    def prepare(self):
+        pass
+
+    def restore(self):
+        pass
+
+    def move_cursor(self, x, y):
+        pass
+
+    def set_cursor_vis(self, vis):
+        pass
+
+    def getheightwidth(self):
+        """Return (height, width) where height and width are the height
+        and width of the terminal window in characters."""
+        pass
+
+    def get_event(self, block=1):
+        """Return an Event instance.  Returns None if |block| is false
+        and there is no event pending, otherwise waits for the
+        completion of an event."""
+        pass
+
+    def beep(self):
+        pass
+
+    def clear(self):
+        """Wipe the screen"""
+        pass
+
+    def finish(self):
+        """Move the cursor to the end of the display and otherwise get
+        ready for end.  XXX could be merged with restore?  Hmm."""
+        pass
+
+    def flushoutput(self):
+        """Flush all output to the screen (assuming there's some
+        buffering going on somewhere)."""
+        pass
+
+    def forgetinput(self):
+        """Forget all pending, but not yet processed input."""
+        pass
+
+    def getpending(self):
+        """Return the characters that have been typed but not yet
+        processed."""
+        pass
+
+    def wait(self):
+        """Wait for an event."""
+        pass

diff --git a/lib_pypy/pyrepl/reader.py b/lib_pypy/pyrepl/reader.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/reader.py
@@ -0,0 +1,614 @@
+#   Copyright 2000-2010 Michael Hudson-Doyle <micahel at gmail.com>
+#                       Antonio Cuni
+#                       Armin Rigo
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+import types
+from pyrepl import unicodedata_
+from pyrepl import commands
+from pyrepl import input
+
+def _make_unctrl_map():
+    uc_map = {}
+    for c in map(unichr, range(256)):
+        if unicodedata_.category(c)[0] <> 'C':
+            uc_map[c] = c
+    for i in range(32):
+        c = unichr(i)
+        uc_map[c] = u'^' + unichr(ord('A') + i - 1)
+    uc_map['\t'] = '    ' # display TABs as 4 characters
+    uc_map['\177'] = u'^?'
+    for i in range(256):
+        c = unichr(i)
+        if not uc_map.has_key(c):
+            uc_map[c] = u'\\%03o'%i 
+    return uc_map
+
+# disp_str proved to be a bottleneck for large inputs, so it's been
+# rewritten in C; it's not required though.
+try:
+    raise ImportError # currently it's borked by the unicode support
+    
+    from _pyrepl_utils import disp_str, init_unctrl_map
+    
+    init_unctrl_map(_make_unctrl_map())
+
+    del init_unctrl_map
+except ImportError:
+    def _my_unctrl(c, u=_make_unctrl_map()):
+        if c in u:
+            return u[c]
+        else:
+            if unicodedata_.category(c).startswith('C'):
+                return '\u%04x'%(ord(c),)
+            else:
+                return c
+
+    def disp_str(buffer, join=''.join, uc=_my_unctrl):
+        """ disp_str(buffer:string) -> (string, [int])
+
+        Return the string that should be the printed represenation of
+        |buffer| and a list detailing where the characters of |buffer|
+        get used up.  E.g.:
+
+        >>> disp_str(chr(3))
+        ('^C', [1, 0])
+
+        the list always contains 0s or 1s at present; it could conceivably
+        go higher as and when unicode support happens."""
+        s = map(uc, buffer)
+        return (join(s),
+                map(ord, join(map(lambda x:'\001'+(len(x)-1)*'\000', s))))
+
+    del _my_unctrl
+
+del _make_unctrl_map
+
+# syntax classes:
+
+[SYNTAX_WHITESPACE,
+ SYNTAX_WORD,
+ SYNTAX_SYMBOL] = range(3)
+
+def make_default_syntax_table():
+    # XXX perhaps should use some unicodedata here?
+    st = {}
+    for c in map(unichr, range(256)):
+        st[c] = SYNTAX_SYMBOL
+    for c in [a for a in map(unichr, range(256)) if a.isalpha()]:
+        st[c] = SYNTAX_WORD
+    st[u'\n'] = st[u' '] = SYNTAX_WHITESPACE
+    return st
+
+default_keymap = tuple(
+    [(r'\C-a', 'beginning-of-line'),
+     (r'\C-b', 'left'),
+     (r'\C-c', 'interrupt'),
+     (r'\C-d', 'delete'),
+     (r'\C-e', 'end-of-line'),
+     (r'\C-f', 'right'),
+     (r'\C-g', 'cancel'),
+     (r'\C-h', 'backspace'),
+     (r'\C-j', 'accept'),
+     (r'\<return>', 'accept'),
+     (r'\C-k', 'kill-line'),
+     (r'\C-l', 'clear-screen'),
+     (r'\C-m', 'accept'),
+     (r'\C-q', 'quoted-insert'),
+     (r'\C-t', 'transpose-characters'),
+     (r'\C-u', 'unix-line-discard'),
+     (r'\C-v', 'quoted-insert'),
+     (r'\C-w', 'unix-word-rubout'),
+     (r'\C-x\C-u', 'upcase-region'),
+     (r'\C-y', 'yank'),
+     (r'\C-z', 'suspend'),
+     
+     (r'\M-b', 'backward-word'),
+     (r'\M-c', 'capitalize-word'),
+     (r'\M-d', 'kill-word'),
+     (r'\M-f', 'forward-word'),
+     (r'\M-l', 'downcase-word'),
+     (r'\M-t', 'transpose-words'),
+     (r'\M-u', 'upcase-word'),
+     (r'\M-y', 'yank-pop'),
+     (r'\M--', 'digit-arg'),
+     (r'\M-0', 'digit-arg'),
+     (r'\M-1', 'digit-arg'),
+     (r'\M-2', 'digit-arg'),
+     (r'\M-3', 'digit-arg'),
+     (r'\M-4', 'digit-arg'),
+     (r'\M-5', 'digit-arg'),
+     (r'\M-6', 'digit-arg'),
+     (r'\M-7', 'digit-arg'),
+     (r'\M-8', 'digit-arg'),
+     (r'\M-9', 'digit-arg'),
+     #(r'\M-\n', 'insert-nl'),
+     ('\\\\', 'self-insert')] + \
+    [(c, 'self-insert')
+     for c in map(chr, range(32, 127)) if c <> '\\'] + \
+    [(c, 'self-insert')
+     for c in map(chr, range(128, 256)) if c.isalpha()] + \
+    [(r'\<up>', 'up'),
+     (r'\<down>', 'down'),
+     (r'\<left>', 'left'),
+     (r'\<right>', 'right'),
+     (r'\<insert>', 'quoted-insert'),
+     (r'\<delete>', 'delete'),
+     (r'\<backspace>', 'backspace'),
+     (r'\M-\<backspace>', 'backward-kill-word'),
+     (r'\<end>', 'end'),
+     (r'\<home>', 'home'),
+     (r'\<f1>', 'help'),
+     (r'\EOF', 'end'),  # the entries in the terminfo database for xterms
+     (r'\EOH', 'home'), # seem to be wrong.  this is a less than ideal
+                        # workaround
+     ])
+
+del c # from the listcomps
+
+class Reader(object):
+    """The Reader class implements the bare bones of a command reader,
+    handling such details as editing and cursor motion.  What it does
+    not support are such things as completion or history support -
+    these are implemented elsewhere.
+
+    Instance variables of note include:
+
+      * buffer:
+        A *list* (*not* a string at the moment :-) containing all the
+        characters that have been entered.
+      * console:
+        Hopefully encapsulates the OS dependent stuff.
+      * pos:
+        A 0-based index into `buffer' for where the insertion point
+        is.
+      * screeninfo:
+        Ahem.  This list contains some info needed to move the
+        insertion point around reasonably efficiently.  I'd like to
+        get rid of it, because its contents are obtuse (to put it
+        mildly) but I haven't worked out if that is possible yet.
+      * cxy, lxy:
+        the position of the insertion point in screen ... XXX
+      * syntax_table:
+        Dictionary mapping characters to `syntax class'; read the
+        emacs docs to see what this means :-)
+      * commands:
+        Dictionary mapping command names to command classes.
+      * arg:
+        The emacs-style prefix argument.  It will be None if no such
+        argument has been provided.
+      * dirty:
+        True if we need to refresh the display.
+      * kill_ring:
+        The emacs-style kill-ring; manipulated with yank & yank-pop
+      * ps1, ps2, ps3, ps4:
+        prompts.  ps1 is the prompt for a one-line input; for a
+        multiline input it looks like:
+            ps2> first line of input goes here
+            ps3> second and further
+            ps3> lines get ps3
+            ...
+            ps4> and the last one gets ps4
+        As with the usual top-level, you can set these to instances if
+        you like; str() will be called on them (once) at the beginning
+        of each command.  Don't put really long or newline containing
+        strings here, please!
+        This is just the default policy; you can change it freely by
+        overriding get_prompt() (and indeed some standard subclasses
+        do).
+      * finished:
+        handle1 will set this to a true value if a command signals
+        that we're done.
+    """
+
+    help_text = """\
+This is pyrepl.  Hear my roar.
+
+Helpful text may appear here at some point in the future when I'm
+feeling more loquacious than I am now."""
+
+    msg_at_bottom = True
+
+    def __init__(self, console):
+        self.buffer = []
+        self.ps1 = "->> "
+        self.ps2 = "/>> "
+        self.ps3 = "|.. "
+        self.ps4 = "\__ "
+        self.kill_ring = []
+        self.arg = None
+        self.finished = 0
+        self.console = console
+        self.commands = {}
+        self.msg = ''
+        for v in vars(commands).values():
+            if  ( isinstance(v, type)
+                  and issubclass(v, commands.Command)
+                  and v.__name__[0].islower() ):
+                self.commands[v.__name__] = v
+                self.commands[v.__name__.replace('_', '-')] = v
+        self.syntax_table = make_default_syntax_table()
+        self.input_trans_stack = []
+        self.keymap = self.collect_keymap()
+        self.input_trans = input.KeymapTranslator(
+            self.keymap,
+            invalid_cls='invalid-key',
+            character_cls='self-insert')
+
+    def collect_keymap(self):
+        return default_keymap
+
+    def calc_screen(self):
+        """The purpose of this method is to translate changes in
+        self.buffer into changes in self.screen.  Currently it rips
+        everything down and starts from scratch, which whilst not
+        especially efficient is certainly simple(r).
+        """
+        lines = self.get_unicode().split("\n")
+        screen = []
+        screeninfo = []
+        w = self.console.width - 1
+        p = self.pos
+        for ln, line in zip(range(len(lines)), lines):
+            ll = len(line)
+            if 0 <= p <= ll:
+                if self.msg and not self.msg_at_bottom:
+                    for mline in self.msg.split("\n"):
+                        screen.append(mline)
+                        screeninfo.append((0, []))
+                self.lxy = p, ln
+            prompt = self.get_prompt(ln, ll >= p >= 0)
+            while '\n' in prompt:
+                pre_prompt, _, prompt = prompt.partition('\n')
+                screen.append(pre_prompt)
+                screeninfo.append((0, []))
+            p -= ll + 1
+            prompt, lp = self.process_prompt(prompt)
+            l, l2 = disp_str(line)
+            wrapcount = (len(l) + lp) / w
+            if wrapcount == 0:
+                screen.append(prompt + l)
+                screeninfo.append((lp, l2+[1]))
+            else:
+                screen.append(prompt + l[:w-lp] + "\\")
+                screeninfo.append((lp, l2[:w-lp]))
+                for i in range(-lp + w, -lp + wrapcount*w, w):
+                    screen.append(l[i:i+w] +  "\\")
+                    screeninfo.append((0, l2[i:i + w]))
+                screen.append(l[wrapcount*w - lp:])
+                screeninfo.append((0, l2[wrapcount*w - lp:]+[1]))
+        self.screeninfo = screeninfo
+        self.cxy = self.pos2xy(self.pos)
+        if self.msg and self.msg_at_bottom:
+            for mline in self.msg.split("\n"):
+                screen.append(mline)
+                screeninfo.append((0, []))
+        return screen
+
+    def process_prompt(self, prompt):
+        """ Process the prompt.
+        
+        This means calculate the length of the prompt. The character \x01
+        and \x02 are used to bracket ANSI control sequences and need to be
+        excluded from the length calculation.  So also a copy of the prompt
+        is returned with these control characters removed.  """
+
+        out_prompt = ''
+        l = len(prompt)
+        pos = 0
+        while True:
+            s = prompt.find('\x01', pos)
+            if s == -1:
+                break
+            e = prompt.find('\x02', s)
+            if e == -1:
+                break
+            # Found start and end brackets, subtract from string length
+            l = l - (e-s+1)
+            out_prompt += prompt[pos:s] + prompt[s+1:e]
+            pos = e+1
+        out_prompt += prompt[pos:]
+        return out_prompt, l
+
+    def bow(self, p=None):
+        """Return the 0-based index of the word break preceding p most
+        immediately.
+
+        p defaults to self.pos; word boundaries are determined using
+        self.syntax_table."""
+        if p is None:
+            p = self.pos
+        st = self.syntax_table
+        b = self.buffer
+        p -= 1
+        while p >= 0 and st.get(b[p], SYNTAX_WORD) <> SYNTAX_WORD:
+            p -= 1
+        while p >= 0 and st.get(b[p], SYNTAX_WORD) == SYNTAX_WORD:
+            p -= 1
+        return p + 1
+
+    def eow(self, p=None):
+        """Return the 0-based index of the word break following p most
+        immediately.
+
+        p defaults to self.pos; word boundaries are determined using
+        self.syntax_table."""
+        if p is None:
+            p = self.pos
+        st = self.syntax_table
+        b = self.buffer
+        while p < len(b) and st.get(b[p], SYNTAX_WORD) <> SYNTAX_WORD:
+            p += 1
+        while p < len(b) and st.get(b[p], SYNTAX_WORD) == SYNTAX_WORD:
+            p += 1
+        return p
+
+    def bol(self, p=None):
+        """Return the 0-based index of the line break preceding p most
+        immediately.
+
+        p defaults to self.pos."""
+        # XXX there are problems here.
+        if p is None:
+            p = self.pos
+        b = self.buffer
+        p -= 1
+        while p >= 0 and b[p] <> '\n':
+            p -= 1
+        return p + 1
+    
+    def eol(self, p=None):
+        """Return the 0-based index of the line break following p most
+        immediately.
+
+        p defaults to self.pos."""
+        if p is None:
+            p = self.pos
+        b = self.buffer
+        while p < len(b) and b[p] <> '\n':
+            p += 1
+        return p
+
+    def get_arg(self, default=1):
+        """Return any prefix argument that the user has supplied,
+        returning `default' if there is None.  `default' defaults
+        (groan) to 1."""
+        if self.arg is None:
+            return default
+        else:
+            return self.arg
+
+    def get_prompt(self, lineno, cursor_on_line):
+        """Return what should be in the left-hand margin for line
+        `lineno'."""
+        if self.arg is not None and cursor_on_line:
+            return "(arg: %s) "%self.arg
+        if "\n" in self.buffer:
+            if lineno == 0:
+                return self._ps2
+            elif lineno == self.buffer.count("\n"):
+                return self._ps4
+            else:
+                return self._ps3
+        else:
+            return self._ps1
+
+    def push_input_trans(self, itrans):
+        self.input_trans_stack.append(self.input_trans)
+        self.input_trans = itrans
+
+    def pop_input_trans(self):
+        self.input_trans = self.input_trans_stack.pop()
+
+    def pos2xy(self, pos):
+        """Return the x, y coordinates of position 'pos'."""
+        # this *is* incomprehensible, yes.
+        y = 0
+        assert 0 <= pos <= len(self.buffer)
+        if pos == len(self.buffer):
+            y = len(self.screeninfo) - 1
+            p, l2 = self.screeninfo[y]
+            return p + len(l2) - 1, y
+        else:
+            for p, l2 in self.screeninfo:
+                l = l2.count(1)
+                if l > pos:
+                    break
+                else:
+                    pos -= l
+                    y += 1
+            c = 0
+            i = 0
+            while c < pos:
+                c += l2[i]
+                i += 1
+            while l2[i] == 0:
+                i += 1
+            return p + i, y
+
+    def insert(self, text):
+        """Insert 'text' at the insertion point."""
+        self.buffer[self.pos:self.pos] = list(text)
+        self.pos += len(text)
+        self.dirty = 1
+
+    def update_cursor(self):
+        """Move the cursor to reflect changes in self.pos"""
+        self.cxy = self.pos2xy(self.pos)
+        self.console.move_cursor(*self.cxy)
+
+    def after_command(self, cmd):
+        """This function is called to allow post command cleanup."""
+        if getattr(cmd, "kills_digit_arg", 1):
+            if self.arg is not None:
+                self.dirty = 1                
+            self.arg = None
+
+    def prepare(self):
+        """Get ready to run.  Call restore when finished.  You must not
+        write to the console in between the calls to prepare and
+        restore."""
+        try:
+            self.console.prepare()
+            self.arg = None
+            self.screeninfo = []
+            self.finished = 0
+            del self.buffer[:]
+            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])
+        except:
+            self.restore()
+            raise
+
+    def last_command_is(self, klass):
+        if not self.last_command:
+            return 0
+        return issubclass(klass, self.last_command)
+
+    def restore(self):
+        """Clean up after a run."""
+        self.console.restore()
+
+    def finish(self):
+        """Called when a command signals that we're finished."""
+        pass
+
+    def error(self, msg="none"):
+        self.msg = "! " + msg + " "
+        self.dirty = 1
+        self.console.beep()
+
+    def update_screen(self):
+        if self.dirty:
+            self.refresh()
+
+    def refresh(self):
+        """Recalculate and refresh the screen."""
+        # this call sets up self.cxy, so call it first.
+        screen = self.calc_screen()
+        self.console.refresh(screen, self.cxy)
+        self.dirty = 0 # forgot this for a while (blush)
+
+    def do_cmd(self, cmd):
+        #print cmd
+        if isinstance(cmd[0], str):
+            cmd = self.commands.get(cmd[0],
+                                    commands.invalid_command)(self, cmd)
+        elif isinstance(cmd[0], type):
+            cmd = cmd[0](self, cmd)
+
+        cmd.do()
+
+        self.after_command(cmd)
+
+        if self.dirty:
+            self.refresh()
+        else:
+            self.update_cursor()
+
+        if not isinstance(cmd, commands.digit_arg):
+            self.last_command = cmd.__class__
+
+        self.finished = cmd.finish
+        if self.finished:
+            self.console.finish()
+            self.finish()
+
+    def handle1(self, block=1):
+        """Handle a single event.  Wait as long as it takes if block
+        is true (the default), otherwise return None if no event is
+        pending."""
+
+        if self.msg:
+            self.msg = ''
+            self.dirty = 1
+
+        while 1:
+            event = self.console.get_event(block)
+            if not event: # can only happen if we're not blocking
+                return None
+
+            if event.evt == 'key':
+                self.input_trans.push(event)
+            elif event.evt == 'scroll':
+                self.refresh()
+            elif event.evt == 'resize':
+                self.refresh()
+            else:
+                pass
+
+            cmd = self.input_trans.get()
+
+            if cmd is None:
+                if block:
+                    continue
+                else:
+                    return None
+
+            self.do_cmd(cmd)
+            return 1
+
+    def push_char(self, char):
+        self.console.push_char(char)
+        self.handle1(0)
+    
+    def readline(self):
+        """Read a line.  The implementation of this method also shows
+        how to drive Reader if you want more control over the event
+        loop."""
+        self.prepare()
+        try:
+            self.refresh()
+            while not self.finished:
+                self.handle1()
+            return self.get_buffer()
+        finally:
+            self.restore()
+
+    def bind(self, spec, command):
+        self.keymap = self.keymap + ((spec, command),)
+        self.input_trans = input.KeymapTranslator(
+            self.keymap,
+            invalid_cls='invalid-key',
+            character_cls='self-insert')
+
+    def get_buffer(self, encoding=None):
+        if encoding is None:
+            encoding = self.console.encoding
+        return u''.join(self.buffer).encode(self.console.encoding)
+
+    def get_unicode(self):
+        """Return the current buffer as a unicode string."""
+        return u''.join(self.buffer)
+
+def test():
+    from pyrepl.unix_console import UnixConsole
+    reader = Reader(UnixConsole())
+    reader.ps1 = "**> "
+    reader.ps2 = "/*> "
+    reader.ps3 = "|*> "
+    reader.ps4 = "\*> "
+    while reader.readline():
+        pass
+
+if __name__=='__main__':
+    test()

diff --git a/pypy/translator/unsimplify.py b/pypy/translator/unsimplify.py
--- a/pypy/translator/unsimplify.py
+++ b/pypy/translator/unsimplify.py
@@ -54,8 +54,7 @@
 def split_block(annotator, block, index, _forcelink=None):
     """return a link where prevblock is the block leading up but excluding the
     index'th operation and target is a new block with the neccessary variables 
-    passed on.  NOTE: if you call this after rtyping, you WILL need to worry
-    about keepalives, you may use backendopt.support.split_block_with_keepalive.
+    passed on.
     """
     assert 0 <= index <= len(block.operations)
     if block.exitswitch == c_last_exception:
@@ -115,46 +114,6 @@
     # in the second block!
     return split_block(annotator, block, 0, _forcelink=block.inputargs)
 
-def remove_direct_loops(annotator, graph):
-    """This is useful for code generators: it ensures that no link has
-    common input and output variables, which could occur if a block's exit
-    points back directly to the same block.  It allows code generators to be
-    simpler because they don't have to worry about overwriting input
-    variables when generating a sequence of assignments."""
-    def visit(link):
-        if isinstance(link, Link) and link.prevblock is link.target:
-            insert_empty_block(annotator, link)
-    traverse(visit, graph)
-
-def remove_double_links(annotator, graph):
-    """This can be useful for code generators: it ensures that no block has
-    more than one incoming links from one and the same other block. It allows
-    argument passing along links to be implemented with phi nodes since the
-    value of an argument can be determined by looking from which block the
-    control passed. """
-    def visit(block):
-        if isinstance(block, Block):
-            double_links = []
-            seen = {}
-            for link in block.exits:
-                if link.target in seen:
-                    double_links.append(link)
-                seen[link.target] = True
-            for link in double_links:
-                insert_empty_block(annotator, link)
-    traverse(visit, graph)
-
-def no_links_to_startblock(graph):
-    """Ensure no links to start block."""    
-    links_to_start_block = False
-    for block in graph.iterblocks():
-        for link in block.exits:
-            if link.target == graph.startblock:
-                links_to_start_block = True
-                break
-    if links_to_start_block:
-        insert_empty_startblock(None, graph)
-
 def call_initial_function(translator, initial_func, annhelper=None):
     """Before the program starts, call 'initial_func()'."""
     from pypy.annotation import model as annmodel

diff --git a/pypy/module/cpyext/test/test_unicodeobject.py b/pypy/module/cpyext/test/test_unicodeobject.py
--- a/pypy/module/cpyext/test/test_unicodeobject.py
+++ b/pypy/module/cpyext/test/test_unicodeobject.py
@@ -1,9 +1,81 @@
 # encoding: iso-8859-15
 from pypy.module.cpyext.test.test_api import BaseApiTest
-from pypy.module.cpyext.unicodeobject import Py_UNICODE
+from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
+from pypy.module.cpyext.unicodeobject import (
+    Py_UNICODE, PyUnicodeObject, new_empty_unicode)
+from pypy.module.cpyext.api import PyObjectP, PyObject
+from pypy.module.cpyext.pyobject import Py_DecRef
 from pypy.rpython.lltypesystem import rffi, lltype
 import sys, py
 
+class AppTestUnicodeObject(AppTestCpythonExtensionBase):
+    def test_unicodeobject(self):
+        module = self.import_extension('foo', [
+            ("get_hello1", "METH_NOARGS",
+             """
+                 return PyUnicode_FromStringAndSize(
+                     "Hello world<should not be included>", 11);
+             """),
+            ("test_GetSize", "METH_NOARGS",
+             """
+                 PyObject* s = PyUnicode_FromString("Hello world");
+                 int result = 0;
+
+                 if(PyUnicode_GetSize(s) == 11) {
+                     result = 1;
+                 }
+                 if(s->ob_type->tp_basicsize != sizeof(void*)*4)
+                     result = 0;
+                 Py_DECREF(s);
+                 return PyBool_FromLong(result);
+             """),
+            ("test_GetSize_exception", "METH_NOARGS",
+             """
+                 PyObject* f = PyFloat_FromDouble(1.0);
+                 Py_ssize_t size = PyUnicode_GetSize(f);
+
+                 Py_DECREF(f);
+                 return NULL;
+             """),
+             ("test_is_unicode", "METH_VARARGS",
+             """
+                return PyBool_FromLong(PyUnicode_Check(PyTuple_GetItem(args, 0)));
+             """)])
+        assert module.get_hello1() == u'Hello world'
+        assert module.test_GetSize()
+        raises(TypeError, module.test_GetSize_exception)
+
+        assert module.test_is_unicode(u"")
+        assert not module.test_is_unicode(())
+
+    def test_unicode_buffer_init(self):
+        module = self.import_extension('foo', [
+            ("getunicode", "METH_NOARGS",
+             """
+                 PyObject *s, *t;
+                 Py_UNICODE* c;
+                 Py_ssize_t len;
+
+                 s = PyUnicode_FromUnicode(NULL, 4);
+                 if (s == NULL)
+                    return NULL;
+                 t = PyUnicode_FromUnicode(NULL, 3);
+                 if (t == NULL)
+                    return NULL;
+                 Py_DECREF(t);
+                 c = PyUnicode_AsUnicode(s);
+                 c[0] = 'a';
+                 c[1] = 0xe9;
+                 c[3] = 'c';
+                 return s;
+             """),
+            ])
+        s = module.getunicode()
+        assert len(s) == 4
+        assert s == u'a&#65533;\x00c'
+
+
+
 class TestUnicode(BaseApiTest):
     def test_unicodeobject(self, space, api):
         assert api.PyUnicode_GET_SIZE(space.wrap(u'sp&#65533;m')) == 4
@@ -77,6 +149,28 @@
         assert space.unwrap(w_res) == u'sp&#65533;'
         rffi.free_charp(s)
 
+    def test_unicode_resize(self, space, api):
+        py_uni = new_empty_unicode(space, 10)
+        ar = lltype.malloc(PyObjectP.TO, 1, flavor='raw')
+        py_uni.c_buffer[0] = u'a'
+        py_uni.c_buffer[1] = u'b'
+        py_uni.c_buffer[2] = u'c'
+        ar[0] = rffi.cast(PyObject, py_uni)
+        api.PyUnicode_Resize(ar, 3)
+        py_uni = rffi.cast(PyUnicodeObject, ar[0])
+        assert py_uni.c_size == 3
+        assert py_uni.c_buffer[1] == u'b'
+        assert py_uni.c_buffer[3] == u'\x00'
+        # the same for growing
+        ar[0] = rffi.cast(PyObject, py_uni)
+        api.PyUnicode_Resize(ar, 10)
+        py_uni = rffi.cast(PyUnicodeObject, ar[0])
+        assert py_uni.c_size == 10
+        assert py_uni.c_buffer[1] == 'b'
+        assert py_uni.c_buffer[10] == '\x00'
+        Py_DecRef(space, ar[0])
+        lltype.free(ar, flavor='raw')
+
     def test_AsUTF8String(self, space, api):
         w_u = space.wrap(u'sp&#65533;m')
         w_res = api.PyUnicode_AsUTF8String(w_u)
@@ -235,13 +329,13 @@
 
         x_chunk = api.PyUnicode_AS_UNICODE(w_x)
         api.Py_UNICODE_COPY(target_chunk, x_chunk, 4)
-        w_y = api.PyUnicode_FromUnicode(target_chunk, 4)
+        w_y = space.wrap(rffi.wcharpsize2unicode(target_chunk, 4))
 
         assert space.eq_w(w_y, space.wrap(u"abcd"))
 
         size = api.PyUnicode_GET_SIZE(w_x)
         api.Py_UNICODE_COPY(target_chunk, x_chunk, size)
-        w_y = api.PyUnicode_FromUnicode(target_chunk, size)
+        w_y = space.wrap(rffi.wcharpsize2unicode(target_chunk, size))
 
         assert space.eq_w(w_y, w_x)
 

diff --git a/pypy/objspace/std/listobject.py b/pypy/objspace/std/listobject.py
--- a/pypy/objspace/std/listobject.py
+++ b/pypy/objspace/std/listobject.py
@@ -36,29 +36,35 @@
 init_defaults = Defaults([None])
 
 def init__List(space, w_list, __args__):
+    from pypy.objspace.std.tupleobject import W_TupleObject
     # this is on the silly side
     w_iterable, = __args__.parse_obj(
             None, 'list', init_signature, init_defaults)
-    #
-    # this is the old version of the loop at the end of this function:
-    #
-    #   w_list.wrappeditems = space.unpackiterable(w_iterable)
-    #
-    # This is commented out to avoid assigning a new RPython list to
-    # 'wrappeditems', which defeats the W_FastSeqIterObject optimization.
-    #
     items_w = w_list.wrappeditems
     del items_w[:]
     if w_iterable is not None:
-        w_iterator = space.iter(w_iterable)
-        while True:
-            try:
-                w_item = space.next(w_iterator)
-            except OperationError, e:
-                if not e.match(space, space.w_StopIteration):
-                    raise
-                break  # done
-            items_w.append(w_item)
+        # unfortunately this is duplicating space.unpackiterable to avoid
+        # assigning a new RPython list to 'wrappeditems', which defeats the
+        # W_FastSeqIterObject optimization.
+        if isinstance(w_iterable, W_ListObject):
+            items_w.extend(w_iterable.wrappeditems)
+        elif isinstance(w_iterable, W_TupleObject):
+            items_w.extend(w_iterable.wrappeditems)
+        else:
+            _init_from_iterable(space, items_w, w_iterable)
+
+def _init_from_iterable(space, items_w, w_iterable):
+    # in its own function to make the JIT look into init__List
+    # XXX this would need a JIT driver somehow?
+    w_iterator = space.iter(w_iterable)
+    while True:
+        try:
+            w_item = space.next(w_iterator)
+        except OperationError, e:
+            if not e.match(space, space.w_StopIteration):
+                raise
+            break  # done
+        items_w.append(w_item)
 
 def len__List(space, w_list):
     result = len(w_list.wrappeditems)

diff --git a/pypy/module/cpyext/include/compile.h b/pypy/module/cpyext/include/compile.h
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/include/compile.h
@@ -0,0 +1,13 @@
+#ifndef Py_COMPILE_H
+#define Py_COMPILE_H
+
+#include "code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_COMPILE_H */

diff --git a/pypy/module/cpyext/include/import.h b/pypy/module/cpyext/include/import.h
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/include/import.h
@@ -0,0 +1,1 @@
+/* empty */

diff --git a/lib_pypy/pyrepl/python_reader.py b/lib_pypy/pyrepl/python_reader.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/python_reader.py
@@ -0,0 +1,392 @@
+#   Copyright 2000-2007 Michael Hudson-Doyle <micahel at gmail.com>
+#                       Bob Ippolito
+#                       Maciek Fijalkowski
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+# one impressive collections of imports:
+from pyrepl.completing_reader import CompletingReader
+from pyrepl.historical_reader import HistoricalReader
+from pyrepl import completing_reader, reader
+from pyrepl import copy_code, commands, completer
+from pyrepl import module_lister
+import new, sys, os, re, code, traceback
+import atexit, warnings
+try:
+    import cPickle as pickle
+except ImportError:
+    import pickle
+try:
+    import imp
+    imp.find_module("twisted")
+    from twisted.internet import reactor
+    from twisted.internet.abstract import FileDescriptor
+except ImportError:
+    default_interactmethod = "interact"
+else:
+    default_interactmethod = "twistedinteract"
+
+CommandCompiler = code.CommandCompiler
+
+def eat_it(*args):
+    """this function eats warnings, if you were wondering"""
+    pass
+
+class maybe_accept(commands.Command):
+    def do(self):
+        r = self.reader
+        text = r.get_unicode()
+        try:
+            # ooh, look at the hack:
+            code = r.compiler("#coding:utf-8\n"+text.encode('utf-8'))
+        except (OverflowError, SyntaxError, ValueError):
+            self.finish = 1
+        else:
+            if code is None:
+                r.insert("\n")
+            else:
+                self.finish = 1
+
+from_line_prog = re.compile(
+    "^from\s+(?P<mod>[A-Za-z_.0-9]*)\s+import\s+(?P<name>[A-Za-z_.0-9]*)")
+import_line_prog = re.compile(
+    "^(?:import|from)\s+(?P<mod>[A-Za-z_.0-9]*)\s*$")
+
+def mk_saver(reader):
+    def saver(reader=reader):
+        try:
+            file = open(os.path.expanduser("~/.pythoni.hist"), "w")
+        except IOError:
+            pass
+        else:
+            pickle.dump(reader.history, file)
+            file.close()
+    return saver
+
+class PythonicReader(CompletingReader, HistoricalReader):
+    def collect_keymap(self):
+        return super(PythonicReader, self).collect_keymap() + (
+            (r'\n', 'maybe-accept'),
+            (r'\M-\n', 'insert-nl'))
+    
+    def __init__(self, console, locals,
+                 compiler=None):
+        super(PythonicReader, self).__init__(console)
+        self.completer = completer.Completer(locals)
+        st = self.syntax_table
+        for c in "._0123456789":
+            st[c] = reader.SYNTAX_WORD
+        self.locals = locals
+        if compiler is None:
+            self.compiler = CommandCompiler()
+        else:
+            self.compiler = compiler
+        try:
+            file = open(os.path.expanduser("~/.pythoni.hist"))
+        except IOError:
+            pass
+        else:
+            try:
+                self.history = pickle.load(file)
+            except:
+                self.history = []
+            self.historyi = len(self.history)
+            file.close()
+        atexit.register(mk_saver(self))
+        for c in [maybe_accept]:
+            self.commands[c.__name__] = c
+            self.commands[c.__name__.replace('_', '-')] = c        
+    
+    def get_completions(self, stem):
+        b = self.get_unicode()
+        m = import_line_prog.match(b)
+        if m:
+            if not self._module_list_ready:
+                module_lister._make_module_list()
+                self._module_list_ready = True
+
+            mod = m.group("mod")
+            try:
+                return module_lister.find_modules(mod)
+            except ImportError:
+                pass
+        m = from_line_prog.match(b)
+        if m:
+            mod, name = m.group("mod", "name")
+            try:
+                l = module_lister._packages[mod]
+            except KeyError:
+                try:
+                    mod = __import__(mod, self.locals, self.locals, [''])
+                    return [x for x in dir(mod) if x.startswith(name)]
+                except ImportError:
+                    pass
+            else:
+                return [x[len(mod) + 1:]
+                        for x in l if x.startswith(mod + '.' + name)]
+        try:
+            l = completing_reader.uniqify(self.completer.complete(stem))
+            return l
+        except (NameError, AttributeError):
+            return []
+
+class ReaderConsole(code.InteractiveInterpreter):
+    II_init = code.InteractiveInterpreter.__init__
+    def __init__(self, console, locals=None):
+        if locals is None:
+            locals = {}
+        self.II_init(locals)
+        self.compiler = CommandCompiler()
+        self.compile = self.compiler.compiler
+        self.reader = PythonicReader(console, locals, self.compiler)
+        locals['Reader'] = self.reader
+
+    def run_user_init_file(self):
+        for key in "PYREPLSTARTUP", "PYTHONSTARTUP":
+            initfile = os.environ.get(key)
+            if initfile is not None and os.path.exists(initfile):
+                break
+        else:
+            return
+        try:
+            execfile(initfile, self.locals, self.locals)
+        except:
+            etype, value, tb = sys.exc_info()
+            traceback.print_exception(etype, value, tb.tb_next)
+
+    def execute(self, text):
+        try:
+            # ooh, look at the hack:            
+            code = self.compile("# coding:utf8\n"+text.encode('utf-8'),
+                                '<input>', 'single')
+        except (OverflowError, SyntaxError, ValueError):
+            self.showsyntaxerror("<input>")
+        else:
+            self.runcode(code)
+            sys.stdout.flush()
+
+    def interact(self):
+        while 1:
+            try: # catches EOFError's and KeyboardInterrupts during execution
+                try: # catches KeyboardInterrupts during editing
+                    try: # warning saver
+                        # can't have warnings spewed onto terminal
+                        sv = warnings.showwarning
+                        warnings.showwarning = eat_it
+                        l = unicode(self.reader.readline(), 'utf-8')
+                    finally:
+                        warnings.showwarning = sv
+                except KeyboardInterrupt:
+                    print "KeyboardInterrupt"
+                else:
+                    if l:
+                        self.execute(l)
+            except EOFError:
+                break
+            except KeyboardInterrupt:
+                continue
+
+    def prepare(self):
+        self.sv_sw = warnings.showwarning
+        warnings.showwarning = eat_it
+        self.reader.prepare()
+        self.reader.refresh() # we want :after methods...
+
+    def restore(self):
+        self.reader.restore()
+        warnings.showwarning = self.sv_sw
+
+    def handle1(self, block=1):
+        try:
+            r = 1
+            r = self.reader.handle1(block)
+        except KeyboardInterrupt:
+            self.restore()
+            print "KeyboardInterrupt"
+            self.prepare()
+        else:
+            if self.reader.finished:
+                text = self.reader.get_unicode()
+                self.restore()
+                if text:
+                    self.execute(text)
+                self.prepare()
+        return r
+
+    def tkfilehandler(self, file, mask):
+        try:
+            self.handle1(block=0)
+        except:
+            self.exc_info = sys.exc_info()
+
+    # how the <expletive> do you get this to work on Windows (without
+    # createfilehandler)?  threads, I guess
+    def really_tkinteract(self):
+        import _tkinter
+        _tkinter.createfilehandler(
+            self.reader.console.input_fd, _tkinter.READABLE,
+            self.tkfilehandler)
+        
+        self.exc_info = None
+        while 1:
+            # dooneevent will return 0 without blocking if there are
+            # no Tk windows, 1 after blocking until an event otherwise
+            # so the following does what we want (this wasn't expected
+            # to be obvious).
+            if not _tkinter.dooneevent(_tkinter.ALL_EVENTS):
+                self.handle1(block=1)
+            if self.exc_info:
+                type, value, tb = self.exc_info
+                self.exc_info = None
+                raise type, value, tb
+        
+    def tkinteract(self):
+        """Run a Tk-aware Python interactive session.
+
+        This function simulates the Python top-level in a way that
+        allows Tk's mainloop to run."""
+        
+        # attempting to understand the control flow of this function
+        # without help may cause internal injuries.  so, some
+        # explanation.
+
+        # The outer while loop is there to restart the interaction if
+        # the user types control-c when execution is deep in our
+        # innards.  I'm not sure this can't leave internals in an
+        # inconsistent state, but it's a good start.
+
+        # then the inside loop keeps calling self.handle1 until
+        # _tkinter gets imported; then control shifts to
+        # self.really_tkinteract, above.
+
+        # this function can only return via an exception; we mask
+        # EOFErrors (but they end the interaction) and
+        # KeyboardInterrupts cause a restart.  All other exceptions
+        # are likely bugs in pyrepl (well, 'cept for SystemExit, of
+        # course).
+        
+        while 1:
+            try:
+                try:
+                    self.prepare()
+                    try:
+                        while 1:
+                            if sys.modules.has_key("_tkinter"):
+                                self.really_tkinteract()
+                                # really_tkinteract is not expected to
+                                # return except via an exception, but:
+                                break
+                            self.handle1()
+                    except EOFError:
+                        pass
+                finally:
+                    self.restore()
+            except KeyboardInterrupt:
+                continue
+            else:
+                break
+
+    def twistedinteract(self):
+        from twisted.internet import reactor
+        from twisted.internet.abstract import FileDescriptor
+        import signal
+        outerself = self
+        class Me(FileDescriptor):
+            def fileno(self):
+                """ We want to select on FD 0 """
+                return 0
+
+            def doRead(self):
+                """called when input is ready"""
+                try:
+                    outerself.handle1()
+                except EOFError:
+                    reactor.stop()
+
+        reactor.addReader(Me())
+        reactor.callWhenRunning(signal.signal,
+                                signal.SIGINT,
+                                signal.default_int_handler)
+        self.prepare()
+        try:
+            reactor.run()
+        finally:
+            self.restore()
+        
+
+    def cocoainteract(self, inputfilehandle=None, outputfilehandle=None):
+        # only call this when there's a run loop already going!
+        # note that unlike the other *interact methods, this returns immediately
+        from cocoasupport import CocoaInteracter
+        self.cocoainteracter = CocoaInteracter.alloc().init(self, inputfilehandle, outputfilehandle)
+        
+        
+def main(use_pygame_console=0, interactmethod=default_interactmethod, print_banner=True, clear_main=True):
+    si, se, so = sys.stdin, sys.stderr, sys.stdout
+    try:
+        if 0 and use_pygame_console: # pygame currently borked
+            from pyrepl.pygame_console import PyGameConsole, FakeStdin, FakeStdout
+            con = PyGameConsole()
+            sys.stderr = sys.stdout = FakeStdout(con)
+            sys.stdin = FakeStdin(con)
+        else:
+            from pyrepl.unix_console import UnixConsole
+            try:
+                import locale
+            except ImportError:
+                encoding = None
+            else:
+                if hasattr(locale, 'nl_langinfo') \
+                       and hasattr(locale, 'CODESET'):
+                    encoding = locale.nl_langinfo(locale.CODESET)
+                elif os.environ.get('TERM_PROGRAM') == 'Apple_Terminal':
+                    # /me whistles innocently...
+                    code = int(os.popen(
+                        "defaults read com.apple.Terminal StringEncoding"
+                        ).read())
+                    if code == 4:
+                        encoding = 'utf-8'
+                        # More could go here -- and what's here isn't
+                        # bulletproof.  What would be?  AppleScript?
+                        # Doesn't seem to be possible.
+                    else:
+                        encoding = None
+                else:
+                    encoding = None # so you get ASCII...
+            con = UnixConsole(0, 1, None, encoding)
+        if print_banner:
+            print "Python", sys.version, "on", sys.platform
+            print 'Type "help", "copyright", "credits" or "license" '\
+                  'for more information.'
+        sys.path.insert(0, os.getcwd())
+
+        if clear_main and __name__ != '__main__':
+            mainmod = new.module('__main__')
+            sys.modules['__main__'] = mainmod
+        else:
+            mainmod = sys.modules['__main__']
+
+        rc = ReaderConsole(con, mainmod.__dict__)
+        rc.reader._module_list_ready = False
+        rc.run_user_init_file()
+        getattr(rc, interactmethod)()
+    finally:
+        sys.stdin, sys.stderr, sys.stdout = si, se, so
+
+if __name__ == '__main__':
+    main()

diff --git a/pypy/translator/backendopt/test/test_ssa.py b/pypy/translator/backendopt/test/test_ssa.py
--- a/pypy/translator/backendopt/test/test_ssa.py
+++ b/pypy/translator/backendopt/test/test_ssa.py
@@ -1,6 +1,6 @@
 from pypy.translator.backendopt.ssa import *
 from pypy.translator.translator import TranslationContext
-from pypy.objspace.flow.model import flatten, Block, Link, Variable, Constant
+from pypy.objspace.flow.model import Block, Link, Variable, Constant
 from pypy.objspace.flow.model import SpaceOperation
 
 

diff --git a/pypy/module/cpyext/pyfile.py b/pypy/module/cpyext/pyfile.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/pyfile.py
@@ -0,0 +1,68 @@
+from pypy.rpython.lltypesystem import rffi, lltype
+from pypy.module.cpyext.api import (
+    cpython_api, CONST_STRING, FILEP, build_type_checkers)
+from pypy.module.cpyext.pyobject import (
+    PyObject)
+from pypy.interpreter.error import OperationError
+from pypy.module._file.interp_file import W_File
+
+PyFile_Check, PyFile_CheckExact = build_type_checkers("File", W_File)
+
+ at cpython_api([PyObject, rffi.INT_real], PyObject)
+def PyFile_GetLine(space, w_obj, n):
+    """
+    Equivalent to p.readline([n]), this function reads one line from the
+    object p.  p may be a file object or any object with a readline()
+    method.  If n is 0, exactly one line is read, regardless of the length of
+    the line.  If n is greater than 0, no more than n bytes will be read
+    from the file; a partial line can be returned.  In both cases, an empty string
+    is returned if the end of the file is reached immediately.  If n is less than
+    0, however, one line is read regardless of length, but EOFError is
+    raised if the end of the file is reached immediately."""
+    try:
+        w_readline = space.getattr(w_obj, space.wrap('readline'))
+    except OperationError:
+        raise OperationError(
+            space.w_TypeError, space.wrap(
+            "argument must be a file, or have a readline() method."))
+
+    n = rffi.cast(lltype.Signed, n)
+    if space.is_true(space.gt(space.wrap(n), space.wrap(0))):
+        return space.call_function(w_readline, space.wrap(n))
+    elif space.is_true(space.lt(space.wrap(n), space.wrap(0))):
+        return space.call_function(w_readline)
+    else:
+        # XXX Raise EOFError as specified
+        return space.call_function(w_readline)
+
+ at cpython_api([CONST_STRING, CONST_STRING], PyObject)
+def PyFile_FromString(space, filename, mode):
+    """
+    On success, return a new file object that is opened on the file given by
+    filename, with a file mode given by mode, where mode has the same
+    semantics as the standard C routine fopen().  On failure, return NULL."""
+    w_filename = space.wrap(rffi.charp2str(filename))
+    w_mode = space.wrap(rffi.charp2str(mode))
+    return space.call_method(space.builtin, 'file', w_filename, w_mode)
+
+ at cpython_api([FILEP, CONST_STRING, CONST_STRING, rffi.VOIDP], PyObject)
+def PyFile_FromFile(space, fp, name, mode, close):
+    """Create a new PyFileObject from the already-open standard C file
+    pointer, fp.  The function close will be called when the file should be
+    closed.  Return NULL on failure."""
+    raise NotImplementedError
+
+ at cpython_api([PyObject, rffi.INT_real], lltype.Void)
+def PyFile_SetBufSize(space, w_file, n):
+    """Available on systems with setvbuf() only.  This should only be called
+    immediately after file object creation."""
+    raise NotImplementedError
+
+ at cpython_api([CONST_STRING, PyObject], rffi.INT_real, error=-1)
+def PyFile_WriteString(space, s, w_p):
+    """Write string s to file object p.  Return 0 on success or -1 on
+    failure; the appropriate exception will be set."""
+    w_s = space.wrap(rffi.charp2str(s))
+    space.call_method(w_p, "write", w_s)
+    return 0
+

diff --git a/lib_pypy/pyrepl/pygame_console.py b/lib_pypy/pyrepl/pygame_console.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/pygame_console.py
@@ -0,0 +1,353 @@
+#   Copyright 2000-2004 Michael Hudson-Doyle <micahel at gmail.com>
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+# the pygame console is currently thoroughly broken.
+
+# there's a fundamental difference from the UnixConsole: here we're
+# the terminal emulator too, in effect.  This means, e.g., for pythoni
+# we really need a separate process (or thread) to monitor for ^C
+# during command execution and zap the executor process.  Making this
+# work on non-Unix is expected to be even more entertaining.
+
+from pygame.locals import *
+from pyrepl.console import Console, Event
+from pyrepl import pygame_keymap
+import pygame
+import types
+
+lmargin = 5
+rmargin = 5
+tmargin = 5
+bmargin = 5
+
+try:
+    bool
+except NameError:
+    def bool(x):
+        return not not x
+
+modcolors = {K_LCTRL:1,
+             K_RCTRL:1,
+             K_LMETA:1,
+             K_RMETA:1,
+             K_LALT:1,
+             K_RALT:1,
+             K_LSHIFT:1,
+             K_RSHIFT:1}
+
+class colors:
+    fg = 250,240,230
+    bg = 5, 5, 5
+    cursor = 230, 0, 230
+    margin = 5, 5, 15
+
+class FakeStdout:
+    def __init__(self, con):
+        self.con = con
+    def write(self, text):
+        self.con.write(text)
+    def flush(self):
+        pass
+
+class FakeStdin:
+    def __init__(self, con):
+        self.con = con
+    def read(self, n=None):
+        # argh!
+        raise NotImplementedError
+    def readline(self, n=None):
+        from reader import Reader
+        try:
+            # this isn't quite right: it will clobber any prompt that's
+            # been printed.  Not sure how to get around this...
+            return Reader(self.con).readline()
+        except EOFError:
+            return ''
+
+class PyGameConsole(Console):
+    """Attributes:
+
+    (keymap),
+    (fd),
+    screen,
+    height,
+    width,
+    """
+    
+    def __init__(self):
+        self.pygame_screen = pygame.display.set_mode((800, 600))
+        pygame.font.init()
+        pygame.key.set_repeat(500, 30)
+        self.font = pygame.font.Font(
+            "/usr/X11R6/lib/X11/fonts/TTF/luximr.ttf", 15)
+        self.fw, self.fh = self.fontsize = self.font.size("X")
+        self.cursor = pygame.Surface(self.fontsize)
+        self.cursor.fill(colors.cursor)
+        self.clear()
+        self.curs_vis = 1
+        self.height, self.width = self.getheightwidth()
+        pygame.display.update()
+        pygame.event.set_allowed(None)
+        pygame.event.set_allowed(KEYDOWN)
+        
+    def install_keymap(self, keymap):
+        """Install a given keymap.
+
+        keymap is a tuple of 2-element tuples; each small tuple is a
+        pair (keyspec, event-name).  The format for keyspec is
+        modelled on that used by readline (so read that manual for
+        now!)."""
+        self.k = self.keymap = pygame_keymap.compile_keymap(keymap)
+
+    def char_rect(self, x, y):
+        return self.char_pos(x, y), self.fontsize
+
+    def char_pos(self, x, y):
+        return (lmargin + x*self.fw,
+                tmargin + y*self.fh + self.cur_top + self.scroll)
+
+    def paint_margin(self):
+        s = self.pygame_screen
+        c = colors.margin
+        s.fill(c, [0, 0, 800, tmargin])
+        s.fill(c, [0, 0, lmargin, 600])
+        s.fill(c, [0, 600 - bmargin, 800, bmargin])
+        s.fill(c, [800 - rmargin, 0, lmargin, 600])
+
+    def refresh(self, screen, (cx, cy)):
+        self.screen = screen
+        self.pygame_screen.fill(colors.bg,
+                                [0, tmargin + self.cur_top + self.scroll,
+                                 800, 600])
+        self.paint_margin()
+
+        line_top = self.cur_top
+        width, height = self.fontsize
+        self.cxy = (cx, cy)
+        cp = self.char_pos(cx, cy)
+        if cp[1] < tmargin:
+            self.scroll = - (cy*self.fh + self.cur_top)
+            self.repaint()
+        elif cp[1] + self.fh > 600 - bmargin:
+            self.scroll += (600 - bmargin) - (cp[1] + self.fh)
+            self.repaint()
+        if self.curs_vis:
+            self.pygame_screen.blit(self.cursor, self.char_pos(cx, cy))
+        for line in screen:
+            if 0 <= line_top + self.scroll <= (600 - bmargin - tmargin - self.fh):
+                if line:
+                    ren = self.font.render(line, 1, colors.fg)
+                    self.pygame_screen.blit(ren, (lmargin,
+                                                  tmargin + line_top + self.scroll))
+            line_top += self.fh
+        pygame.display.update()
+
+    def prepare(self):
+        self.cmd_buf = ''
+        self.k = self.keymap
+        self.height, self.width = self.getheightwidth()
+        self.curs_vis = 1
+        self.cur_top = self.pos[0]
+        self.event_queue = []
+
+    def restore(self):
+        pass
+
+    def blit_a_char(self, linen, charn):
+        line = self.screen[linen]
+        if charn < len(line):
+            text = self.font.render(line[charn], 1, colors.fg)
+            self.pygame_screen.blit(text, self.char_pos(charn, linen))
+
+    def move_cursor(self, x, y):
+        cp = self.char_pos(x, y)
+        if cp[1] < tmargin or cp[1] + self.fh > 600 - bmargin:
+            self.event_queue.append(Event('refresh', '', ''))
+        else:
+            if self.curs_vis:
+                cx, cy = self.cxy
+                self.pygame_screen.fill(colors.bg, self.char_rect(cx, cy))
+                self.blit_a_char(cy, cx)
+                self.pygame_screen.blit(self.cursor, cp)
+                self.blit_a_char(y, x)
+                pygame.display.update()
+            self.cxy = (x, y)
+
+    def set_cursor_vis(self, vis):
+        self.curs_vis = vis
+        if vis:
+            self.move_cursor(*self.cxy)
+        else:
+            cx, cy = self.cxy
+            self.pygame_screen.fill(colors.bg, self.char_rect(cx, cy))
+            self.blit_a_char(cy, cx)
+            pygame.display.update()
+
+    def getheightwidth(self):
+        """Return (height, width) where height and width are the height
+        and width of the terminal window in characters."""
+        return ((600 - tmargin - bmargin)/self.fh,
+                (800 - lmargin - rmargin)/self.fw)
+
+    def tr_event(self, pyg_event):
+        shift = bool(pyg_event.mod & KMOD_SHIFT)
+        ctrl = bool(pyg_event.mod & KMOD_CTRL)
+        meta = bool(pyg_event.mod & (KMOD_ALT|KMOD_META))
+
+        try:
+            return self.k[(pyg_event.unicode, meta, ctrl)], pyg_event.unicode
+        except KeyError:
+            try:
+                return self.k[(pyg_event.key, meta, ctrl)], pyg_event.unicode
+            except KeyError:
+                return "invalid-key", pyg_event.unicode
+
+    def get_event(self, block=1):
+        """Return an Event instance.  Returns None if |block| is false
+        and there is no event pending, otherwise waits for the
+        completion of an event."""
+        while 1:
+            if self.event_queue:
+                return self.event_queue.pop(0)
+            elif block:
+                pyg_event = pygame.event.wait()
+            else:
+                pyg_event = pygame.event.poll()
+                if pyg_event.type == NOEVENT:
+                    return
+
+            if pyg_event.key in modcolors:
+                continue
+
+            k, c = self.tr_event(pyg_event)
+            self.cmd_buf += c.encode('ascii', 'replace')
+            self.k = k
+
+            if not isinstance(k, types.DictType):
+                e = Event(k, self.cmd_buf, [])
+                self.k = self.keymap
+                self.cmd_buf = ''
+                return e
+
+    def beep(self):
+        # uhh, can't be bothered now.
+        # pygame.sound.something, I guess.
+        pass
+
+    def clear(self):
+        """Wipe the screen"""
+        self.pygame_screen.fill(colors.bg)
+        #self.screen = []
+        self.pos = [0, 0]
+        self.grobs = []
+        self.cur_top = 0
+        self.scroll = 0
+
+    def finish(self):
+        """Move the cursor to the end of the display and otherwise get
+        ready for end.  XXX could be merged with restore?  Hmm."""
+        if self.curs_vis:
+            cx, cy = self.cxy
+            self.pygame_screen.fill(colors.bg, self.char_rect(cx, cy))
+            self.blit_a_char(cy, cx)
+        for line in self.screen:
+            self.write_line(line, 1)
+        if self.curs_vis:
+            self.pygame_screen.blit(self.cursor,
+                                    (lmargin + self.pos[1],
+                                     tmargin + self.pos[0] + self.scroll))
+        pygame.display.update()
+
+    def flushoutput(self):
+        """Flush all output to the screen (assuming there's some
+        buffering going on somewhere)"""
+        # no buffering here, ma'am (though perhaps there should be!)
+        pass
+
+    def forgetinput(self):
+        """Forget all pending, but not yet processed input."""
+        while pygame.event.poll().type <> NOEVENT:
+            pass
+    
+    def getpending(self):
+        """Return the characters that have been typed but not yet
+        processed."""
+        events = []
+        while 1:
+            event = pygame.event.poll()
+            if event.type == NOEVENT:
+                break
+            events.append(event)
+
+        return events
+
+    def wait(self):
+        """Wait for an event."""
+        raise Exception, "erp!"
+
+    def repaint(self):
+        # perhaps we should consolidate grobs?
+        self.pygame_screen.fill(colors.bg)
+        self.paint_margin()
+        for (y, x), surf, text in self.grobs:
+            if surf and 0 < y + self.scroll:
+                self.pygame_screen.blit(surf, (lmargin + x,
+                                               tmargin + y + self.scroll))
+        pygame.display.update()
+
+    def write_line(self, line, ret):
+        charsleft = (self.width*self.fw - self.pos[1])/self.fw
+        while len(line) > charsleft:
+            self.write_line(line[:charsleft], 1)
+            line = line[charsleft:]
+        if line:
+            ren = self.font.render(line, 1, colors.fg, colors.bg)
+            self.grobs.append((self.pos[:], ren, line))
+            self.pygame_screen.blit(ren,
+                                    (lmargin + self.pos[1],
+                                     tmargin + self.pos[0] + self.scroll))
+        else:
+            self.grobs.append((self.pos[:], None, line))
+        if ret:
+            self.pos[0] += self.fh
+            if tmargin + self.pos[0] + self.scroll + self.fh > 600 - bmargin:
+                self.scroll = 600 - bmargin - self.pos[0] - self.fh - tmargin
+                self.repaint()
+            self.pos[1] = 0
+        else:
+            self.pos[1] += self.fw*len(line)
+
+    def write(self, text):
+        lines = text.split("\n")
+        if self.curs_vis:
+            self.pygame_screen.fill(colors.bg,
+                                    (lmargin + self.pos[1],
+                                     tmargin + self.pos[0] + self.scroll,
+                                     self.fw, self.fh))
+        for line in lines[:-1]:
+            self.write_line(line, 1)
+        self.write_line(lines[-1], 0)
+        if self.curs_vis:
+            self.pygame_screen.blit(self.cursor,
+                                    (lmargin + self.pos[1],
+                                     tmargin + self.pos[0] + self.scroll))
+        pygame.display.update()
+
+    def flush(self):
+        pass

diff --git a/pypy/module/cpyext/test/test_api.py b/pypy/module/cpyext/test/test_api.py
--- a/pypy/module/cpyext/test/test_api.py
+++ b/pypy/module/cpyext/test/test_api.py
@@ -61,6 +61,12 @@
         except OperationError, e:
             print e.errorstr(self.space)
             raise
+
+        try:
+            del self.space.getexecutioncontext().cpyext_threadstate
+        except AttributeError:
+            pass
+
         if self.check_and_print_leaks():
             assert False, "Test leaks or loses object(s)."
 

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
@@ -19,7 +19,8 @@
 from pypy.jit.backend.llsupport.descr import BaseCallDescr, BaseSizeDescr
 from pypy.jit.backend.llsupport.regalloc import FrameManager, RegisterManager,\
      TempBox
-from pypy.jit.backend.x86.arch import WORD, FRAME_FIXED_SIZE, IS_X86_32, IS_X86_64
+from pypy.jit.backend.x86.arch import WORD, FRAME_FIXED_SIZE
+from pypy.jit.backend.x86.arch import IS_X86_32, IS_X86_64, MY_COPY_OF_REGS
 from pypy.rlib.rarithmetic import r_longlong, r_uint
 
 class X86RegisterManager(RegisterManager):
@@ -34,6 +35,12 @@
         esi: 2,
         edi: 3,
     }
+    REGLOC_TO_COPY_AREA_OFS = {
+        ecx: MY_COPY_OF_REGS + 0 * WORD,
+        ebx: MY_COPY_OF_REGS + 1 * WORD,
+        esi: MY_COPY_OF_REGS + 2 * WORD,
+        edi: MY_COPY_OF_REGS + 3 * WORD,
+    }
 
     def call_result_location(self, v):
         return eax
@@ -61,6 +68,19 @@
         r14: 4,
         r15: 5,
     }
+    REGLOC_TO_COPY_AREA_OFS = {
+        ecx: MY_COPY_OF_REGS + 0 * WORD,
+        ebx: MY_COPY_OF_REGS + 1 * WORD,
+        esi: MY_COPY_OF_REGS + 2 * WORD,
+        edi: MY_COPY_OF_REGS + 3 * WORD,
+        r8:  MY_COPY_OF_REGS + 4 * WORD,
+        r9:  MY_COPY_OF_REGS + 5 * WORD,
+        r10: MY_COPY_OF_REGS + 6 * WORD,
+        r12: MY_COPY_OF_REGS + 7 * WORD,
+        r13: MY_COPY_OF_REGS + 8 * WORD,
+        r14: MY_COPY_OF_REGS + 9 * WORD,
+        r15: MY_COPY_OF_REGS + 10 * WORD,
+    }
 
 class X86XMMRegisterManager(RegisterManager):
 
@@ -117,6 +137,16 @@
         else:
             return 1
 
+if WORD == 4:
+    gpr_reg_mgr_cls = X86RegisterManager
+    xmm_reg_mgr_cls = X86XMMRegisterManager
+elif WORD == 8:
+    gpr_reg_mgr_cls = X86_64_RegisterManager
+    xmm_reg_mgr_cls = X86_64_XMMRegisterManager
+else:
+    raise AssertionError("Word size should be 4 or 8")
+
+
 class RegAlloc(object):
 
     def __init__(self, assembler, translate_support_code=False):
@@ -126,6 +156,7 @@
         self.translate_support_code = translate_support_code
         # to be read/used by the assembler too
         self.jump_target_descr = None
+        self.close_stack_struct = 0
 
     def _prepare(self, inputargs, operations):
         self.fm = X86FrameManager()
@@ -135,16 +166,6 @@
         # compute longevity of variables
         longevity = self._compute_vars_longevity(inputargs, operations)
         self.longevity = longevity
-        # XXX
-        if cpu.WORD == 4:
-            gpr_reg_mgr_cls = X86RegisterManager
-            xmm_reg_mgr_cls = X86XMMRegisterManager
-        elif cpu.WORD == 8:
-            gpr_reg_mgr_cls = X86_64_RegisterManager
-            xmm_reg_mgr_cls = X86_64_XMMRegisterManager
-        else:
-            raise AssertionError("Word size should be 4 or 8")
-            
         self.rm = gpr_reg_mgr_cls(longevity,
                                   frame_manager = self.fm,
                                   assembler = self.assembler)
@@ -740,8 +761,12 @@
 
     def _call(self, op, arglocs, force_store=[], guard_not_forced_op=None):
         save_all_regs = guard_not_forced_op is not None
+        self.xrm.before_call(force_store, save_all_regs=save_all_regs)
+        if not save_all_regs:
+            gcrootmap = gc_ll_descr = self.assembler.cpu.gc_ll_descr.gcrootmap
+            if gcrootmap and gcrootmap.is_shadow_stack:
+                save_all_regs = 2
         self.rm.before_call(force_store, save_all_regs=save_all_regs)
-        self.xrm.before_call(force_store, save_all_regs=save_all_regs)
         if op.result is not None:
             if op.result.type == FLOAT:
                 resloc = self.xrm.after_call(op.result)
@@ -801,6 +826,11 @@
         self._consider_call(op, guard_op)
 
     def consider_call_release_gil(self, op, guard_op):
+        # first force the registers like eax into the stack, because of
+        # the initial call to _close_stack()
+        self.rm.before_call()
+        self.xrm.before_call()
+        #
         assert guard_op is not None
         self._consider_call(op, guard_op)
 
@@ -842,31 +872,53 @@
         self.PerformDiscard(op, arglocs)
         self.rm.possibly_free_vars_for_op(op)
 
-    def _fastpath_malloc(self, op, descr):
+    def fastpath_malloc_fixedsize(self, op, descr):
         assert isinstance(descr, BaseSizeDescr)
+        self._do_fastpath_malloc(op, descr.size, descr.tid)
+
+    def fastpath_malloc_varsize(self, op, arraydescr, num_elem):
+        assert isinstance(arraydescr, BaseArrayDescr)
+        ofs_length = arraydescr.get_ofs_length(self.translate_support_code)
+        basesize = arraydescr.get_base_size(self.translate_support_code)
+        itemsize = arraydescr.get_item_size(self.translate_support_code)
+        size = basesize + itemsize * num_elem
+        self._do_fastpath_malloc(op, size, arraydescr.tid)
+        self.assembler.set_new_array_length(eax, ofs_length, imm(num_elem))
+
+    def _do_fastpath_malloc(self, op, size, tid):
         gc_ll_descr = self.assembler.cpu.gc_ll_descr
         self.rm.force_allocate_reg(op.result, selected_reg=eax)
-        # We need to force-allocate each of save_around_call_regs now.
-        # The alternative would be to save and restore them around the
-        # actual call to malloc(), in the rare case where we need to do
-        # it; however, mark_gc_roots() would need to be adapted to know
-        # where the variables end up being saved.  Messy.
-        for reg in self.rm.save_around_call_regs:
-            if reg is not eax:
-                tmp_box = TempBox()
-                self.rm.force_allocate_reg(tmp_box, selected_reg=reg)
-                self.rm.possibly_free_var(tmp_box)
 
-        self.assembler.malloc_cond_fixedsize(
+        if gc_ll_descr.gcrootmap and gc_ll_descr.gcrootmap.is_shadow_stack:
+            # ---- shadowstack ----
+            # We need edx as a temporary, but otherwise don't save any more
+            # register.  See comments in _build_malloc_slowpath().
+            tmp_box = TempBox()
+            self.rm.force_allocate_reg(tmp_box, selected_reg=edx)
+            self.rm.possibly_free_var(tmp_box)
+        else:
+            # ---- asmgcc ----
+            # We need to force-allocate each of save_around_call_regs now.
+            # The alternative would be to save and restore them around the
+            # actual call to malloc(), in the rare case where we need to do
+            # it; however, mark_gc_roots() would need to be adapted to know
+            # where the variables end up being saved.  Messy.
+            for reg in self.rm.save_around_call_regs:
+                if reg is not eax:
+                    tmp_box = TempBox()
+                    self.rm.force_allocate_reg(tmp_box, selected_reg=reg)
+                    self.rm.possibly_free_var(tmp_box)
+
+        self.assembler.malloc_cond(
             gc_ll_descr.get_nursery_free_addr(),
             gc_ll_descr.get_nursery_top_addr(),
-            descr.size, descr.tid,
+            size, tid,
             )
 
     def consider_new(self, op):
         gc_ll_descr = self.assembler.cpu.gc_ll_descr
         if gc_ll_descr.can_inline_malloc(op.getdescr()):
-            self._fastpath_malloc(op, op.getdescr())
+            self.fastpath_malloc_fixedsize(op, op.getdescr())
         else:
             args = gc_ll_descr.args_for_new(op.getdescr())
             arglocs = [imm(x) for x in args]
@@ -876,7 +928,7 @@
         classint = op.getarg(0).getint()
         descrsize = heaptracker.vtable2descr(self.assembler.cpu, classint)
         if self.assembler.cpu.gc_ll_descr.can_inline_malloc(descrsize):
-            self._fastpath_malloc(op, descrsize)
+            self.fastpath_malloc_fixedsize(op, descrsize)
             self.assembler.set_vtable(eax, imm(classint))
             # result of fastpath malloc is in eax
         else:
@@ -935,16 +987,25 @@
         gc_ll_descr = self.assembler.cpu.gc_ll_descr
         if gc_ll_descr.get_funcptr_for_newarray is not None:
             # framework GC
-            args = self.assembler.cpu.gc_ll_descr.args_for_new_array(op.getdescr())
+            box_num_elem = op.getarg(0)
+            if isinstance(box_num_elem, ConstInt):
+                num_elem = box_num_elem.value
+                if gc_ll_descr.can_inline_malloc_varsize(op.getdescr(),
+                                                         num_elem):
+                    self.fastpath_malloc_varsize(op, op.getdescr(), num_elem)
+                    return
+            args = self.assembler.cpu.gc_ll_descr.args_for_new_array(
+                op.getdescr())
             arglocs = [imm(x) for x in args]
-            arglocs.append(self.loc(op.getarg(0)))
-            return self._call(op, arglocs)
+            arglocs.append(self.loc(box_num_elem))
+            self._call(op, arglocs)
+            return
         # boehm GC (XXX kill the following code at some point)
         itemsize, basesize, ofs_length, _, _ = (
             self._unpack_arraydescr(op.getdescr()))
         scale_of_field = _get_scale(itemsize)
-        return self._malloc_varsize(basesize, ofs_length, scale_of_field,
-                                    op.getarg(0), op.result)
+        self._malloc_varsize(basesize, ofs_length, scale_of_field,
+                             op.getarg(0), op.result)
 
     def _unpack_arraydescr(self, arraydescr):
         assert isinstance(arraydescr, BaseArrayDescr)
@@ -1138,7 +1199,7 @@
         # call memcpy()
         self.rm.before_call()
         self.xrm.before_call()
-        self.assembler._emit_call(imm(self.assembler.memcpy_addr),
+        self.assembler._emit_call(-1, imm(self.assembler.memcpy_addr),
                                   [dstaddr_loc, srcaddr_loc, length_loc])
         self.rm.possibly_free_var(length_box)
         self.rm.possibly_free_var(dstaddr_box)
@@ -1206,18 +1267,24 @@
     def consider_jit_debug(self, op):
         pass
 
-    def get_mark_gc_roots(self, gcrootmap):
+    def get_mark_gc_roots(self, gcrootmap, use_copy_area=False):
         shape = gcrootmap.get_basic_shape(IS_X86_64)
         for v, val in self.fm.frame_bindings.items():
             if (isinstance(v, BoxPtr) and self.rm.stays_alive(v)):
                 assert isinstance(val, StackLoc)
-                gcrootmap.add_ebp_offset(shape, get_ebp_ofs(val.position))
+                gcrootmap.add_frame_offset(shape, get_ebp_ofs(val.position))
         for v, reg in self.rm.reg_bindings.items():
             if reg is eax:
                 continue      # ok to ignore this one
             if (isinstance(v, BoxPtr) and self.rm.stays_alive(v)):
-                assert reg in self.rm.REGLOC_TO_GCROOTMAP_REG_INDEX
-                gcrootmap.add_callee_save_reg(shape, self.rm.REGLOC_TO_GCROOTMAP_REG_INDEX[reg])
+                if use_copy_area:
+                    assert reg in self.rm.REGLOC_TO_COPY_AREA_OFS
+                    area_offset = self.rm.REGLOC_TO_COPY_AREA_OFS[reg]
+                    gcrootmap.add_frame_offset(shape, area_offset)
+                else:
+                    assert reg in self.rm.REGLOC_TO_GCROOTMAP_REG_INDEX
+                    gcrootmap.add_callee_save_reg(
+                        shape, self.rm.REGLOC_TO_GCROOTMAP_REG_INDEX[reg])
         return gcrootmap.compress_callshape(shape,
                                             self.assembler.datablockwrapper)
 

diff --git a/pypy/translator/backendopt/inline.py b/pypy/translator/backendopt/inline.py
--- a/pypy/translator/backendopt/inline.py
+++ b/pypy/translator/backendopt/inline.py
@@ -5,7 +5,7 @@
 from pypy.objspace.flow.model import Variable, Constant, Block, Link
 from pypy.objspace.flow.model import SpaceOperation, c_last_exception
 from pypy.objspace.flow.model import FunctionGraph
-from pypy.objspace.flow.model import traverse, mkentrymap, checkgraph
+from pypy.objspace.flow.model import mkentrymap, checkgraph
 from pypy.annotation import model as annmodel
 from pypy.rpython.lltypesystem.lltype import Bool, Signed, typeOf, Void, Ptr
 from pypy.rpython.lltypesystem.lltype import normalizeptr
@@ -13,7 +13,7 @@
 from pypy.rpython import rmodel
 from pypy.tool.algo import sparsemat
 from pypy.translator.backendopt import removenoops
-from pypy.translator.backendopt.support import log, split_block_with_keepalive
+from pypy.translator.backendopt.support import log
 from pypy.translator.unsimplify import split_block
 from pypy.translator.backendopt.support import find_backedges, find_loop_blocks
 from pypy.translator.backendopt.canraise import RaiseAnalyzer
@@ -280,13 +280,6 @@
             self.varmap[var] = copyvar(None, var)
         return self.varmap[var]
 
-    def generate_keepalive(self, *args):
-        from pypy.translator.backendopt.support import generate_keepalive
-        if self.translator.rtyper.type_system.name == 'lltypesystem':
-            return generate_keepalive(*args)
-        else:
-            return []
-
     def passon_vars(self, cache_key):
         if cache_key in self._passon_vars:
             return self._passon_vars[cache_key]
@@ -397,7 +390,6 @@
             for exceptionlink in afterblock.exits[1:]:
                 if exc_match(vtable, exceptionlink.llexitcase):
                     passon_vars = self.passon_vars(link.prevblock)
-                    copiedblock.operations += self.generate_keepalive(passon_vars)
                     copiedlink.target = exceptionlink.target
                     linkargs = self.find_args_in_exceptional_case(
                         exceptionlink, link.prevblock, var_etype, var_evalue, afterblock, passon_vars)
@@ -445,7 +437,6 @@
         del blocks[-1].exits[0].llexitcase
         linkargs = copiedexceptblock.inputargs
         copiedexceptblock.recloseblock(Link(linkargs, blocks[0]))
-        copiedexceptblock.operations += self.generate_keepalive(linkargs)
 
     def do_inline(self, block, index_operation):
         splitlink = split_block(None, block, index_operation)
@@ -457,11 +448,8 @@
         # this copy is created with the method passon_vars
         self.original_passon_vars = [arg for arg in block.exits[0].args
                                          if isinstance(arg, Variable)]
-        n = 0
-        while afterblock.operations[n].opname == 'keepalive':
-            n += 1
-        assert afterblock.operations[n].opname == self.op.opname
-        self.op = afterblock.operations.pop(n)
+        assert afterblock.operations[0].opname == self.op.opname
+        self.op = afterblock.operations.pop(0)
         #vars that need to be passed through the blocks of the inlined function
         linktoinlined = splitlink
         copiedstartblock = self.copy_block(self.graph_to_inline.startblock)
@@ -551,7 +539,6 @@
 
 OP_WEIGHTS = {'same_as': 0,
               'cast_pointer': 0,
-              'keepalive': 0,
               'malloc': 2,
               'yield_current_frame_to_caller': sys.maxint, # XXX bit extreme
               'resume_point': sys.maxint, # XXX bit extreme
@@ -784,5 +771,4 @@
                               call_count_pred=call_count_pred)
         log.inlining('inlined %d callsites.'% (count,))
         for graph in graphs:
-            removenoops.remove_superfluous_keep_alive(graph)
             removenoops.remove_duplicate_casts(graph, translator)

diff --git a/pypy/rpython/extfunc.py b/pypy/rpython/extfunc.py
--- a/pypy/rpython/extfunc.py
+++ b/pypy/rpython/extfunc.py
@@ -249,6 +249,9 @@
     llfakeimpl, oofakeimpl: optional; if provided, they are called by the llinterpreter
     sandboxsafe: use True if the function performs no I/O (safe for --sandbox)
     """
+    
+    if export_name is None:
+        export_name = function.__name__
 
     class FunEntry(ExtFuncEntry):
         _about_ = function

diff --git a/pypy/module/cpyext/test/test_import.py b/pypy/module/cpyext/test/test_import.py
--- a/pypy/module/cpyext/test/test_import.py
+++ b/pypy/module/cpyext/test/test_import.py
@@ -1,5 +1,6 @@
 from pypy.module.cpyext.test.test_api import BaseApiTest
 from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
+from pypy.rpython.lltypesystem import rffi, lltype
 
 class TestImport(BaseApiTest):
     def test_import(self, space, api):
@@ -7,6 +8,22 @@
         assert pdb
         assert space.getattr(pdb, space.wrap("pm"))
 
+    def test_addmodule(self, space, api):
+        with rffi.scoped_str2charp("sys") as modname:
+            w_sys = api.PyImport_AddModule(modname)
+        assert w_sys is space.sys
+
+        with rffi.scoped_str2charp("foobar") as modname:
+            w_foobar = api.PyImport_AddModule(modname)
+        assert space.str_w(space.getattr(w_foobar,
+                                         space.wrap('__name__'))) == 'foobar'
+
+    def test_reload(self, space, api):
+        pdb = api.PyImport_Import(space.wrap("pdb"))
+        space.delattr(pdb, space.wrap("set_trace"))
+        pdb = api.PyImport_ReloadModule(pdb)
+        assert space.getattr(pdb, space.wrap("set_trace"))
+
 class AppTestImportLogic(AppTestCpythonExtensionBase):
     def test_import_logic(self):
         skip("leak?")

diff --git a/pypy/module/cpyext/test/test_frameobject.py b/pypy/module/cpyext/test/test_frameobject.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/test/test_frameobject.py
@@ -0,0 +1,66 @@
+from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
+
+class AppTestFrameObject(AppTestCpythonExtensionBase):
+
+    def test_forge_frame(self):
+        module = self.import_extension('foo', [
+            ("raise_exception", "METH_NOARGS",
+             """
+                 PyObject *py_srcfile = PyString_FromString("filename");
+                 PyObject *py_funcname = PyString_FromString("funcname");
+                 PyObject *py_globals = PyDict_New();
+                 PyObject *empty_string = PyString_FromString("");
+                 PyObject *empty_tuple = PyTuple_New(0);
+                 PyCodeObject *py_code;
+                 PyFrameObject *py_frame;
+
+                 py_code = PyCode_New(
+                     0,            /*int argcount,*/
+                     #if PY_MAJOR_VERSION >= 3
+                     0,            /*int kwonlyargcount,*/
+                     #endif
+                     0,            /*int nlocals,*/
+                     0,            /*int stacksize,*/
+                     0,            /*int flags,*/
+                     empty_string, /*PyObject *code,*/
+                     empty_tuple,  /*PyObject *consts,*/
+                     empty_tuple,  /*PyObject *names,*/
+                     empty_tuple,  /*PyObject *varnames,*/
+                     empty_tuple,  /*PyObject *freevars,*/
+                     empty_tuple,  /*PyObject *cellvars,*/
+                     py_srcfile,   /*PyObject *filename,*/
+                     py_funcname,  /*PyObject *name,*/
+                     42,           /*int firstlineno,*/
+                     empty_string  /*PyObject *lnotab*/
+                 );
+
+                 if (!py_code) goto bad;
+                 py_frame = PyFrame_New(
+                     PyThreadState_Get(), /*PyThreadState *tstate,*/
+                     py_code,             /*PyCodeObject *code,*/
+                     py_globals,          /*PyObject *globals,*/
+                     0                    /*PyObject *locals*/
+                 );
+                 if (!py_frame) goto bad;
+                 py_frame->f_lineno = 48; /* Does not work with CPython */
+                 PyErr_SetString(PyExc_ValueError, "error message");
+                 PyTraceBack_Here(py_frame);
+             bad:
+                 Py_XDECREF(py_srcfile);
+                 Py_XDECREF(py_funcname);
+                 Py_XDECREF(empty_string);
+                 Py_XDECREF(empty_tuple);
+                 Py_XDECREF(py_globals);
+                 Py_XDECREF(py_code);
+                 Py_XDECREF(py_frame);
+                 return NULL;
+             """),
+            ])
+        exc = raises(ValueError, module.raise_exception)
+        frame = exc.traceback.tb_frame
+        assert frame.f_code.co_filename == "filename"
+        assert frame.f_code.co_name == "funcname"
+
+        # Cython does not work on CPython as well...
+        assert exc.traceback.tb_lineno == 42 # should be 48
+        assert frame.f_lineno == 42

diff --git a/lib_pypy/pyrepl/tests/basic.py b/lib_pypy/pyrepl/tests/basic.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/tests/basic.py
@@ -0,0 +1,115 @@
+#   Copyright 2000-2004 Michael Hudson-Doyle <micahel at gmail.com>
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+from pyrepl.console import Event
+from pyrepl.tests.infrastructure import ReaderTestCase, EA, run_testcase
+
+class SimpleTestCase(ReaderTestCase):
+
+    def test_basic(self):
+        self.run_test([(('self-insert', 'a'), ['a']),
+                       ( 'accept',            ['a'])])
+
+    def test_repeat(self):
+        self.run_test([(('digit-arg', '3'),   ['']),
+                       (('self-insert', 'a'), ['aaa']),
+                       ( 'accept',            ['aaa'])])
+
+    def test_kill_line(self):
+        self.run_test([(('self-insert', 'abc'), ['abc']),
+                       ( 'left',                None),
+                       ( 'kill-line',           ['ab']),
+                       ( 'accept',              ['ab'])])
+
+    def test_unix_line_discard(self):
+        self.run_test([(('self-insert', 'abc'), ['abc']),
+                       ( 'left',                None),
+                       ( 'unix-word-rubout',    ['c']),
+                       ( 'accept',              ['c'])])
+
+    def test_kill_word(self):
+        self.run_test([(('self-insert', 'ab cd'), ['ab cd']),
+                       ( 'beginning-of-line',     ['ab cd']),
+                       ( 'kill-word',             [' cd']),
+                       ( 'accept',                [' cd'])])
+
+    def test_backward_kill_word(self):
+        self.run_test([(('self-insert', 'ab cd'), ['ab cd']),
+                       ( 'backward-kill-word',    ['ab ']),
+                       ( 'accept',                ['ab '])])
+
+    def test_yank(self):
+        self.run_test([(('self-insert', 'ab cd'), ['ab cd']),
+                       ( 'backward-kill-word',    ['ab ']),
+                       ( 'beginning-of-line',     ['ab ']),
+                       ( 'yank',                  ['cdab ']),
+                       ( 'accept',                ['cdab '])])
+        
+    def test_yank_pop(self):
+        self.run_test([(('self-insert', 'ab cd'), ['ab cd']),
+                       ( 'backward-kill-word',    ['ab ']),
+                       ( 'left',                  ['ab ']),
+                       ( 'backward-kill-word',    [' ']),
+                       ( 'yank',                  ['ab ']),
+                       ( 'yank-pop',              ['cd ']),
+                       ( 'accept',                ['cd '])])
+
+    def test_interrupt(self):
+        try:
+            self.run_test([( 'interrupt',  [''])])
+        except KeyboardInterrupt:
+            pass
+        else:
+            self.fail('KeyboardInterrupt got lost')
+
+    # test_suspend -- hah
+
+    def test_up(self):
+        self.run_test([(('self-insert', 'ab\ncd'), ['ab', 'cd']),
+                       ( 'up',                     ['ab', 'cd']),
+                       (('self-insert', 'e'),      ['abe', 'cd']),
+                       ( 'accept',                 ['abe', 'cd'])])
+
+    def test_down(self):
+        self.run_test([(('self-insert', 'ab\ncd'), ['ab', 'cd']),
+                       ( 'up',                     ['ab', 'cd']),
+                       (('self-insert', 'e'),      ['abe', 'cd']),
+                       ( 'down',                   ['abe', 'cd']),
+                       (('self-insert', 'f'),      ['abe', 'cdf']),
+                       ( 'accept',                 ['abe', 'cdf'])])
+
+    def test_left(self):
+        self.run_test([(('self-insert', 'ab'), ['ab']),
+                       ( 'left',               ['ab']),
+                       (('self-insert', 'c'),  ['acb']),
+                       ( 'accept',             ['acb'])])
+
+    def test_right(self):
+        self.run_test([(('self-insert', 'ab'), ['ab']),
+                       ( 'left',               ['ab']),
+                       (('self-insert', 'c'),  ['acb']),
+                       ( 'right',              ['acb']),
+                       (('self-insert', 'd'),  ['acbd']),
+                       ( 'accept',             ['acbd'])])
+        
+def test():
+    run_testcase(SimpleTestCase)
+
+if __name__ == '__main__':
+    test()

diff --git a/pypy/rpython/ootypesystem/ootype.py b/pypy/rpython/ootypesystem/ootype.py
--- a/pypy/rpython/ootypesystem/ootype.py
+++ b/pypy/rpython/ootypesystem/ootype.py
@@ -443,7 +443,8 @@
             "ll_upper": Meth([], self.SELFTYPE_T),
             "ll_lower": Meth([], self.SELFTYPE_T),
             "ll_substring": Meth([Signed, Signed], self.SELFTYPE_T), # ll_substring(start, count)
-            "ll_split_chr": Meth([self.CHAR], Array(self.SELFTYPE_T)), # XXX this is not pure!
+            "ll_split_chr": Meth([self.CHAR, Signed], Array(self.SELFTYPE_T)), # XXX this is not pure!
+            "ll_rsplit_chr": Meth([self.CHAR, Signed], Array(self.SELFTYPE_T)), # XXX this is not pure!
             "ll_contains": Meth([self.CHAR], Bool),
             "ll_replace_chr_chr": Meth([self.CHAR, self.CHAR], self.SELFTYPE_T),
             })
@@ -1480,9 +1481,16 @@
         # NOT_RPYTHON
         return self.make_string(self._str[start:start+count])
 
-    def ll_split_chr(self, ch):
+    def ll_split_chr(self, ch, max):
         # NOT_RPYTHON
-        l = [self.make_string(s) for s in self._str.split(ch)]
+        l = [self.make_string(s) for s in self._str.split(ch, max)]
+        res = _array(Array(self._TYPE), len(l))
+        res._array[:] = l
+        return res
+
+    def ll_rsplit_chr(self, ch, max):
+        # NOT_RPYTHON
+        l = [self.make_string(s) for s in self._str.rsplit(ch, max)]
         res = _array(Array(self._TYPE), len(l))
         res._array[:] = l
         return res

diff --git a/pypy/translator/goal/translate.py b/pypy/translator/goal/translate.py
--- a/pypy/translator/goal/translate.py
+++ b/pypy/translator/goal/translate.py
@@ -285,6 +285,15 @@
         elif drv.exe_name is None and '__name__' in targetspec_dic:
             drv.exe_name = targetspec_dic['__name__'] + '-%(backend)s'
 
+        # Double check to ensure we are not overwriting the current interpreter
+        try:
+            exe_name = str(drv.compute_exe_name())
+            assert not os.path.samefile(exe_name, sys.executable), (
+                'Output file %r is the currently running '
+                'interpreter (use --output=...)'% exe_name)
+        except OSError:
+            pass
+
         goals = translateconfig.goals
         try:
             drv.proceed(goals)

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
@@ -151,9 +151,9 @@
 
 class CPythonFakeFrame(eval.Frame):
 
-    def __init__(self, space, code, w_globals=None, numlocals=-1):
+    def __init__(self, space, code, w_globals=None):
         self.fakecode = code
-        eval.Frame.__init__(self, space, w_globals, numlocals)
+        eval.Frame.__init__(self, space, w_globals)
 
     def getcode(self):
         return self.fakecode

diff --git a/pypy/jit/tl/pypyjit.py b/pypy/jit/tl/pypyjit.py
--- a/pypy/jit/tl/pypyjit.py
+++ b/pypy/jit/tl/pypyjit.py
@@ -102,7 +102,7 @@
 
     # first annotate, rtype, and backendoptimize PyPy
     try:
-        interp, graph = get_interpreter(entry_point, [], backendopt=True,
+        interp, graph = get_interpreter(entry_point, [], backendopt=False,
                                         config=config,
                                         type_system=config.translation.type_system,
                                         policy=PyPyAnnotatorPolicy(space))

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
@@ -8,9 +8,8 @@
 from pypy.rpython.lltypesystem.lloperation import llop
 from pypy.rpython.annlowlevel import llhelper
 from pypy.jit.backend.model import CompiledLoopToken
-from pypy.jit.backend.x86.regalloc import (RegAlloc, X86RegisterManager,
-                                           X86XMMRegisterManager, get_ebp_ofs,
-                                           _get_scale)
+from pypy.jit.backend.x86.regalloc import (RegAlloc, get_ebp_ofs,
+                                           _get_scale, gpr_reg_mgr_cls)
 
 from pypy.jit.backend.x86.arch import (FRAME_FIXED_SIZE, FORCE_INDEX_OFS, WORD,
                                        IS_X86_32, IS_X86_64)
@@ -78,8 +77,8 @@
         self.loop_run_counters = []
         self.float_const_neg_addr = 0
         self.float_const_abs_addr = 0
-        self.malloc_fixedsize_slowpath1 = 0
-        self.malloc_fixedsize_slowpath2 = 0
+        self.malloc_slowpath1 = 0
+        self.malloc_slowpath2 = 0
         self.memcpy_addr = 0
         self.setup_failure_recovery()
         self._debug = False
@@ -124,15 +123,18 @@
             self._build_failure_recovery(True, withfloats=True)
             support.ensure_sse2_floats()
             self._build_float_constants()
-        if hasattr(gc_ll_descr, 'get_malloc_fixedsize_slowpath_addr'):
-            self._build_malloc_fixedsize_slowpath()
+        if gc_ll_descr.get_malloc_slowpath_addr is not None:
+            self._build_malloc_slowpath()
         self._build_stack_check_slowpath()
+        if gc_ll_descr.gcrootmap:
+            self._build_close_stack()
         debug_start('jit-backend-counts')
         self.set_debug(have_debug_prints())
         debug_stop('jit-backend-counts')
 
     def setup(self, looptoken):
         assert self.memcpy_addr != 0, "setup_once() not called?"
+        self.current_clt = looptoken.compiled_loop_token
         self.pending_guard_tokens = []
         self.mc = codebuf.MachineCodeBlockWrapper()
         if self.datablockwrapper is None:
@@ -145,6 +147,7 @@
         self.mc = None
         self.looppos = -1
         self.currently_compiling_loop = None
+        self.current_clt = None
 
     def finish_once(self):
         if self._debug:
@@ -170,26 +173,47 @@
         self.float_const_neg_addr = float_constants
         self.float_const_abs_addr = float_constants + 16
 
-    def _build_malloc_fixedsize_slowpath(self):
+    def _build_malloc_slowpath(self):
+        # With asmgcc, we need two helpers, so that we can write two CALL
+        # instructions in assembler, with a mark_gc_roots in between.
+        # With shadowstack, this is not needed, so we produce a single helper.
+        gcrootmap = self.cpu.gc_ll_descr.gcrootmap
+        #
         # ---------- first helper for the slow path of malloc ----------
         mc = codebuf.MachineCodeBlockWrapper()
         if self.cpu.supports_floats:          # save the XMM registers in
             for i in range(self.cpu.NUM_REGS):# the *caller* frame, from esp+8
                 mc.MOVSD_sx((WORD*2)+8*i, i)
         mc.SUB_rr(edx.value, eax.value)       # compute the size we want
-        if IS_X86_32:
-            mc.MOV_sr(WORD, edx.value)        # save it as the new argument
-        elif IS_X86_64:
-            # rdi can be clobbered: its content was forced to the stack
-            # by _fastpath_malloc(), like all other save_around_call_regs.
-            mc.MOV_rr(edi.value, edx.value)
-
-        addr = self.cpu.gc_ll_descr.get_malloc_fixedsize_slowpath_addr()
-        mc.JMP(imm(addr))                    # tail call to the real malloc
-        rawstart = mc.materialize(self.cpu.asmmemmgr, [])
-        self.malloc_fixedsize_slowpath1 = rawstart
-        # ---------- second helper for the slow path of malloc ----------
-        mc = codebuf.MachineCodeBlockWrapper()
+        addr = self.cpu.gc_ll_descr.get_malloc_slowpath_addr()
+        #
+        if gcrootmap is not None and gcrootmap.is_shadow_stack:
+            # ---- shadowstack ----
+            for reg, ofs in gpr_reg_mgr_cls.REGLOC_TO_COPY_AREA_OFS.items():
+                mc.MOV_br(ofs, reg.value)
+            mc.SUB_ri(esp.value, 16 - WORD)      # stack alignment of 16 bytes
+            if IS_X86_32:
+                mc.MOV_sr(0, edx.value)          # push argument
+            elif IS_X86_64:
+                mc.MOV_rr(edi.value, edx.value)
+            mc.CALL(imm(addr))
+            mc.ADD_ri(esp.value, 16 - WORD)
+            for reg, ofs in gpr_reg_mgr_cls.REGLOC_TO_COPY_AREA_OFS.items():
+                mc.MOV_rb(reg.value, ofs)
+        else:
+            # ---- asmgcc ----
+            if IS_X86_32:
+                mc.MOV_sr(WORD, edx.value)       # save it as the new argument
+            elif IS_X86_64:
+                # rdi can be clobbered: its content was forced to the stack
+                # by _fastpath_malloc(), like all other save_around_call_regs.
+                mc.MOV_rr(edi.value, edx.value)
+            mc.JMP(imm(addr))                    # tail call to the real malloc
+            rawstart = mc.materialize(self.cpu.asmmemmgr, [])
+            self.malloc_slowpath1 = rawstart
+            # ---------- second helper for the slow path of malloc ----------
+            mc = codebuf.MachineCodeBlockWrapper()
+        #
         if self.cpu.supports_floats:          # restore the XMM registers
             for i in range(self.cpu.NUM_REGS):# from where they were saved
                 mc.MOVSD_xs(i, (WORD*2)+8*i)
@@ -197,21 +221,28 @@
         mc.MOV(edx, heap(nursery_free_adr))   # load this in EDX
         mc.RET()
         rawstart = mc.materialize(self.cpu.asmmemmgr, [])
-        self.malloc_fixedsize_slowpath2 = rawstart
+        self.malloc_slowpath2 = rawstart
 
     def _build_stack_check_slowpath(self):
-        from pypy.rlib import rstack
         _, _, slowpathaddr = self.cpu.insert_stack_check()
         if slowpathaddr == 0 or self.cpu.exit_frame_with_exception_v < 0:
             return      # no stack check (for tests, or non-translated)
         #
+        # make a "function" that is called immediately at the start of
+        # an assembler function.  In particular, the stack looks like:
+        #
+        #    |  ...                |    <-- aligned to a multiple of 16
+        #    |  retaddr of caller  |
+        #    |  my own retaddr     |    <-- esp
+        #    +---------------------+
+        #
         mc = codebuf.MachineCodeBlockWrapper()
-        mc.PUSH_r(ebp.value)
-        mc.MOV_rr(ebp.value, esp.value)
         #
+        stack_size = WORD
         if IS_X86_64:
             # on the x86_64, we have to save all the registers that may
             # have been used to pass arguments
+            stack_size += 6*WORD + 8*8
             for reg in [edi, esi, edx, ecx, r8, r9]:
                 mc.PUSH_r(reg.value)
             mc.SUB_ri(esp.value, 8*8)
@@ -220,11 +251,13 @@
         #
         if IS_X86_32:
             mc.LEA_rb(eax.value, +8)
+            stack_size += 2*WORD
+            mc.PUSH_r(eax.value)        # alignment
             mc.PUSH_r(eax.value)
         elif IS_X86_64:
             mc.LEA_rb(edi.value, +16)
-            mc.AND_ri(esp.value, -16)
         #
+        # esp is now aligned to a multiple of 16 again
         mc.CALL(imm(slowpathaddr))
         #
         mc.MOV(eax, heap(self.cpu.pos_exception()))
@@ -232,16 +265,16 @@
         mc.J_il8(rx86.Conditions['NZ'], 0)
         jnz_location = mc.get_relative_pos()
         #
-        if IS_X86_64:
+        if IS_X86_32:
+            mc.ADD_ri(esp.value, 2*WORD)
+        elif IS_X86_64:
             # restore the registers
             for i in range(7, -1, -1):
                 mc.MOVSD_xs(i, 8*i)
-            for i, reg in [(6, r9), (5, r8), (4, ecx),
-                           (3, edx), (2, esi), (1, edi)]:
-                mc.MOV_rb(reg.value, -8*i)
+            mc.ADD_ri(esp.value, 8*8)
+            for reg in [r9, r8, ecx, edx, esi, edi]:
+                mc.POP_r(reg.value)
         #
-        mc.MOV_rr(esp.value, ebp.value)
-        mc.POP_r(ebp.value)
         mc.RET()
         #
         # patch the JNZ above
@@ -266,14 +299,61 @@
         # function, and will instead return to the caller's caller.  Note
         # also that we completely ignore the saved arguments, because we
         # are interrupting the function.
-        mc.MOV_rr(esp.value, ebp.value)
-        mc.POP_r(ebp.value)
-        mc.ADD_ri(esp.value, WORD)
+        mc.ADD_ri(esp.value, stack_size)
         mc.RET()
         #
         rawstart = mc.materialize(self.cpu.asmmemmgr, [])
         self.stack_check_slowpath = rawstart
 
+    @staticmethod
+    def _close_stack(css):
+        # similar to trackgcroot.py:pypy_asm_stackwalk, first part
+        from pypy.rpython.memory.gctransform import asmgcroot
+        new = rffi.cast(asmgcroot.ASM_FRAMEDATA_HEAD_PTR, css)
+        next = asmgcroot.gcrootanchor.next
+        new.next = next
+        new.prev = asmgcroot.gcrootanchor
+        asmgcroot.gcrootanchor.next = new
+        next.prev = new
+        # and now release the GIL
+        before = rffi.aroundstate.before
+        # Store a flag (by abuse in new+2*WORD) that tells if we must
+        # call the "after" function or not.  The issue is that the
+        # before/after fields can be set at a random point during the
+        # execution, and we should not call the "after" function if we
+        # did not call the "before" function.  It works by assuming that
+        # before/after start out being None/None, and are later set (once
+        # only) to some pair of functions.
+        css[2] = int(bool(before))
+        if before:
+            before()
+
+    @staticmethod
+    def _reopen_stack(css):
+        # first reacquire the GIL
+        if css[2]:
+            after = rffi.aroundstate.after
+            assert after
+            after()
+        # similar to trackgcroot.py:pypy_asm_stackwalk, second part
+        from pypy.rpython.memory.gctransform import asmgcroot
+        old = rffi.cast(asmgcroot.ASM_FRAMEDATA_HEAD_PTR, css)
+        prev = old.prev
+        next = old.next
+        prev.next = next
+        next.prev = prev
+
+    _CLOSESTACK_FUNC = lltype.Ptr(lltype.FuncType([rffi.LONGP],
+                                                  lltype.Void))
+
+    def _build_close_stack(self):
+        closestack_func = llhelper(self._CLOSESTACK_FUNC,
+                                   self._close_stack)
+        reopenstack_func = llhelper(self._CLOSESTACK_FUNC,
+                                    self._reopen_stack)
+        self.closestack_addr  = self.cpu.cast_ptr_to_int(closestack_func)
+        self.reopenstack_addr = self.cpu.cast_ptr_to_int(reopenstack_func)
+
     def assemble_loop(self, inputargs, operations, looptoken, log):
         '''adds the following attributes to looptoken:
                _x86_loop_code       (an integer giving an address)
@@ -537,7 +617,7 @@
     def _get_offset_of_ebp_from_esp(self, allocated_depth):
         # Given that [EBP] is where we saved EBP, i.e. in the last word
         # of our fixed frame, then the 'words' value is:
-        words = (self.cpu.FRAME_FIXED_SIZE - 1) + allocated_depth
+        words = (FRAME_FIXED_SIZE - 1) + allocated_depth
         # align, e.g. for Mac OS X
         aligned_words = align_stack_words(words+2)-2 # 2 = EIP+EBP
         return -WORD * aligned_words
@@ -550,6 +630,10 @@
         for regloc in self.cpu.CALLEE_SAVE_REGISTERS:
             self.mc.PUSH_r(regloc.value)
 
+        gcrootmap = self.cpu.gc_ll_descr.gcrootmap
+        if gcrootmap and gcrootmap.is_shadow_stack:
+            self._call_header_shadowstack(gcrootmap)
+
     def _call_header_with_stack_check(self):
         if self.stack_check_slowpath == 0:
             pass                # no stack check (e.g. not translated)
@@ -571,12 +655,32 @@
     def _call_footer(self):
         self.mc.LEA_rb(esp.value, -len(self.cpu.CALLEE_SAVE_REGISTERS) * WORD)
 
+        gcrootmap = self.cpu.gc_ll_descr.gcrootmap
+        if gcrootmap and gcrootmap.is_shadow_stack:
+            self._call_footer_shadowstack(gcrootmap)
+
         for i in range(len(self.cpu.CALLEE_SAVE_REGISTERS)-1, -1, -1):
             self.mc.POP_r(self.cpu.CALLEE_SAVE_REGISTERS[i].value)
 
         self.mc.POP_r(ebp.value)
         self.mc.RET()
 
+    def _call_header_shadowstack(self, gcrootmap):
+        # we need to put two words into the shadowstack: the MARKER
+        # and the address of the frame (ebp, actually)
+        rst = gcrootmap.get_root_stack_top_addr()
+        assert rx86.fits_in_32bits(rst)
+        self.mc.MOV_rj(eax.value, rst)                # MOV eax, [rootstacktop]
+        self.mc.LEA_rm(edx.value, (eax.value, 2*WORD))  # LEA edx, [eax+2*WORD]
+        self.mc.MOV_mi((eax.value, 0), gcrootmap.MARKER)    # MOV [eax], MARKER
+        self.mc.MOV_mr((eax.value, WORD), ebp.value)      # MOV [eax+WORD], ebp
+        self.mc.MOV_jr(rst, edx.value)                # MOV [rootstacktop], edx
+
+    def _call_footer_shadowstack(self, gcrootmap):
+        rst = gcrootmap.get_root_stack_top_addr()
+        assert rx86.fits_in_32bits(rst)
+        self.mc.SUB_ji8(rst, 2*WORD)       # SUB [rootstacktop], 2*WORD
+
     def _assemble_bootstrap_direct_call(self, arglocs, jmppos, stackdepth):
         if IS_X86_64:
             return self._assemble_bootstrap_direct_call_64(arglocs, jmppos, stackdepth)
@@ -686,8 +790,8 @@
         nonfloatlocs, floatlocs = arglocs
         self._call_header()
         stackadjustpos = self._patchable_stackadjust()
-        tmp = X86RegisterManager.all_regs[0]
-        xmmtmp = X86XMMRegisterManager.all_regs[0]
+        tmp = eax
+        xmmtmp = xmm0
         self.mc.begin_reuse_scratch_register()
         for i in range(len(nonfloatlocs)):
             loc = nonfloatlocs[i]
@@ -896,9 +1000,9 @@
                     self.implement_guard(guard_token, checkfalsecond)
         return genop_cmp_guard_float
 
-    def _emit_call(self, x, arglocs, start=0, tmp=eax):
+    def _emit_call(self, force_index, x, arglocs, start=0, tmp=eax):
         if IS_X86_64:
-            return self._emit_call_64(x, arglocs, start)
+            return self._emit_call_64(force_index, x, arglocs, start)
 
         p = 0
         n = len(arglocs)
@@ -924,9 +1028,9 @@
         self._regalloc.reserve_param(p//WORD)
         # x is a location
         self.mc.CALL(x)
-        self.mark_gc_roots()
+        self.mark_gc_roots(force_index)
 
-    def _emit_call_64(self, x, arglocs, start=0):
+    def _emit_call_64(self, force_index, x, arglocs, start):
         src_locs = []
         dst_locs = []
         xmm_src_locs = []
@@ -984,12 +1088,27 @@
 
         self._regalloc.reserve_param(len(pass_on_stack))
         self.mc.CALL(x)
-        self.mark_gc_roots()
+        self.mark_gc_roots(force_index)
 
     def call(self, addr, args, res):
-        self._emit_call(imm(addr), args)
+        force_index = self.write_new_force_index()
+        self._emit_call(force_index, imm(addr), args)
         assert res is eax
 
+    def write_new_force_index(self):
+        # for shadowstack only: get a new, unused force_index number and
+        # write it to FORCE_INDEX_OFS.  Used to record the call shape
+        # (i.e. where the GC pointers are in the stack) around a CALL
+        # instruction that doesn't already have a force_index.
+        gcrootmap = self.cpu.gc_ll_descr.gcrootmap
+        if gcrootmap and gcrootmap.is_shadow_stack:
+            clt = self.current_clt
+            force_index = clt.reserve_and_record_some_faildescr_index()
+            self.mc.MOV_bi(FORCE_INDEX_OFS, force_index)
+            return force_index
+        else:
+            return 0
+
     genop_int_neg = _unaryop("NEG")
     genop_int_invert = _unaryop("NOT")
     genop_int_add = _binaryop("ADD", True)
@@ -1205,6 +1324,11 @@
             assert isinstance(loc_vtable, ImmedLoc)
             self.mc.MOV(mem(loc, self.cpu.vtable_offset), loc_vtable)
 
+    def set_new_array_length(self, loc, ofs_length, loc_num_elem):
+        assert isinstance(loc, RegLoc)
+        assert isinstance(loc_num_elem, ImmedLoc)
+        self.mc.MOV(mem(loc, ofs_length), loc_num_elem)
+
     # XXX genop_new is abused for all varsized mallocs with Boehm, for now
     # (instead of genop_new_array, genop_newstr, genop_newunicode)
     def genop_new(self, op, arglocs, result_loc):
@@ -1783,6 +1907,10 @@
         self.pending_guard_tokens.append(guard_token)
 
     def genop_call(self, op, arglocs, resloc):
+        force_index = self.write_new_force_index()
+        self._genop_call(op, arglocs, resloc, force_index)
+
+    def _genop_call(self, op, arglocs, resloc, force_index):
         sizeloc = arglocs[0]
         assert isinstance(sizeloc, ImmedLoc)
         size = sizeloc.value
@@ -1796,8 +1924,8 @@
             tmp = ecx
         else:
             tmp = eax
-        
-        self._emit_call(x, arglocs, 3, tmp=tmp)
+
+        self._emit_call(force_index, x, arglocs, 3, tmp=tmp)
 
         if IS_X86_32 and isinstance(resloc, StackLoc) and resloc.width == 8:
             # a float or a long long return
@@ -1828,11 +1956,79 @@
         faildescr = guard_op.getdescr()
         fail_index = self.cpu.get_fail_descr_number(faildescr)
         self.mc.MOV_bi(FORCE_INDEX_OFS, fail_index)
-        self.genop_call(op, arglocs, result_loc)
+        self._genop_call(op, arglocs, result_loc, fail_index)
         self.mc.CMP_bi(FORCE_INDEX_OFS, 0)
         self.implement_guard(guard_token, 'L')
 
-    genop_guard_call_release_gil = genop_guard_call_may_force
+    def genop_guard_call_release_gil(self, op, guard_op, guard_token,
+                                     arglocs, result_loc):
+        # first, close the stack in the sense of the asmgcc GC root tracker
+        gcrootmap = self.cpu.gc_ll_descr.gcrootmap
+        if gcrootmap:
+            # note that regalloc.py used save_all_regs=True to save all
+            # registers, so we don't have to care about saving them (other
+            # than ebp) in the close_stack_struct
+            self.call_close_stack()
+        # do the call
+        faildescr = guard_op.getdescr()
+        fail_index = self.cpu.get_fail_descr_number(faildescr)
+        self.mc.MOV_bi(FORCE_INDEX_OFS, fail_index)
+        self.genop_call(op, arglocs, result_loc)
+        # then reopen the stack
+        if gcrootmap:
+            self.call_reopen_stack(result_loc)
+        # finally, the guard_not_forced
+        self.mc.CMP_bi(FORCE_INDEX_OFS, 0)
+        self.implement_guard(guard_token, 'L')
+
+    def call_close_stack(self):
+        from pypy.rpython.memory.gctransform import asmgcroot
+        css = self._regalloc.close_stack_struct
+        if css == 0:
+            use_words = (2 + max(asmgcroot.INDEX_OF_EBP,
+                                 asmgcroot.FRAME_PTR) + 1)
+            pos = self._regalloc.fm.reserve_location_in_frame(use_words)
+            css = get_ebp_ofs(pos + use_words - 1)
+            self._regalloc.close_stack_struct = css
+        # The location where the future CALL will put its return address
+        # will be [ESP-WORD], so save that as the next frame's top address
+        self.mc.LEA_rs(eax.value, -WORD)        # LEA EAX, [ESP-4]
+        frame_ptr = css + WORD * (2+asmgcroot.FRAME_PTR)
+        self.mc.MOV_br(frame_ptr, eax.value)    # MOV [css.frame], EAX
+        # Save ebp
+        index_of_ebp = css + WORD * (2+asmgcroot.INDEX_OF_EBP)
+        self.mc.MOV_br(index_of_ebp, ebp.value) # MOV [css.ebp], EBP
+        # Call the closestack() function (also releasing the GIL)
+        if IS_X86_32:
+            reg = eax
+        elif IS_X86_64:
+            reg = edi
+        self.mc.LEA_rb(reg.value, css)
+        self._emit_call(imm(self.closestack_addr), [reg])
+
+    def call_reopen_stack(self, save_loc):
+        # save the previous result (eax/xmm0) into the stack temporarily
+        if isinstance(save_loc, RegLoc):
+            self._regalloc.reserve_param(save_loc.width//WORD)
+            if save_loc.is_xmm:
+                self.mc.MOVSD_sx(0, save_loc.value)
+            else:
+                self.mc.MOV_sr(0, save_loc.value)
+        # call the reopenstack() function (also reacquiring the GIL)
+        css = self._regalloc.close_stack_struct
+        assert css != 0
+        if IS_X86_32:
+            reg = eax
+        elif IS_X86_64:
+            reg = edi
+        self.mc.LEA_rb(reg.value, css)
+        self._emit_call(imm(self.reopenstack_addr), [reg])
+        # restore the result from the stack
+        if isinstance(save_loc, RegLoc):
+            if save_loc.is_xmm:
+                self.mc.MOVSD_xs(save_loc.value, 0)
+            else:
+                self.mc.MOV_rs(save_loc.value, 0)
 
     def genop_guard_call_assembler(self, op, guard_op, guard_token,
                                    arglocs, result_loc):
@@ -1844,8 +2040,8 @@
         assert len(arglocs) - 2 == len(descr._x86_arglocs[0])
         #
         # Write a call to the direct_bootstrap_code of the target assembler
-        self._emit_call(imm(descr._x86_direct_bootstrap_code), arglocs, 2,
-                        tmp=eax)
+        self._emit_call(fail_index, imm(descr._x86_direct_bootstrap_code),
+                        arglocs, 2, tmp=eax)
         if op.result is None:
             assert result_loc is None
             value = self.cpu.done_with_this_frame_void_v
@@ -1870,7 +2066,7 @@
         jd = descr.outermost_jitdriver_sd
         assert jd is not None
         asm_helper_adr = self.cpu.cast_adr_to_int(jd.assembler_helper_adr)
-        self._emit_call(imm(asm_helper_adr), [eax, arglocs[1]], 0,
+        self._emit_call(fail_index, imm(asm_helper_adr), [eax, arglocs[1]], 0,
                         tmp=ecx)
         if IS_X86_32 and isinstance(result_loc, StackLoc) and result_loc.type == FLOAT:
             self.mc.FSTP_b(result_loc.value)
@@ -1897,7 +2093,7 @@
             # load the return value from fail_boxes_xxx[0]
             kind = op.result.type
             if kind == FLOAT:
-                xmmtmp = X86XMMRegisterManager.all_regs[0]
+                xmmtmp = xmm0
                 adr = self.fail_boxes_float.get_addr_for_num(0)
                 self.mc.MOVSD(xmmtmp, heap(adr))
                 self.mc.MOVSD(result_loc, xmmtmp)
@@ -1992,11 +2188,16 @@
         not_implemented("not implemented operation (guard): %s" %
                         op.getopname())
 
-    def mark_gc_roots(self):
+    def mark_gc_roots(self, force_index, use_copy_area=False):
+        if force_index < 0:
+            return     # not needed
         gcrootmap = self.cpu.gc_ll_descr.gcrootmap
         if gcrootmap:
-            mark = self._regalloc.get_mark_gc_roots(gcrootmap)
-            self.mc.insert_gcroot_marker(mark)
+            mark = self._regalloc.get_mark_gc_roots(gcrootmap, use_copy_area)
+            if gcrootmap.is_shadow_stack:
+                gcrootmap.write_callshape(mark, force_index)
+            else:
+                self.mc.insert_gcroot_marker(mark)
 
     def target_arglocs(self, loop_token):
         return loop_token._x86_arglocs
@@ -2008,8 +2209,7 @@
         else:
             self.mc.JMP(imm(loop_token._x86_loop_code))
 
-    def malloc_cond_fixedsize(self, nursery_free_adr, nursery_top_adr,
-                              size, tid):
+    def malloc_cond(self, nursery_free_adr, nursery_top_adr, size, tid):
         size = max(size, self.cpu.gc_ll_descr.minimal_size_in_nursery)
         self.mc.MOV(eax, heap(nursery_free_adr))
         self.mc.LEA_rm(edx.value, (eax.value, size))
@@ -2017,7 +2217,7 @@
         self.mc.J_il8(rx86.Conditions['NA'], 0) # patched later
         jmp_adr = self.mc.get_relative_pos()
 
-        # See comments in _build_malloc_fixedsize_slowpath for the
+        # See comments in _build_malloc_slowpath for the
         # details of the two helper functions that we are calling below.
         # First, we need to call two of them and not just one because we
         # need to have a mark_gc_roots() in between.  Then the calling
@@ -2027,22 +2227,30 @@
         # result in EAX; slowpath_addr2 additionally returns in EDX a
         # copy of heap(nursery_free_adr), so that the final MOV below is
         # a no-op.
-        slowpath_addr1 = self.malloc_fixedsize_slowpath1
+
         # reserve room for the argument to the real malloc and the
         # 8 saved XMM regs
         self._regalloc.reserve_param(1+16)
-        self.mc.CALL(imm(slowpath_addr1))
-        self.mark_gc_roots()
-        slowpath_addr2 = self.malloc_fixedsize_slowpath2
+
+        gcrootmap = self.cpu.gc_ll_descr.gcrootmap
+        shadow_stack = (gcrootmap is not None and gcrootmap.is_shadow_stack)
+        if not shadow_stack:
+            # there are two helpers to call only with asmgcc
+            slowpath_addr1 = self.malloc_slowpath1
+            self.mc.CALL(imm(slowpath_addr1))
+        self.mark_gc_roots(self.write_new_force_index(),
+                           use_copy_area=shadow_stack)
+        slowpath_addr2 = self.malloc_slowpath2
         self.mc.CALL(imm(slowpath_addr2))
 
         offset = self.mc.get_relative_pos() - jmp_adr
         assert 0 < offset <= 127
         self.mc.overwrite(jmp_adr-1, chr(offset))
         # on 64-bits, 'tid' is a value that fits in 31 bits
+        assert rx86.fits_in_32bits(tid)
         self.mc.MOV_mi((eax.value, 0), tid)
         self.mc.MOV(heap(nursery_free_adr), edx)
-        
+
 genop_discard_list = [Assembler386.not_implemented_op_discard] * rop._LAST
 genop_list = [Assembler386.not_implemented_op] * rop._LAST
 genop_llong_list = {}

diff --git a/pypy/module/cpyext/include/traceback.h b/pypy/module/cpyext/include/traceback.h
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/include/traceback.h
@@ -0,0 +1,12 @@
+#ifndef Py_TRACEBACK_H
+#define Py_TRACEBACK_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef PyObject PyTracebackObject;
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_TRACEBACK_H */


More information about the Pypy-commit mailing list