[pypy-commit] pypy arm-backend-2: merge up to a98d7b4c1f16

bivab noreply at buildbot.pypy.org
Fri Jul 1 16:16:02 CEST 2011


Author: David Schneider <david.schneider at picle.org>
Branch: arm-backend-2
Changeset: r45231:4a6d9d2ae42a
Date: 2011-07-01 15:45 +0200
http://bitbucket.org/pypy/pypy/changeset/4a6d9d2ae42a/

Log:	merge up to a98d7b4c1f16

diff --git a/.hgignore b/.hgignore
--- a/.hgignore
+++ b/.hgignore
@@ -25,6 +25,8 @@
 ^pypy/translator/c/src/libffi_msvc/.+\.dll$
 ^pypy/translator/c/src/libffi_msvc/.+\.lib$
 ^pypy/translator/c/src/libffi_msvc/.+\.exp$
+^pypy/translator/c/src/cjkcodecs/.+\.o$
+^pypy/translator/c/src/cjkcodecs/.+\.obj$
 ^pypy/translator/jvm/\.project$
 ^pypy/translator/jvm/\.classpath$
 ^pypy/translator/jvm/eclipse-bin$
diff --git a/README b/README
--- a/README
+++ b/README
@@ -15,10 +15,10 @@
 
 The getting-started document will help guide you:
 
-    http://codespeak.net/pypy/dist/pypy/doc/getting-started.html
+    http://doc.pypy.org/en/latest/getting-started.html
 
 It will also point you to the rest of the documentation which is generated
 from files in the pypy/doc directory within the source repositories. Enjoy
 and send us feedback!
 
-    the pypy-dev team <pypy-dev at codespeak.net>
+    the pypy-dev team <pypy-dev at python.org>
diff --git a/lib-python/TODO b/lib-python/TODO
deleted file mode 100644
--- a/lib-python/TODO
+++ /dev/null
@@ -1,100 +0,0 @@
-TODO list for 2.7.0
-===================
-
-You can find the results of the most recent buildbot run at:
-http://buildbot.pypy.org/
-
-
-Probably easy tasks
--------------------
-
-- (unicode|bytearray).(index|find) should accept None as indices (see
-  test_unicode.py)
-
-- missing posix.confstr and posix.confstr_names
-
-- remove code duplication: bit_length() and _count_bits() in rlib/rbigint.py,
-  objspace/std/longobject.py and objspace/std/longtype.py.
-
-- missing module pyexpat.errors
-
-- support for PYTHONIOENCODING, this needs a way to update file.encoding
-
-- implement format__Complex_ANY() in pypy/objspace/std/complexobject.py
-
-- Code like this does not work, for two reasons::
-
-  \
-  from __future__ import (with_statement,
-                          unicode_literals)
-  assert type("") is unicode
-
-- Code like::
-
-  assert(x is not None, "error message")
-
-  should emit a SyntaxWarning when compiled (the tuple is always true)
-
-
-Medium tasks
-------------
-
-- socket module has a couple of changes (including AF_TIPC packet range)
-
-Longer tasks
-------------
-
-- Fix usage of __cmp__ in subclasses::
-
-    class badint(int):
-        def __cmp__(self, other):
-            raise RuntimeError
-    raises(RuntimeError, cmp, 0, badint(1))
-
-- Fix comparison of objects layout: if two classes have the same __slots__, it
-  should be possible to change the instances __class__::
-
-      class A(object): __slots__ = ('a', 'b')
-      class B(object): __slots__ = ('b', 'a')
-      a = A()
-      a.__class__ = B
-
-- Show a ResourceWarning when a file/socket is not explicitely closed, like
-  CPython did for 3.2: http://svn.python.org/view?view=rev&revision=85920
-  in PyPy this should be enabled by default
-
-Won't do for this release
--------------------------
-
-Note: when you give up with a missing feature, please mention it here, as well
-as the various skips added to the test suite.
-
-- py3k warnings
-
-  * the -3 flag is accepted on the command line, but displays a warning (see
-    `translator/goal/app_main.py`)
-
-- CJK codecs.
-
-  * In `./conftest.py`, skipped all `test_codecencodings_*.py` and
-    `test_codecmaps_*.py`.
-
-  * In test_codecs, commented out various items in `all_unicode_encodings`.
-
-- Error messages about ill-formed calls (like "argument after ** must be a
-  mapping") don't always show the function name.  That's hard to fix for
-  the case of errors raised when the Argument object is created (as opposed
-  to when parsing for a given target function, which occurs later).
-
-  * Some "..." were added to doctests in test_extcall.py
-
-- CPython's builtin methods are both functions and unbound methods (for
-  example, `str.upper is dict(str.__dict__)['upper']`). This is not the case
-  in pypy, and assertions like `object.__str__ is object.__str__` are False
-  with pypy.  Use the `==` operator instead.
-
-  * pprint.py, _threading_local.py
-
-- When importing a nested module fails, the ImportError message mentions the
-  name of the package up to the component that could not be imported (CPython
-  prefers to display the names starting with the failing part).
diff --git a/lib-python/modified-2.7/distutils/sysconfig.py b/lib-python/modified-2.7/distutils/sysconfig.py
--- a/lib-python/modified-2.7/distutils/sysconfig.py
+++ b/lib-python/modified-2.7/distutils/sysconfig.py
@@ -20,8 +20,10 @@
 if '__pypy__' in sys.builtin_module_names:
     from distutils.sysconfig_pypy import *
     from distutils.sysconfig_pypy import _config_vars # needed by setuptools
+    from distutils.sysconfig_pypy import _variable_rx # read_setup_file()
 else:
     from distutils.sysconfig_cpython import *
     from distutils.sysconfig_cpython import _config_vars # needed by setuptools
+    from distutils.sysconfig_cpython import _variable_rx # read_setup_file()
 
 
diff --git a/lib-python/modified-2.7/distutils/sysconfig_pypy.py b/lib-python/modified-2.7/distutils/sysconfig_pypy.py
--- a/lib-python/modified-2.7/distutils/sysconfig_pypy.py
+++ b/lib-python/modified-2.7/distutils/sysconfig_pypy.py
@@ -116,3 +116,7 @@
     if compiler.compiler_type == "unix":
         compiler.compiler_so.extend(['-fPIC', '-Wimplicit'])
         compiler.shared_lib_extension = get_config_var('SO')
+
+from sysconfig_cpython import (
+    parse_makefile, _variable_rx, expand_makefile_vars)
+
diff --git a/lib_pypy/_pypy_wait.py b/lib_pypy/_pypy_wait.py
--- a/lib_pypy/_pypy_wait.py
+++ b/lib_pypy/_pypy_wait.py
@@ -6,12 +6,12 @@
 
 libc = CDLL(find_library("c"))
 c_wait3 = libc.wait3
-
 c_wait3.argtypes = [POINTER(c_int), c_int, POINTER(_struct_rusage)]
+c_wait3.restype = c_int
 
 c_wait4 = libc.wait4
-
 c_wait4.argtypes = [c_int, POINTER(c_int), c_int, POINTER(_struct_rusage)]
+c_wait4.restype = c_int
 
 def create_struct_rusage(c_struct):
     return struct_rusage((
diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py
--- a/lib_pypy/_sqlite3.py
+++ b/lib_pypy/_sqlite3.py
@@ -127,8 +127,6 @@
 SQLITE_FUNCTION                 = 31
 
 # SQLite C API
-sqlite.sqlite3_bind_double.argtypes = [c_void_p, c_int, c_double]
-sqlite.sqlite3_bind_int64.argtypes = [c_void_p, c_int, c_int64]
 
 sqlite.sqlite3_value_int.argtypes = [c_void_p]
 sqlite.sqlite3_value_int.restype = c_int
@@ -151,7 +149,16 @@
 sqlite.sqlite3_value_type.argtypes = [c_void_p]
 sqlite.sqlite3_value_type.restype = c_int
 
+sqlite.sqlite3_bind_blob.argtypes = [c_void_p, c_int, c_void_p, c_int,c_void_p]
+sqlite.sqlite3_bind_blob.restype = c_int
+sqlite.sqlite3_bind_double.argtypes = [c_void_p, c_int, c_double]
+sqlite.sqlite3_bind_double.restype = c_int
 sqlite.sqlite3_bind_int.argtypes = [c_void_p, c_int, c_int]
+sqlite.sqlite3_bind_int.restype = c_int
+sqlite.sqlite3_bind_int64.argtypes = [c_void_p, c_int, c_int64]
+sqlite.sqlite3_bind_int64.restype = c_int
+sqlite.sqlite3_bind_null.argtypes = [c_void_p, c_int]
+sqlite.sqlite3_bind_null.restype = c_int
 sqlite.sqlite3_bind_parameter_count.argtypes = [c_void_p]
 sqlite.sqlite3_bind_parameter_count.restype = c_int
 sqlite.sqlite3_bind_parameter_index.argtypes = [c_void_p, c_char_p]
@@ -159,45 +166,69 @@
 sqlite.sqlite3_bind_parameter_name.argtypes = [c_void_p, c_int]
 sqlite.sqlite3_bind_parameter_name.restype = c_char_p
 sqlite.sqlite3_bind_text.argtypes = [c_void_p, c_int, c_char_p, c_int,c_void_p]
-sqlite.sqlite3_bind_blob.argtypes = [c_void_p, c_int, c_void_p, c_int,c_void_p]
-sqlite.sqlite3_bind_blob.restype = c_int
+sqlite.sqlite3_bind_text.restype = c_int
+sqlite.sqlite3_busy_timeout.argtypes = [c_void_p, c_int]
+sqlite.sqlite3_busy_timeout.restype = c_int
 sqlite.sqlite3_changes.argtypes = [c_void_p]
 sqlite.sqlite3_changes.restype = c_int
 sqlite.sqlite3_close.argtypes = [c_void_p]
 sqlite.sqlite3_close.restype = c_int
+sqlite.sqlite3_column_blob.argtypes = [c_void_p, c_int]
 sqlite.sqlite3_column_blob.restype = c_void_p
+sqlite.sqlite3_column_bytes.argtypes = [c_void_p, c_int]
 sqlite.sqlite3_column_bytes.restype = c_int
+sqlite.sqlite3_column_count.argtypes = [c_void_p]
+sqlite.sqlite3_column_count.restype = c_int
+sqlite.sqlite3_column_decltype.argtypes = [c_void_p, c_int]
+sqlite.sqlite3_column_decltype.restype = c_char_p
+sqlite.sqlite3_column_double.argtypes = [c_void_p, c_int]
 sqlite.sqlite3_column_double.restype = c_double
+sqlite.sqlite3_column_int64.argtypes = [c_void_p, c_int]
 sqlite.sqlite3_column_int64.restype = c_int64
+sqlite.sqlite3_column_name.argtypes = [c_void_p, c_int]
 sqlite.sqlite3_column_name.restype = c_char_p
+sqlite.sqlite3_column_text.argtypes = [c_void_p, c_int]
 sqlite.sqlite3_column_text.restype = c_char_p
+sqlite.sqlite3_column_type.argtypes = [c_void_p, c_int]
+sqlite.sqlite3_column_type.restype = c_int
 sqlite.sqlite3_complete.argtypes = [c_char_p]
 sqlite.sqlite3_complete.restype = c_int
 sqlite.sqlite3_errcode.restype = c_int
+sqlite.sqlite3_errmsg.argtypes = [c_void_p]
 sqlite.sqlite3_errmsg.restype = c_char_p
+sqlite.sqlite3_finalize.argtypes = [c_void_p]
+sqlite.sqlite3_finalize.restype = c_int
 sqlite.sqlite3_get_autocommit.argtypes = [c_void_p]
 sqlite.sqlite3_get_autocommit.restype = c_int
+sqlite.sqlite3_last_insert_rowid.argtypes = [c_void_p]
+sqlite.sqlite3_last_insert_rowid.restype = c_int64
 sqlite.sqlite3_libversion.argtypes = []
 sqlite.sqlite3_libversion.restype = c_char_p
 sqlite.sqlite3_open.argtypes = [c_char_p, c_void_p]
 sqlite.sqlite3_open.restype = c_int
+sqlite.sqlite3_prepare.argtypes = [c_void_p, c_char_p, c_int, c_void_p, POINTER(c_char_p)]
+sqlite.sqlite3_prepare.restype = c_int
 sqlite.sqlite3_prepare_v2.argtypes = [c_void_p, c_char_p, c_int, c_void_p, POINTER(c_char_p)]
 sqlite.sqlite3_prepare_v2.restype = c_int
-sqlite.sqlite3_column_decltype.argtypes = [c_void_p, c_int]
-sqlite.sqlite3_column_decltype.restype = c_char_p
 sqlite.sqlite3_step.argtypes = [c_void_p]
 sqlite.sqlite3_step.restype = c_int
 sqlite.sqlite3_reset.argtypes = [c_void_p]
 sqlite.sqlite3_reset.restype = c_int
-sqlite.sqlite3_column_count.argtypes = [c_void_p]
-sqlite.sqlite3_column_count.restype = c_int
+sqlite.sqlite3_total_changes.argtypes = [c_void_p]
+sqlite.sqlite3_total_changes.restype = c_int
 
 sqlite.sqlite3_result_blob.argtypes = [c_void_p, c_char_p, c_int, c_void_p]
+sqlite.sqlite3_result_blob.restype = None
 sqlite.sqlite3_result_int64.argtypes = [c_void_p, c_int64]
+sqlite.sqlite3_result_int64.restype = None
 sqlite.sqlite3_result_null.argtypes = [c_void_p]
+sqlite.sqlite3_result_null.restype = None
 sqlite.sqlite3_result_double.argtypes = [c_void_p, c_double]
+sqlite.sqlite3_result_double.restype = None
 sqlite.sqlite3_result_error.argtypes = [c_void_p, c_char_p, c_int]
+sqlite.sqlite3_result_error.restype = None
 sqlite.sqlite3_result_text.argtypes = [c_void_p, c_char_p, c_int, c_void_p]
+sqlite.sqlite3_result_text.restype = None
 
 ##########################################
 # END Wrapped SQLite C API and constants
diff --git a/lib_pypy/stackless.py b/lib_pypy/stackless.py
--- a/lib_pypy/stackless.py
+++ b/lib_pypy/stackless.py
@@ -200,14 +200,15 @@
     # I can't think of a better solution without a real transform.
 
 def rewrite_stackless_primitive(coro_state, alive, tempval):
-    flags, state, thunk, parent = coro_state
-    for i, frame in enumerate(state):
+    flags, frame, thunk, parent = coro_state
+    while frame is not None:
         retval_expr = _stackless_primitive_registry.get(frame.f_code)
         if retval_expr:
             # this tasklet needs to stop pickling here and return its value.
             tempval = eval(retval_expr, globals(), frame.f_locals)
-            state = state[:i]
-            coro_state = flags, state, thunk, parent
+            coro_state = flags, frame, thunk, parent
+            break
+        frame = frame.f_back
     return coro_state, alive, tempval
 
 #
@@ -492,23 +493,22 @@
         assert two == ()
         # we want to get rid of the parent thing.
         # for now, we just drop it
-        a, b, c, d = coro_state
-        
+        a, frame, c, d = coro_state
+
         # Removing all frames related to stackless.py.
         # They point to stuff we don't want to be pickled.
-        frame_list = list(b)
-        new_frame_list = []
-        for frame in frame_list:
+
+        pickleframe = frame
+        while frame is not None:
             if frame.f_code == schedule.func_code:
                 # Removing everything including and after the
                 # call to stackless.schedule()
+                pickleframe = frame.f_back
                 break
-            new_frame_list.append(frame)
-        b = tuple(new_frame_list)
-        
+            frame = frame.f_back
         if d:
             assert isinstance(d, coroutine)
-        coro_state = a, b, c, None
+        coro_state = a, pickleframe, c, None
         coro_state, alive, tempval = rewrite_stackless_primitive(coro_state, self.alive, self.tempval)
         inst_dict = self.__dict__.copy()
         inst_dict.pop('tempval', None)
diff --git a/pypy/annotation/annrpython.py b/pypy/annotation/annrpython.py
--- a/pypy/annotation/annrpython.py
+++ b/pypy/annotation/annrpython.py
@@ -228,7 +228,7 @@
             # graph -- it's already low-level operations!
             for a, s_newarg in zip(graph.getargs(), cells):
                 s_oldarg = self.binding(a)
-                assert s_oldarg.contains(s_newarg)
+                assert annmodel.unionof(s_oldarg, s_newarg) == s_oldarg
         else:
             assert not self.frozen
             for a in cells:
diff --git a/pypy/annotation/description.py b/pypy/annotation/description.py
--- a/pypy/annotation/description.py
+++ b/pypy/annotation/description.py
@@ -565,7 +565,7 @@
         if self.is_exception_class():
             if self.pyobj.__module__ == 'exceptions':
                 return True
-            if self.pyobj is py.code._AssertionError:
+            if issubclass(self.pyobj, AssertionError):
                 return True
         return False
 
diff --git a/pypy/annotation/model.py b/pypy/annotation/model.py
--- a/pypy/annotation/model.py
+++ b/pypy/annotation/model.py
@@ -32,13 +32,15 @@
 import pypy
 from pypy.tool import descriptor
 from pypy.tool.pairtype import pair, extendabletype
-from pypy.tool.tls import tlsobject
 from pypy.rlib.rarithmetic import r_uint, r_ulonglong, base_int
 from pypy.rlib.rarithmetic import r_singlefloat, r_longfloat
 import inspect, weakref
 
 DEBUG = False    # set to False to disable recording of debugging information
-TLS = tlsobject()
+
+class State(object):
+    pass
+TLS = State()
 
 class SomeObject(object):
     """The set of all objects.  Each instance stands
diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py
--- a/pypy/config/pypyoption.py
+++ b/pypy/config/pypyoption.py
@@ -33,7 +33,7 @@
      "struct", "_hashlib", "_md5", "_sha", "_minimal_curses", "cStringIO",
      "thread", "itertools", "pyexpat", "_ssl", "cpyext", "array",
      "_bisect", "binascii", "_multiprocessing", '_warnings',
-     "_collections", "_multibytecodec"]
+     "_collections", "_multibytecodec", "micronumpy"]
 ))
 
 translation_modules = default_modules.copy()
@@ -242,6 +242,10 @@
                    "(the empty string and potentially single-char strings)",
                    default=False),
 
+        BoolOption("withsmalltuple",
+                   "use small tuples",
+                   default=False),
+
         BoolOption("withrope", "use ropes as the string implementation",
                    default=False,
                    requires=[("objspace.std.withstrslice", False),
@@ -269,7 +273,7 @@
                    "make instances really small but slow without the JIT",
                    default=False,
                    requires=[("objspace.std.getattributeshortcut", True),
-                             ("objspace.std.withtypeversion", True),
+                             ("objspace.std.withmethodcache", True),
                        ]),
 
         BoolOption("withrangelist",
diff --git a/pypy/config/translationoption.py b/pypy/config/translationoption.py
--- a/pypy/config/translationoption.py
+++ b/pypy/config/translationoption.py
@@ -221,17 +221,17 @@
         StrOption("profile_based_inline",
                   "Use call count profiling to drive inlining"
                   ", specify arguments",
-                  default=None, cmdline="--prof-based-inline"),
+                  default=None),   # cmdline="--prof-based-inline" fix me
         FloatOption("profile_based_inline_threshold",
                     "Threshold when to inline functions "
                     "for profile based inlining",
                   default=DEFL_PROF_BASED_INLINE_THRESHOLD,
-                  cmdline="--prof-based-inline-threshold"),
+                  ),   # cmdline="--prof-based-inline-threshold" fix me
         StrOption("profile_based_inline_heuristic",
                   "Dotted name of an heuristic function "
                   "for profile based inlining",
                 default="pypy.translator.backendopt.inline.inlining_heuristic",
-                cmdline="--prof-based-inline-heuristic"),
+                ),  # cmdline="--prof-based-inline-heuristic" fix me
         # control clever malloc removal
         BoolOption("clever_malloc_removal",
                    "Drives inlining to remove mallocs in a clever way",
diff --git a/pypy/conftest.py b/pypy/conftest.py
--- a/pypy/conftest.py
+++ b/pypy/conftest.py
@@ -46,6 +46,10 @@
     group.addoption('-P', '--platform', action="callback", type="string",
            default="host", callback=_set_platform,
            help="set up tests to use specified platform as compile/run target")
+    group = parser.getgroup("JIT options")
+    group.addoption('--viewloops', action="store_true",
+           default=False, dest="viewloops",
+           help="show only the compiled loops")
 
 def pytest_sessionstart():
     # have python subprocesses avoid startup customizations by default
diff --git a/pypy/doc/config/objspace.std.withsmalltuple.txt b/pypy/doc/config/objspace.std.withsmalltuple.txt
new file mode 100644
--- /dev/null
+++ b/pypy/doc/config/objspace.std.withsmalltuple.txt
@@ -0,0 +1,1 @@
+Use small tuple objects for sizes from 1 to 3
diff --git a/pypy/doc/cpython_differences.rst b/pypy/doc/cpython_differences.rst
--- a/pypy/doc/cpython_differences.rst
+++ b/pypy/doc/cpython_differences.rst
@@ -136,6 +136,11 @@
 next access.  Any code that uses weak proxies must carefully catch such
 ``ReferenceError`` at any place that uses them.
 
+As a side effect, the ``finally`` clause inside a generator will be executed
+only when the generator object is garbage collected (see `issue 736`__).
+
+.. __: http://bugs.pypy.org/issue736
+
 There are a few extra implications for the difference in the GC.  Most
 notably, if an object has a ``__del__``, the ``__del__`` is never called more
 than once in PyPy; but CPython will call the same ``__del__`` several times
diff --git a/pypy/doc/project-ideas.rst b/pypy/doc/project-ideas.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/project-ideas.rst
@@ -0,0 +1,49 @@
+
+Potential project list
+======================
+
+This is a list of projects that are interesting for potential contributors
+who are seriously interested in the PyPy project. They mostly share common
+patterns - they're mid-to-large in size, they're usually well defined as
+a standalone projects and they're not being actively worked on. For small
+projects that you might want to work on, it's much better to either look
+at the `issue tracker`_, pop up on #pypy on irc.freenode.net or write to the
+`mailing list`_. This is simply for the reason that small possible projects
+tend to change very rapidly.
+
+Numpy improvements
+------------------
+
+This is more of a project-container than a single project. Possible ideas:
+
+* experiment with auto-vectorization using SSE or implement vectorization
+  without automatically detecting it for array operations.
+
+* improve numpy, for example implement memory views.
+
+* interface with fortran/C libraries.
+
+Potential mentors: fijal
+
+JIT tooling
+-----------
+
+xxx
+
+Work on some of other languages
+-------------------------------
+
+xxx
+
+Various GCs
+-----------
+
+xxx
+
+Remove the GIL
+--------------
+
+xxx
+
+.. _`issue tracker`: ...
+.. _`mailing list`: ...
diff --git a/pypy/interpreter/astcompiler/misc.py b/pypy/interpreter/astcompiler/misc.py
--- a/pypy/interpreter/astcompiler/misc.py
+++ b/pypy/interpreter/astcompiler/misc.py
@@ -31,11 +31,12 @@
     future_lineno = 0
     future_column = 0
     have_docstring = False
+    body = None
     if isinstance(tree, ast.Module):
         body = tree.body
     elif isinstance(tree, ast.Interactive):
         body = tree.body
-    else:
+    if body is None:
         return 0, 0
     for stmt in body:
         if isinstance(stmt, ast.Expr) and isinstance(stmt.value, ast.Str):
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -82,7 +82,7 @@
             raise
 
     def getaddrstring(self, space):
-        # XXX slowish
+        # slowish
         w_id = space.id(self)
         w_4 = space.wrap(4)
         w_0x0F = space.wrap(0x0F)
@@ -616,7 +616,6 @@
 
     def createcompiler(self):
         "Factory function creating a compiler object."
-        # XXX simple selection logic for now
         try:
             return self.default_compiler
         except AttributeError:
@@ -821,11 +820,11 @@
 
     def call_obj_args(self, w_callable, w_obj, args):
         if not self.config.objspace.disable_call_speedhacks:
-            # XXX start of hack for performance
+            # start of hack for performance
             from pypy.interpreter.function import Function
             if isinstance(w_callable, Function):
                 return w_callable.call_obj_args(w_obj, args)
-            # XXX end of hack for performance
+            # end of hack for performance
         return self.call_args(w_callable, args.prepend(w_obj))
 
     def call(self, w_callable, w_args, w_kwds=None):
@@ -835,7 +834,7 @@
     def call_function(self, w_func, *args_w):
         nargs = len(args_w) # used for pruning funccall versions
         if not self.config.objspace.disable_call_speedhacks and nargs < 5:
-            # XXX start of hack for performance
+            # start of hack for performance
             from pypy.interpreter.function import Function, Method
             if isinstance(w_func, Method):
                 w_inst = w_func.w_instance
@@ -850,7 +849,7 @@
 
             if isinstance(w_func, Function):
                 return w_func.funccall(*args_w)
-            # XXX end of hack for performance
+            # end of hack for performance
 
         args = Arguments(self, list(args_w))
         return self.call_args(w_func, args)
@@ -864,7 +863,7 @@
             return self.call_args_and_c_profile(frame, w_func, args)
 
         if not self.config.objspace.disable_call_speedhacks:
-            # XXX start of hack for performance
+            # start of hack for performance
             if isinstance(w_func, Method):
                 w_inst = w_func.w_instance
                 if w_inst is not None:
@@ -879,7 +878,7 @@
 
             if isinstance(w_func, Function):
                 return w_func.funccall_valuestack(nargs, frame)
-            # XXX end of hack for performance
+            # end of hack for performance
 
         args = frame.make_arguments(nargs)
         return self.call_args(w_func, args)
@@ -1338,7 +1337,7 @@
         source = source.lstrip()
         assert source.startswith('('), "incorrect header in:\n%s" % (source,)
         source = py.code.Source("def anonymous%s\n" % source)
-        w_glob = space.newdict()
+        w_glob = space.newdict(module=True)
         space.exec_(str(source), w_glob, w_glob)
         return space.getitem(w_glob, space.wrap('anonymous'))
 
diff --git a/pypy/interpreter/error.py b/pypy/interpreter/error.py
--- a/pypy/interpreter/error.py
+++ b/pypy/interpreter/error.py
@@ -11,14 +11,14 @@
     """Interpreter-level exception that signals an exception that should be
     sent to the application level.
 
-    OperationError instances have three public attributes (and no .args),
-    w_type, w_value and application_traceback, which contain the wrapped
+    OperationError instances have three attributes (and no .args),
+    w_type, _w_value and _application_traceback, which contain the wrapped
     type and value describing the exception, and a chained list of
     PyTraceback objects making the application-level traceback.
     """
 
     _w_value = None
-    application_traceback = None
+    _application_traceback = None
 
     def __init__(self, w_type, w_value, tb=None):
         if not we_are_translated() and w_type is None:
@@ -26,7 +26,7 @@
             raise FlowingError(w_value)
         self.setup(w_type)
         self._w_value = w_value
-        self.application_traceback = tb
+        self._application_traceback = tb
 
     def setup(self, w_type):
         self.w_type = w_type
@@ -37,7 +37,7 @@
         # for sys.exc_clear()
         self.w_type = space.w_None
         self._w_value = space.w_None
-        self.application_traceback = None
+        self._application_traceback = None
         if not we_are_translated():
             del self.debug_excs[:]
 
@@ -103,7 +103,7 @@
 
     def print_app_tb_only(self, file):
         "NOT_RPYTHON"
-        tb = self.application_traceback
+        tb = self._application_traceback
         if tb:
             import linecache
             print >> file, "Traceback (application-level):"
@@ -251,6 +251,30 @@
     def _compute_value(self):
         raise NotImplementedError
 
+    def get_traceback(self):
+        """Calling this marks the PyTraceback as escaped, i.e. it becomes
+        accessible and inspectable by app-level Python code.  For the JIT.
+        Note that this has no effect if there are already several traceback
+        frames recorded, because in this case they are already marked as
+        escaping by executioncontext.leave() being called with
+        got_exception=True.
+        """
+        from pypy.interpreter.pytraceback import PyTraceback
+        tb = self._application_traceback
+        if tb is not None and isinstance(tb, PyTraceback):
+            tb.frame.mark_as_escaped()
+        return tb
+
+    def set_traceback(self, traceback):
+        """Set the current traceback.  It should either be a traceback
+        pointing to some already-escaped frame, or a traceback for the
+        current frame.  To support the latter case we do not mark the
+        frame as escaped.  The idea is that it will be marked as escaping
+        only if the exception really propagates out of this frame, by
+        executioncontext.leave() being called with got_exception=True.
+        """
+        self._application_traceback = traceback
+
 # ____________________________________________________________
 # optimization only: avoid the slowest operation -- the string
 # formatting with '%' -- in the common case were we don't
diff --git a/pypy/interpreter/eval.py b/pypy/interpreter/eval.py
--- a/pypy/interpreter/eval.py
+++ b/pypy/interpreter/eval.py
@@ -2,6 +2,7 @@
 This module defines the abstract base classes that support execution:
 Code and Frame.
 """
+from pypy.rlib import jit
 from pypy.interpreter.error import OperationError
 from pypy.interpreter.baseobjspace import Wrappable
 
@@ -97,6 +98,7 @@
         "Abstract. Get the expected number of locals."
         raise TypeError, "abstract"
 
+    @jit.dont_look_inside
     def fast2locals(self):
         # Copy values from self.fastlocals_w to self.w_locals
         if self.w_locals is None:
@@ -110,6 +112,7 @@
                 w_name = self.space.wrap(name)
                 self.space.setitem(self.w_locals, w_name, w_value)
 
+    @jit.dont_look_inside
     def locals2fast(self):
         # Copy values from self.w_locals to self.fastlocals_w
         assert self.w_locals is not None
diff --git a/pypy/interpreter/executioncontext.py b/pypy/interpreter/executioncontext.py
--- a/pypy/interpreter/executioncontext.py
+++ b/pypy/interpreter/executioncontext.py
@@ -24,6 +24,8 @@
     # XXX [fijal] but they're not. is_being_profiled is guarded a bit all
     #     over the place as well as w_tracefunc
 
+    _immutable_fields_ = ['profilefunc?', 'w_tracefunc?']
+
     def __init__(self, space):
         self.space = space
         self.topframeref = jit.vref_None
@@ -56,13 +58,23 @@
         frame.f_backref = self.topframeref
         self.topframeref = jit.virtual_ref(frame)
 
-    def leave(self, frame, w_exitvalue):
+    def leave(self, frame, w_exitvalue, got_exception):
         try:
             if self.profilefunc:
                 self._trace(frame, 'leaveframe', w_exitvalue)
         finally:
+            frame_vref = self.topframeref
             self.topframeref = frame.f_backref
-            jit.virtual_ref_finish(frame)
+            if frame.escaped or got_exception:
+                # if this frame escaped to applevel, we must ensure that also
+                # f_back does
+                f_back = frame.f_backref()
+                if f_back:
+                    f_back.mark_as_escaped()
+                # force the frame (from the JIT point of view), so that it can
+                # be accessed also later
+                frame_vref()
+            jit.virtual_ref_finish(frame_vref, frame)
 
         if self.w_tracefunc is not None and not frame.hide():
             self.space.frame_trace_action.fire()
@@ -100,18 +112,16 @@
 
         # the following interface is for pickling and unpickling
         def getstate(self, space):
-            # XXX we could just save the top frame, which brings
-            # the whole frame stack, but right now we get the whole stack
-            items = [space.wrap(f) for f in self.getframestack()]
-            return space.newtuple(items)
+            if self.topframe is None:
+                return space.w_None
+            return self.topframe
 
         def setstate(self, space, w_state):
             from pypy.interpreter.pyframe import PyFrame
-            frames_w = space.unpackiterable(w_state)
-            if len(frames_w) > 0:
-                self.topframe = space.interp_w(PyFrame, frames_w[-1])
+            if space.is_w(w_state, space.w_None):
+                self.topframe = None
             else:
-                self.topframe = None
+                self.topframe = space.interp_w(PyFrame, w_state)
 
         def getframestack(self):
             lst = []
@@ -276,7 +286,7 @@
             if operr is not None:
                 w_value = operr.get_w_value(space)
                 w_arg = space.newtuple([operr.w_type, w_value,
-                                     space.wrap(operr.application_traceback)])
+                                     space.wrap(operr.get_traceback())])
 
             frame.fast2locals()
             self.is_tracing += 1
diff --git a/pypy/interpreter/main.py b/pypy/interpreter/main.py
--- a/pypy/interpreter/main.py
+++ b/pypy/interpreter/main.py
@@ -118,7 +118,7 @@
         operationerr.normalize_exception(space)
         w_type = operationerr.w_type
         w_value = operationerr.get_w_value(space)
-        w_traceback = space.wrap(operationerr.application_traceback)
+        w_traceback = space.wrap(operationerr.get_traceback())
 
         # for debugging convenience we also insert the exception into
         # the interpreter-level sys.last_xxx
diff --git a/pypy/interpreter/nestedscope.py b/pypy/interpreter/nestedscope.py
--- a/pypy/interpreter/nestedscope.py
+++ b/pypy/interpreter/nestedscope.py
@@ -127,6 +127,7 @@
         if self.cells is not None:
             self.cells[:ncellvars] = cellvars
 
+    @jit.dont_look_inside
     def fast2locals(self):
         super_fast2locals(self)
         # cellvars are values exported to inner scopes
@@ -145,6 +146,7 @@
                 w_name = self.space.wrap(name)
                 self.space.setitem(self.w_locals, w_name, w_value)
 
+    @jit.dont_look_inside
     def locals2fast(self):
         super_locals2fast(self)
         freevarnames = self.pycode.co_cellvars + self.pycode.co_freevars
diff --git a/pypy/interpreter/pycompiler.py b/pypy/interpreter/pycompiler.py
--- a/pypy/interpreter/pycompiler.py
+++ b/pypy/interpreter/pycompiler.py
@@ -101,9 +101,9 @@
     """
     def __init__(self, space, override_version=None):
         PyCodeCompiler.__init__(self, space)
-        self.parser = pyparse.PythonParser(space)
+        self.future_flags = future.futureFlags_2_7
+        self.parser = pyparse.PythonParser(space, self.future_flags)
         self.additional_rules = {}
-        self.future_flags = future.futureFlags_2_7
         self.compiler_flags = self.future_flags.allowed_flags
 
     def compile_ast(self, node, filename, mode, flags):
@@ -140,9 +140,6 @@
     def _compile_to_ast(self, source, info):
         space = self.space
         try:
-            f_flags, future_info = future.get_futures(self.future_flags, source)
-            info.last_future_import = future_info
-            info.flags |= f_flags
             parse_tree = self.parser.parse_source(source, info)
             mod = astbuilder.ast_from_node(space, parse_tree, info)
         except parseerror.IndentationError, e:
diff --git a/pypy/interpreter/pyframe.py b/pypy/interpreter/pyframe.py
--- a/pypy/interpreter/pyframe.py
+++ b/pypy/interpreter/pyframe.py
@@ -11,7 +11,7 @@
 from pypy.rlib.jit import hint
 from pypy.rlib.debug import make_sure_not_resized
 from pypy.rlib.rarithmetic import intmask
-from pypy.rlib import jit, rstack
+from pypy.rlib import jit
 from pypy.tool import stdlib_opcode
 from pypy.tool.stdlib_opcode import host_bytecode_spec
 
@@ -49,6 +49,7 @@
     instr_ub                 = 0
     instr_prev_plus_one      = 0
     is_being_profiled        = False
+    escaped                  = False  # see mark_as_escaped()
 
     def __init__(self, space, code, w_globals, closure):
         self = hint(self, access_directly=True, fresh_virtualizable=True)
@@ -67,6 +68,15 @@
         make_sure_not_resized(self.fastlocals_w)
         self.f_lineno = code.co_firstlineno
 
+    def mark_as_escaped(self):
+        """
+        Must be called on frames that are exposed to applevel, e.g. by
+        sys._getframe().  This ensures that the virtualref holding the frame
+        is properly forced by ec.leave(), and thus the frame will be still
+        accessible even after the corresponding C stack died.
+        """
+        self.escaped = True
+
     def append_block(self, block):
         block.previous = self.lastblock
         self.lastblock = block
@@ -138,6 +148,7 @@
                 not self.space.config.translating)
         executioncontext = self.space.getexecutioncontext()
         executioncontext.enter(self)
+        got_exception = True
         w_exitvalue = self.space.w_None
         try:
             executioncontext.call_trace(self)
@@ -157,8 +168,6 @@
             try:
                 w_exitvalue = self.dispatch(self.pycode, next_instr,
                                             executioncontext)
-                rstack.resume_point("execute_frame", self, executioncontext,
-                                    returns=w_exitvalue)
             except Exception:
                 executioncontext.return_trace(self, self.space.w_None)
                 raise
@@ -166,8 +175,9 @@
             # clean up the exception, might be useful for not
             # allocating exception objects in some cases
             self.last_exception = None
+            got_exception = False
         finally:
-            executioncontext.leave(self, w_exitvalue)
+            executioncontext.leave(self, w_exitvalue, got_exception)
         return w_exitvalue
     execute_frame.insert_stack_check_here = True
 
@@ -314,7 +324,7 @@
             w_tb = space.w_None
         else:
             w_exc_value = self.last_exception.get_w_value(space)
-            w_tb = w(self.last_exception.application_traceback)
+            w_tb = w(self.last_exception.get_traceback())
         
         tup_state = [
             w(self.f_backref()),
@@ -415,6 +425,7 @@
         "Get the fast locals as a list."
         return self.fastlocals_w
 
+    @jit.dont_look_inside
     def setfastscope(self, scope_w):
         """Initialize the fast locals from a list of values,
         where the order is according to self.pycode.signature()."""
@@ -634,7 +645,7 @@
             while f is not None and f.last_exception is None:
                 f = f.f_backref()
             if f is not None:
-                return space.wrap(f.last_exception.application_traceback)
+                return space.wrap(f.last_exception.get_traceback())
         return space.w_None
          
     def fget_f_restricted(self, space):
diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py
--- a/pypy/interpreter/pyopcode.py
+++ b/pypy/interpreter/pyopcode.py
@@ -11,7 +11,7 @@
 from pypy.interpreter.pycode import PyCode
 from pypy.tool.sourcetools import func_with_new_name
 from pypy.rlib.objectmodel import we_are_translated
-from pypy.rlib import jit, rstackovf, rstack
+from pypy.rlib import jit, rstackovf
 from pypy.rlib.rarithmetic import r_uint, intmask
 from pypy.rlib.unroll import unrolling_iterable
 from pypy.rlib.debug import check_nonneg
@@ -83,16 +83,12 @@
         try:
             while True:
                 next_instr = self.handle_bytecode(co_code, next_instr, ec)
-                rstack.resume_point("dispatch", self, co_code, ec,
-                                    returns=next_instr)
         except ExitFrame:
             return self.popvalue()
 
     def handle_bytecode(self, co_code, next_instr, ec):
         try:
             next_instr = self.dispatch_bytecode(co_code, next_instr, ec)
-            rstack.resume_point("handle_bytecode", self, co_code, ec,
-                                returns=next_instr)
         except OperationError, operr:
             next_instr = self.handle_operation_error(ec, operr)
         except Reraise:
@@ -248,9 +244,6 @@
                         # dispatch to the opcode method
                         meth = getattr(self, opdesc.methodname)
                         res = meth(oparg, next_instr)
-                        if opdesc.index == self.opcodedesc.CALL_FUNCTION.index:
-                            rstack.resume_point("dispatch_call", self, co_code,
-                                                next_instr, ec)
                         # !! warning, for the annotator the next line is not
                         # comparing an int and None - you can't do that.
                         # Instead, it's constant-folded to either True or False
@@ -573,7 +566,7 @@
         else:
             msg = "raise: arg 3 must be a traceback or None"
             tb = pytraceback.check_traceback(space, w_traceback, msg)
-            operror.application_traceback = tb
+            operror.set_traceback(tb)
             # special 3-arguments raise, no new traceback obj will be attached
             raise RaiseWithExplicitTraceback(operror)
 
@@ -953,7 +946,7 @@
                       isinstance(unroller, SApplicationException))
         if is_app_exc:
             operr = unroller.operr
-            w_traceback = self.space.wrap(operr.application_traceback)
+            w_traceback = self.space.wrap(operr.get_traceback())
             w_suppress = self.call_contextmanager_exit_function(
                 w_exitfunc,
                 operr.w_type,
@@ -997,7 +990,6 @@
                                                           args)
         else:
             w_result = self.space.call_args(w_function, args)
-        rstack.resume_point("call_function", self, returns=w_result)
         self.pushvalue(w_result)
 
     def CALL_FUNCTION(self, oparg, next_instr):
@@ -1008,8 +1000,6 @@
             w_function = self.peekvalue(nargs)
             try:
                 w_result = self.space.call_valuestack(w_function, nargs, self)
-                rstack.resume_point("CALL_FUNCTION", self, nargs,
-                                    returns=w_result)
             finally:
                 self.dropvalues(nargs + 1)
             self.pushvalue(w_result)
@@ -1099,6 +1089,7 @@
         w_dict = self.space.newdict()
         self.pushvalue(w_dict)
 
+    @jit.unroll_safe
     def BUILD_SET(self, itemcount, next_instr):
         w_set = self.space.call_function(self.space.w_set)
         if itemcount:
diff --git a/pypy/interpreter/pyparser/pyparse.py b/pypy/interpreter/pyparser/pyparse.py
--- a/pypy/interpreter/pyparser/pyparse.py
+++ b/pypy/interpreter/pyparser/pyparse.py
@@ -1,6 +1,6 @@
 from pypy.interpreter import gateway
 from pypy.interpreter.error import OperationError
-from pypy.interpreter.pyparser import parser, pytokenizer, pygram, error
+from pypy.interpreter.pyparser import future, parser, pytokenizer, pygram, error
 from pypy.interpreter.astcompiler import consts
 
 
@@ -88,9 +88,11 @@
 
 class PythonParser(parser.Parser):
 
-    def __init__(self, space, grammar=pygram.python_grammar):
+    def __init__(self, space, future_flags=future.futureFlags_2_7,
+                 grammar=pygram.python_grammar):
         parser.Parser.__init__(self, grammar)
         self.space = space
+        self.future_flags = future_flags
 
     def parse_source(self, textsrc, compile_info):
         """Main entry point for parsing Python source.
@@ -133,6 +135,10 @@
                         raise error.SyntaxError(space.str_w(w_message))
                     raise
 
+        f_flags, future_info = future.get_futures(self.future_flags, textsrc)
+        compile_info.last_future_import = future_info
+        compile_info.flags |= f_flags
+
         flags = compile_info.flags
 
         if flags & consts.CO_FUTURE_PRINT_FUNCTION:
diff --git a/pypy/interpreter/pytraceback.py b/pypy/interpreter/pytraceback.py
--- a/pypy/interpreter/pytraceback.py
+++ b/pypy/interpreter/pytraceback.py
@@ -51,9 +51,9 @@
 def record_application_traceback(space, operror, frame, last_instruction):
     if frame.pycode.hidden_applevel:
         return
-    tb = operror.application_traceback
+    tb = operror.get_traceback()
     tb = PyTraceback(space, frame, last_instruction, tb)
-    operror.application_traceback = tb
+    operror.set_traceback(tb)
 
 def offset2lineno(c, stopat):
     tab = c.co_lnotab
diff --git a/pypy/interpreter/test/test_compiler.py b/pypy/interpreter/test/test_compiler.py
--- a/pypy/interpreter/test/test_compiler.py
+++ b/pypy/interpreter/test/test_compiler.py
@@ -714,6 +714,12 @@
 
 class AppTestCompiler:
 
+    def test_bom_with_future(self):
+        s = '\xef\xbb\xbffrom __future__ import division\nx = 1/2'
+        ns = {}
+        exec s in ns
+        assert ns["x"] == .5
+
     def test_values_of_different_types(self):
         exec "a = 0; b = 0L; c = 0.0; d = 0j"
         assert type(a) is int
diff --git a/pypy/interpreter/test/test_pyframe.py b/pypy/interpreter/test/test_pyframe.py
--- a/pypy/interpreter/test/test_pyframe.py
+++ b/pypy/interpreter/test/test_pyframe.py
@@ -98,6 +98,15 @@
             return sys._getframe().f_back.f_code.co_name 
         f()
 
+    def test_f_back_virtualref(self):
+        import sys
+        def f():
+            return g()
+        def g():
+            return sys._getframe()
+        frame = f()
+        assert frame.f_back.f_code.co_name == 'f'
+
     def test_f_exc_xxx(self):
         import sys
 
@@ -122,6 +131,21 @@
         except:
             g(sys.exc_info())
 
+    def test_virtualref_through_traceback(self):
+        import sys
+        def g():
+            try:
+                raise ValueError
+            except:
+                _, _, tb = sys.exc_info()
+            return tb
+        def f():
+            return g()
+        #
+        tb = f()
+        assert tb.tb_frame.f_code.co_name == 'g'
+        assert tb.tb_frame.f_back.f_code.co_name == 'f'
+
     def test_trace_basic(self):
         import sys
         l = []
diff --git a/pypy/jit/backend/arm/test/test_zrpy_gc.py b/pypy/jit/backend/arm/test/test_zrpy_gc.py
--- a/pypy/jit/backend/arm/test/test_zrpy_gc.py
+++ b/pypy/jit/backend/arm/test/test_zrpy_gc.py
@@ -524,8 +524,8 @@
         glob = A()
         def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s):
             a = A()
-            glob.v = virtual_ref(a)
-            virtual_ref_finish(a)
+            glob.v = vref = virtual_ref(a)
+            virtual_ref_finish(vref, a)
             n -= 1
             return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s
         return None, f, 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
@@ -209,7 +209,7 @@
                         llimpl.compile_add_fail_arg(c, var2index[box])
                     else:
                         llimpl.compile_add_fail_arg(c, -1)
-                        
+
             x = op.result
             if x is not None:
                 if isinstance(x, history.BoxInt):
diff --git a/pypy/jit/backend/llsupport/llmodel.py b/pypy/jit/backend/llsupport/llmodel.py
--- a/pypy/jit/backend/llsupport/llmodel.py
+++ b/pypy/jit/backend/llsupport/llmodel.py
@@ -143,11 +143,11 @@
         STACK_CHECK_SLOWPATH = lltype.Ptr(lltype.FuncType([lltype.Signed],
                                                           lltype.Void))
         def insert_stack_check():
-            startaddr = rstack._stack_get_start_adr()
-            length = rstack._stack_get_length()
+            endaddr = rstack._stack_get_end_adr()
+            lengthaddr = rstack._stack_get_length_adr()
             f = llhelper(STACK_CHECK_SLOWPATH, rstack.stack_check_slowpath)
             slowpathaddr = rffi.cast(lltype.Signed, f)
-            return startaddr, length, slowpathaddr
+            return endaddr, lengthaddr, slowpathaddr
 
         self.pos_exception = pos_exception
         self.pos_exc_value = pos_exc_value
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
@@ -221,18 +221,6 @@
             del self.reg_bindings[var]
             self.free_regs.append(loc)
         except KeyError:
-            if not we_are_translated():
-                import pdb; pdb.set_trace()
-            else:
-                raise ValueError
-
-    def force_spill_var(self, var):
-        self._sync_var(var)
-        try:
-            loc = self.reg_bindings[var]
-            del self.reg_bindings[var]
-            self.free_regs.append(loc)
-        except KeyError:
             pass   # 'var' is already not in a register
 
     def loc(self, box):
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
@@ -137,10 +137,11 @@
         self.current_clt = looptoken.compiled_loop_token
         self.pending_guard_tokens = []
         self.mc = codebuf.MachineCodeBlockWrapper()
-        if self.datablockwrapper is None:
-            allblocks = self.get_asmmemmgr_blocks(looptoken)
-            self.datablockwrapper = MachineDataBlockWrapper(self.cpu.asmmemmgr,
-                                                            allblocks)
+        #assert self.datablockwrapper is None --- but obscure case
+        # possible, e.g. getting MemoryError and continuing
+        allblocks = self.get_asmmemmgr_blocks(looptoken)
+        self.datablockwrapper = MachineDataBlockWrapper(self.cpu.asmmemmgr,
+                                                        allblocks)
 
     def teardown(self):
         self.pending_guard_tokens = None
@@ -620,11 +621,11 @@
         if self.stack_check_slowpath == 0:
             pass                # no stack check (e.g. not translated)
         else:
-            startaddr, length, _ = self.cpu.insert_stack_check()
-            self.mc.MOV(eax, esp)                       # MOV eax, current
-            self.mc.SUB(eax, heap(startaddr))           # SUB eax, [startaddr]
-            self.mc.CMP(eax, imm(length))               # CMP eax, length
-            self.mc.J_il8(rx86.Conditions['B'], 0)      # JB .skip
+            endaddr, lengthaddr, _ = self.cpu.insert_stack_check()
+            self.mc.MOV(eax, heap(endaddr))             # MOV eax, [start]
+            self.mc.SUB(eax, esp)                       # SUB eax, current
+            self.mc.CMP(eax, heap(lengthaddr))          # CMP eax, [length]
+            self.mc.J_il8(rx86.Conditions['BE'], 0)     # JBE .skip
             jb_location = self.mc.get_relative_pos()
             self.mc.CALL(imm(self.stack_check_slowpath))# CALL slowpath
             # patch the JB above                        # .skip:
@@ -678,27 +679,29 @@
         nonfloatlocs, floatlocs = arglocs
         self._call_header_with_stack_check()
         self.mc.LEA_rb(esp.value, self._get_offset_of_ebp_from_esp(stackdepth))
-        for i in range(len(nonfloatlocs)):
-            loc = nonfloatlocs[i]
-            if isinstance(loc, RegLoc):
-                assert not loc.is_xmm
-                self.mc.MOV_rb(loc.value, (2 + i) * WORD)
-            loc = floatlocs[i]
-            if isinstance(loc, RegLoc):
-                assert loc.is_xmm
-                self.mc.MOVSD_xb(loc.value, (1 + i) * 2 * WORD)
+        offset = 2 * WORD
         tmp = eax
         xmmtmp = xmm0
         for i in range(len(nonfloatlocs)):
             loc = nonfloatlocs[i]
-            if loc is not None and not isinstance(loc, RegLoc):
-                self.mc.MOV_rb(tmp.value, (2 + i) * WORD)
-                self.mc.MOV(loc, tmp)
+            if loc is not None:
+                if isinstance(loc, RegLoc):
+                    assert not loc.is_xmm
+                    self.mc.MOV_rb(loc.value, offset)
+                else:
+                    self.mc.MOV_rb(tmp.value, offset)
+                    self.mc.MOV(loc, tmp)
+                offset += WORD
             loc = floatlocs[i]
-            if loc is not None and not isinstance(loc, RegLoc):
-                self.mc.MOVSD_xb(xmmtmp.value, (1 + i) * 2 * WORD)
-                assert isinstance(loc, StackLoc)
-                self.mc.MOVSD_bx(loc.value, xmmtmp.value)
+            if loc is not None:
+                if isinstance(loc, RegLoc):
+                    assert loc.is_xmm
+                    self.mc.MOVSD_xb(loc.value, offset)
+                else:
+                    self.mc.MOVSD_xb(xmmtmp.value, offset)
+                    assert isinstance(loc, StackLoc)
+                    self.mc.MOVSD_bx(loc.value, xmmtmp.value)
+                offset += 2 * WORD
         endpos = self.mc.get_relative_pos() + 5
         self.mc.JMP_l(jmppos - endpos)
         assert endpos == self.mc.get_relative_pos()
@@ -1099,6 +1102,8 @@
             self.mc.MOV_bi(FORCE_INDEX_OFS, force_index)
             return force_index
         else:
+            # the return value is ignored, apart from the fact that it
+            # is not negative.
             return 0
 
     genop_int_neg = _unaryop("NEG")
@@ -2182,7 +2187,8 @@
         # a no-op.
 
         # reserve room for the argument to the real malloc and the
-        # 8 saved XMM regs
+        # saved XMM regs (on 32 bit: 8 * 2 words; on 64 bit: 16 * 1
+        # word)
         self._regalloc.reserve_param(1+16)
 
         gcrootmap = self.cpu.gc_ll_descr.gcrootmap
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
@@ -326,7 +326,7 @@
         if not we_are_translated():
             self.assembler.dump('%s <- %s(%s)' % (result_loc, op, arglocs))
         self.assembler.regalloc_perform_llong(op, arglocs, result_loc)
-        
+
     def PerformMath(self, op, arglocs, result_loc):
         if not we_are_translated():
             self.assembler.dump('%s <- %s(%s)' % (result_loc, op, arglocs))
@@ -634,7 +634,7 @@
         loc0 = self.xrm.force_result_in_reg(op.result, op.getarg(0))
         self.Perform(op, [loc0], loc0)
         self.xrm.possibly_free_var(op.getarg(0))
-        
+
     consider_float_neg = _consider_float_unary_op
     consider_float_abs = _consider_float_unary_op
 
@@ -722,7 +722,7 @@
         loc1 = self.rm.make_sure_var_in_reg(op.getarg(1))
         self.PerformLLong(op, [loc1], loc0)
         self.rm.possibly_free_vars_for_op(op)
-        
+
     def _consider_math_sqrt(self, op):
         loc0 = self.xrm.force_result_in_reg(op.result, op.getarg(1))
         self.PerformMath(op, [loc0], loc0)
@@ -1229,12 +1229,12 @@
         xmmtmploc = self.xrm.force_allocate_reg(box1, selected_reg=xmmtmp)
         # Part about non-floats
         # XXX we don't need a copy, we only just the original list
-        src_locations1 = [self.loc(op.getarg(i)) for i in range(op.numargs()) 
+        src_locations1 = [self.loc(op.getarg(i)) for i in range(op.numargs())
                          if op.getarg(i).type != FLOAT]
         assert tmploc not in nonfloatlocs
         dst_locations1 = [loc for loc in nonfloatlocs if loc is not None]
         # Part about floats
-        src_locations2 = [self.loc(op.getarg(i)) for i in range(op.numargs()) 
+        src_locations2 = [self.loc(op.getarg(i)) for i in range(op.numargs())
                          if op.getarg(i).type == FLOAT]
         dst_locations2 = [loc for loc in floatlocs if loc is not None]
         remap_frame_layout_mixed(assembler,
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
@@ -508,7 +508,9 @@
     LEA = _binaryop('LEA')
 
     MOVSD = _binaryop('MOVSD')
+    MOVAPD = _binaryop('MOVAPD')
     ADDSD = _binaryop('ADDSD')
+    ADDPD = _binaryop('ADDPD')
     SUBSD = _binaryop('SUBSD')
     MULSD = _binaryop('MULSD')
     DIVSD = _binaryop('DIVSD')
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
@@ -690,12 +690,17 @@
 
 define_modrm_modes('MOVSD_x*', ['\xF2', rex_nw, '\x0F\x10', register(1,8)], regtype='XMM')
 define_modrm_modes('MOVSD_*x', ['\xF2', rex_nw, '\x0F\x11', register(2,8)], regtype='XMM')
+define_modrm_modes('MOVAPD_x*', ['\x66', rex_nw, '\x0F\x28', register(1,8)],
+                   regtype='XMM')
+define_modrm_modes('MOVAPD_*x', ['\x66', rex_nw, '\x0F\x29', register(2,8)],
+                   regtype='XMM')
 
 define_modrm_modes('SQRTSD_x*', ['\xF2', rex_nw, '\x0F\x51', register(1,8)], regtype='XMM')
 
 #define_modrm_modes('XCHG_r*', [rex_w, '\x87', register(1, 8)])
 
 define_modrm_modes('ADDSD_x*', ['\xF2', rex_nw, '\x0F\x58', register(1, 8)], regtype='XMM')
+define_modrm_modes('ADDPD_x*', ['\x66', rex_nw, '\x0F\x58', register(1, 8)], regtype='XMM')
 define_modrm_modes('SUBSD_x*', ['\xF2', rex_nw, '\x0F\x5C', register(1, 8)], regtype='XMM')
 define_modrm_modes('MULSD_x*', ['\xF2', rex_nw, '\x0F\x59', register(1, 8)], regtype='XMM')
 define_modrm_modes('DIVSD_x*', ['\xF2', rex_nw, '\x0F\x5E', register(1, 8)], regtype='XMM')
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
@@ -525,8 +525,8 @@
         glob = A()
         def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s):
             a = A()
-            glob.v = virtual_ref(a)
-            virtual_ref_finish(a)
+            glob.v = vref = virtual_ref(a)
+            virtual_ref_finish(vref, a)
             n -= 1
             return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s
         return None, f, None
diff --git a/pypy/jit/codewriter/call.py b/pypy/jit/codewriter/call.py
--- a/pypy/jit/codewriter/call.py
+++ b/pypy/jit/codewriter/call.py
@@ -219,11 +219,10 @@
                 assert not NON_VOID_ARGS, ("arguments not supported for "
                                            "loop-invariant function!")
         # build the extraeffect
+        can_invalidate = self.quasiimmut_analyzer.analyze(op)
         if extraeffect is None:
             if self.virtualizable_analyzer.analyze(op):
                 extraeffect = EffectInfo.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE
-            elif self.quasiimmut_analyzer.analyze(op):
-                extraeffect = EffectInfo.EF_CAN_INVALIDATE
             elif loopinvariant:
                 extraeffect = EffectInfo.EF_LOOPINVARIANT
             elif pure:
@@ -236,12 +235,14 @@
         #
         effectinfo = effectinfo_from_writeanalyze(
             self.readwrite_analyzer.analyze(op), self.cpu, extraeffect,
-            oopspecindex)
+            oopspecindex, can_invalidate)
         #
         if pure or loopinvariant:
             assert effectinfo is not None
             assert extraeffect != EffectInfo.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE
-            assert extraeffect != EffectInfo.EF_CAN_INVALIDATE
+            # XXX this should also say assert not can_invalidate, but
+            #     it can't because our analyzer is not good enough for now
+            #     (and getexecutioncontext() can't really invalidate)
         #
         return self.cpu.calldescrof(FUNC, tuple(NON_VOID_ARGS), RESULT,
                                     effectinfo)
diff --git a/pypy/jit/codewriter/effectinfo.py b/pypy/jit/codewriter/effectinfo.py
--- a/pypy/jit/codewriter/effectinfo.py
+++ b/pypy/jit/codewriter/effectinfo.py
@@ -13,7 +13,6 @@
     EF_LOOPINVARIANT                   = 1 #special: call it only once per loop
     EF_CANNOT_RAISE                    = 2 #a function which cannot raise
     EF_CAN_RAISE                       = 3 #normal function (can raise)
-    EF_CAN_INVALIDATE                  = 4 #can force all GUARD_NOT_INVALIDATED
     EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE = 5 #can raise and force virtualizables
 
     # the 'oopspecindex' field is one of the following values:
@@ -79,7 +78,8 @@
     def __new__(cls, readonly_descrs_fields,
                 write_descrs_fields, write_descrs_arrays,
                 extraeffect=EF_CAN_RAISE,
-                oopspecindex=OS_NONE):
+                oopspecindex=OS_NONE,
+                can_invalidate=False):
         key = (frozenset(readonly_descrs_fields),
                frozenset(write_descrs_fields),
                frozenset(write_descrs_arrays),
@@ -97,19 +97,21 @@
             result.write_descrs_fields = write_descrs_fields
             result.write_descrs_arrays = write_descrs_arrays
         result.extraeffect = extraeffect
+        result.can_invalidate = can_invalidate
         result.oopspecindex = oopspecindex
         cls._cache[key] = result
         return result
 
     def check_can_invalidate(self):
-        return self.extraeffect >= self.EF_CAN_INVALIDATE
+        return self.can_invalidate
 
     def check_forces_virtual_or_virtualizable(self):
         return self.extraeffect >= self.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE
 
 def effectinfo_from_writeanalyze(effects, cpu,
                                  extraeffect=EffectInfo.EF_CAN_RAISE,
-                                 oopspecindex=EffectInfo.OS_NONE):
+                                 oopspecindex=EffectInfo.OS_NONE,
+                                 can_invalidate=False):
     from pypy.translator.backendopt.writeanalyze import top_set
     if effects is top_set:
         return None
@@ -147,7 +149,8 @@
                       write_descrs_fields,
                       write_descrs_arrays,
                       extraeffect,
-                      oopspecindex)
+                      oopspecindex,
+                      can_invalidate)
 
 def consider_struct(TYPE, fieldname):
     if fieldType(TYPE, fieldname) is lltype.Void:
diff --git a/pypy/jit/codewriter/jitcode.py b/pypy/jit/codewriter/jitcode.py
--- a/pypy/jit/codewriter/jitcode.py
+++ b/pypy/jit/codewriter/jitcode.py
@@ -100,6 +100,9 @@
     def __repr__(self):
         return '<JitCode %r>' % self.name
 
+    def _clone_if_mutable(self):
+        raise NotImplementedError
+    
 class MissingLiveness(Exception):
     pass
 
@@ -111,6 +114,9 @@
         dict = getattr(self, 'dict', '?')
         return '<SwitchDictDescr %s>' % (dict,)
 
+    def _clone_if_mutable(self):
+        raise NotImplementedError
+
 
 class LiveVarsInfo(object):
     def __init__(self, live_i, live_r, live_f):
diff --git a/pypy/jit/codewriter/jtransform.py b/pypy/jit/codewriter/jtransform.py
--- a/pypy/jit/codewriter/jtransform.py
+++ b/pypy/jit/codewriter/jtransform.py
@@ -209,7 +209,6 @@
     def rewrite_op_cast_int_to_unichar(self, op): pass
     def rewrite_op_cast_int_to_uint(self, op): pass
     def rewrite_op_cast_uint_to_int(self, op): pass
-    def rewrite_op_resume_point(self, op): pass
 
     def _rewrite_symmetric(self, op):
         """Rewrite 'c1+v2' into 'v2+c1' in an attempt to avoid generating
diff --git a/pypy/jit/codewriter/policy.py b/pypy/jit/codewriter/policy.py
--- a/pypy/jit/codewriter/policy.py
+++ b/pypy/jit/codewriter/policy.py
@@ -63,12 +63,27 @@
             contains_loop = contains_loop and not getattr(
                     func, '_jit_unroll_safe_', False)
 
-        res = see_function and not contains_unsupported_variable_type(graph,
-                                                        self.supports_floats,
-                                                        self.supports_longlong)
+        unsupported = contains_unsupported_variable_type(graph,
+                                                         self.supports_floats,
+                                                         self.supports_longlong)
+        res = see_function and not unsupported
         if res and contains_loop:
             self.unsafe_loopy_graphs.add(graph)
-        return res and not contains_loop
+        res = res and not contains_loop
+        if (see_function and not res and
+            getattr(graph, "access_directly", False)):
+            # This happens when we have a function which has an argument with
+            # the access_directly flag, and the annotator has determined we will
+            # see the function. (See
+            # pypy/annotation/specialize.py:default_specialize) However,
+            # look_inside_graph just decided that we will not see it. (It has a
+            # loop or unsupported variables.) If we return False, the call will
+            # be turned into a residual call, but the graph is access_directly!
+            # If such a function is called and accesses a virtualizable, the JIT
+            # will not notice, and the virtualizable will fall out of sync. So,
+            # we fail loudly now.
+            raise ValueError("access_directly on a function which we don't see %s" % graph)
+        return res
 
 def contains_unsupported_variable_type(graph, supports_floats,
                                        supports_longlong):
diff --git a/pypy/jit/codewriter/test/test_policy.py b/pypy/jit/codewriter/test/test_policy.py
--- a/pypy/jit/codewriter/test/test_policy.py
+++ b/pypy/jit/codewriter/test/test_policy.py
@@ -1,4 +1,5 @@
 import sys
+import py
 from pypy.jit.codewriter.policy import contains_unsupported_variable_type
 from pypy.jit.codewriter.policy import JitPolicy
 from pypy.jit.codewriter import support
@@ -107,3 +108,19 @@
                     mod = called_graph.func.__module__
                     assert (mod == 'pypy.rpython.rlist' or
                             mod == 'pypy.rpython.lltypesystem.rlist')
+
+def test_access_directly_but_not_seen():
+    class X:
+        _virtualizable2_ = ["a"]
+    def h(x, y):
+        w = 0
+        for i in range(y):
+            w += 4
+        return w
+    def f(y):
+        x = jit.hint(X(), access_directly=True)
+        h(x, y)
+    rtyper = support.annotate(f, [3])
+    h_graph = rtyper.annotator.translator.graphs[1]
+    assert h_graph.func is h
+    py.test.raises(ValueError, JitPolicy().look_inside_graph, h_graph)
diff --git a/pypy/jit/conftest.py b/pypy/jit/conftest.py
--- a/pypy/jit/conftest.py
+++ b/pypy/jit/conftest.py
@@ -5,7 +5,4 @@
     group.addoption('--slow', action="store_true",
            default=False, dest="run_slow_tests",
            help="run all the compiled tests (instead of just a few)")
-    group.addoption('--viewloops', action="store_true",
-           default=False, dest="viewloops",
-           help="show only the compiled loops")
 
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
@@ -97,7 +97,7 @@
 
     history = metainterp.history
     loop = create_empty_loop(metainterp)
-    loop.inputargs = history.inputargs
+    loop.inputargs = history.inputargs[:]
     for box in loop.inputargs:
         assert isinstance(box, Box)
     # make a copy, because optimize_loop can mutate the ops and descrs
@@ -124,18 +124,21 @@
         return old_loop_token
 
     if loop.preamble.operations is not None:
-        send_loop_to_backend(metainterp_sd, loop, "loop")
+        send_loop_to_backend(greenkey, jitdriver_sd, metainterp_sd, loop,
+                             "loop")
         record_loop_or_bridge(metainterp_sd, loop)
         token = loop.preamble.token
         if full_preamble_needed:
-            send_loop_to_backend(metainterp_sd, loop.preamble, "entry bridge")
+            send_loop_to_backend(greenkey, jitdriver_sd, metainterp_sd,
+                                 loop.preamble, "entry bridge")
             insert_loop_token(old_loop_tokens, loop.preamble.token)
             jitdriver_sd.warmstate.attach_unoptimized_bridge_from_interp(
                 greenkey, loop.preamble.token)
             record_loop_or_bridge(metainterp_sd, loop.preamble)
         return token
     else:
-        send_loop_to_backend(metainterp_sd, loop, "loop")
+        send_loop_to_backend(greenkey, jitdriver_sd, metainterp_sd, loop,
+                             "loop")
         insert_loop_token(old_loop_tokens, loop_token)
         jitdriver_sd.warmstate.attach_unoptimized_bridge_from_interp(
             greenkey, loop.token)
@@ -150,7 +153,9 @@
     # XXX do we still need a list?
     old_loop_tokens.append(loop_token)
 
-def send_loop_to_backend(metainterp_sd, loop, type):
+def send_loop_to_backend(greenkey, jitdriver_sd, metainterp_sd, loop, type):
+    jitdriver_sd.on_compile(metainterp_sd.logger_ops, loop.token,
+                            loop.operations, type, greenkey)
     globaldata = metainterp_sd.globaldata
     loop_token = loop.token
     loop_token.number = n = globaldata.loopnumbering
@@ -186,8 +191,11 @@
     if metainterp_sd.warmrunnerdesc is not None:    # for tests
         metainterp_sd.warmrunnerdesc.memory_manager.keep_loop_alive(loop.token)
 
-def send_bridge_to_backend(metainterp_sd, faildescr, inputargs, operations,
-                           original_loop_token):
+def send_bridge_to_backend(jitdriver_sd, metainterp_sd, faildescr, inputargs,
+                           operations, original_loop_token):
+    n = metainterp_sd.cpu.get_fail_descr_number(faildescr)
+    jitdriver_sd.on_compile_bridge(metainterp_sd.logger_ops,
+                                   original_loop_token, operations, n)
     if not we_are_translated():
         show_loop(metainterp_sd)
         TreeLoop.check_consistency_of(inputargs, operations)
@@ -204,7 +212,6 @@
         metainterp_sd.stats.compiled()
     metainterp_sd.log("compiled new bridge")
     #
-    n = metainterp_sd.cpu.get_fail_descr_number(faildescr)
     metainterp_sd.logger_ops.log_bridge(inputargs, operations, n, ops_offset)
     #
     if metainterp_sd.warmrunnerdesc is not None:    # for tests
@@ -390,8 +397,9 @@
         inputargs = metainterp.history.inputargs
         if not we_are_translated():
             self._debug_suboperations = new_loop.operations
-        send_bridge_to_backend(metainterp.staticdata, self, inputargs,
-                               new_loop.operations, new_loop.token)
+        send_bridge_to_backend(metainterp.jitdriver_sd, metainterp.staticdata,
+                               self, inputargs, new_loop.operations,
+                               new_loop.token)
 
     def copy_all_attributes_into(self, res):
         # XXX a bit ugly to have to list them all here
@@ -570,7 +578,8 @@
         # to every guard in the loop.
         new_loop_token = make_loop_token(len(redargs), jitdriver_sd)
         new_loop.token = new_loop_token
-        send_loop_to_backend(metainterp_sd, new_loop, "entry bridge")
+        send_loop_to_backend(self.original_greenkey, metainterp.jitdriver_sd,
+                             metainterp_sd, new_loop, "entry bridge")
         # send the new_loop to warmspot.py, to be called directly the next time
         jitdriver_sd.warmstate.attach_unoptimized_bridge_from_interp(
             self.original_greenkey,
@@ -600,7 +609,7 @@
     # Attempt to use optimize_bridge().  This may return None in case
     # it does not work -- i.e. none of the existing old_loop_tokens match.
     new_loop = create_empty_loop(metainterp)
-    new_loop.inputargs = metainterp.history.inputargs
+    new_loop.inputargs = metainterp.history.inputargs[:]
     # clone ops, as optimize_bridge can mutate the ops
     new_loop.operations = [op.clone() for op in metainterp.history.operations]
     metainterp_sd = metainterp.staticdata
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
@@ -294,8 +294,8 @@
         cpu.set_future_value_int(j, self.value)
 
     def same_constant(self, other):
-        if isinstance(other, Const):
-            return self.value == other.getint()
+        if isinstance(other, ConstInt):
+            return self.value == other.value
         return False
 
     def nonnull(self):
@@ -787,7 +787,6 @@
 
     def dump(self):
         self.compiled_loop_token.cpu.dump_loop_token(self)
-
 class TreeLoop(object):
     inputargs = None
     operations = None
@@ -957,7 +956,7 @@
     compiled_count = 0
     enter_count = 0
     aborted_count = 0
-    history = None
+    operations = None
 
     def __init__(self):
         self.loops = []
@@ -965,7 +964,7 @@
         self.aborted_keys = []
 
     def set_history(self, history):
-        self.history = history
+        self.operations = history.operations
 
     def aborted(self):
         self.aborted_count += 1
@@ -995,7 +994,7 @@
 
     def check_history(self, expected=None, **check):
         insns = {}
-        for op in self.history.operations:
+        for op in self.operations:
             opname = op.getopname()
             insns[opname] = insns.get(opname, 0) + 1
         if expected is not None:
diff --git a/pypy/jit/metainterp/jitdriver.py b/pypy/jit/metainterp/jitdriver.py
--- a/pypy/jit/metainterp/jitdriver.py
+++ b/pypy/jit/metainterp/jitdriver.py
@@ -20,6 +20,7 @@
     #    self.portal_finishtoken... pypy.jit.metainterp.pyjitpl
     #    self.index             ... pypy.jit.codewriter.call
     #    self.mainjitcode       ... pypy.jit.codewriter.call
+    #    self.on_compile        ... pypy.jit.metainterp.warmstate
 
     # These attributes are read by the backend in CALL_ASSEMBLER:
     #    self.assembler_helper_adr
diff --git a/pypy/jit/metainterp/logger.py b/pypy/jit/metainterp/logger.py
--- a/pypy/jit/metainterp/logger.py
+++ b/pypy/jit/metainterp/logger.py
@@ -75,6 +75,40 @@
         else:
             return '?'
 
+    def repr_of_resop(self, memo, op, ops_offset=None):
+        if op.getopnum() == rop.DEBUG_MERGE_POINT:
+            loc = op.getarg(0)._get_str()
+            reclev = op.getarg(1).getint()
+            return "debug_merge_point('%s', %s)" % (loc, reclev)
+        if ops_offset is None:
+            offset = -1
+        else:
+            offset = ops_offset.get(op, -1)
+        if offset == -1:
+            s_offset = ""
+        else:
+            s_offset = "+%d: " % offset
+        args = ", ".join([self.repr_of_arg(memo, op.getarg(i)) for i in range(op.numargs())])
+        if op.result is not None:
+            res = self.repr_of_arg(memo, op.result) + " = "
+        else:
+            res = ""
+        is_guard = op.is_guard()
+        if op.getdescr() is not None:
+            descr = op.getdescr()
+            if is_guard and self.guard_number:
+                index = self.metainterp_sd.cpu.get_fail_descr_number(descr)
+                r = "<Guard%d>" % index
+            else:
+                r = self.repr_of_descr(descr)
+            args += ', descr=' +  r
+        if is_guard and op.getfailargs() is not None:
+            fail_args = ' [' + ", ".join([self.repr_of_arg(memo, arg)
+                                          for arg in op.getfailargs()]) + ']'
+        else:
+            fail_args = ''
+        return s_offset + res + op.getopname() + '(' + args + ')' + fail_args
+
     def _log_operations(self, inputargs, operations, ops_offset):
         if not have_debug_prints():
             return
@@ -86,37 +120,7 @@
             debug_print('[' + args + ']')
         for i in range(len(operations)):
             op = operations[i]
-            if op.getopnum() == rop.DEBUG_MERGE_POINT:
-                loc = op.getarg(0)._get_str()
-                reclev = op.getarg(1).getint()
-                debug_print("debug_merge_point('%s', %s)" % (loc, reclev))
-                continue
-            offset = ops_offset.get(op, -1)
-            if offset == -1:
-                s_offset = ""
-            else:
-                s_offset = "+%d: " % offset
-            args = ", ".join([self.repr_of_arg(memo, op.getarg(i)) for i in range(op.numargs())])
-            if op.result is not None:
-                res = self.repr_of_arg(memo, op.result) + " = "
-            else:
-                res = ""
-            is_guard = op.is_guard()
-            if op.getdescr() is not None:
-                descr = op.getdescr()
-                if is_guard and self.guard_number:
-                    index = self.metainterp_sd.cpu.get_fail_descr_number(descr)
-                    r = "<Guard%d>" % index
-                else:
-                    r = self.repr_of_descr(descr)
-                args += ', descr=' +  r
-            if is_guard and op.getfailargs() is not None:
-                fail_args = ' [' + ", ".join([self.repr_of_arg(memo, arg)
-                                              for arg in op.getfailargs()]) + ']'
-            else:
-                fail_args = ''
-            debug_print(s_offset + res + op.getopname() +
-                        '(' + args + ')' + fail_args)
+            debug_print(self.repr_of_resop(memo, operations[i], ops_offset))
         if ops_offset and None in ops_offset:
             offset = ops_offset[None]
             debug_print("+%d: --end of the loop--" % offset)
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
@@ -161,6 +161,9 @@
             if self.nextop.getopnum() == rop.GUARD_NO_OVERFLOW:
                 # Synthesize the non overflowing op for optimize_default to reuse
                 self.pure(rop.INT_ADD, op.getarglist()[:], op.result)
+                # Synthesize the reverse op for optimize_default to reuse
+                self.pure(rop.INT_SUB, [op.result, op.getarg(1)], op.getarg(0))
+                self.pure(rop.INT_SUB, [op.result, op.getarg(0)], op.getarg(1))
 
 
     def optimize_INT_SUB_OVF(self, op):
@@ -180,6 +183,10 @@
             if self.nextop.getopnum() == rop.GUARD_NO_OVERFLOW:
                 # Synthesize the non overflowing op for optimize_default to reuse
                 self.pure(rop.INT_SUB, op.getarglist()[:], op.result)
+                # Synthesize the reverse ops for optimize_default to reuse
+                self.pure(rop.INT_ADD, [op.result, op.getarg(1)], op.getarg(0))
+                self.pure(rop.INT_SUB, [op.getarg(0), op.result], op.getarg(1))
+                
 
     def optimize_INT_MUL_OVF(self, op):
         v1 = self.getvalue(op.getarg(0))
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
@@ -415,14 +415,22 @@
         dest_start_box = self.get_constant_box(op.getarg(4))
         length = self.get_constant_box(op.getarg(5))
         if (source_value.is_virtual() and source_start_box and dest_start_box
-            and length and dest_value.is_virtual()):
-            # XXX optimize the case where dest value is not virtual,
-            #     but we still can avoid a mess
+            and length and (dest_value.is_virtual() or length.getint() <= 8)):
+            from pypy.jit.metainterp.optimizeopt.virtualize import VArrayValue
+            assert isinstance(source_value, VArrayValue)
             source_start = source_start_box.getint()
             dest_start = dest_start_box.getint()
             for index in range(length.getint()):
                 val = source_value.getitem(index + source_start)
-                dest_value.setitem(index + dest_start, val)
+                if dest_value.is_virtual():
+                    dest_value.setitem(index + dest_start, val)
+                else:
+                    newop = ResOperation(rop.SETARRAYITEM_GC,
+                                         [op.getarg(2),
+                                          ConstInt(index + dest_start),
+                                          val.force_box()], None,
+                                         descr=source_value.arraydescr)
+                    self.emit_operation(newop)
             return True
         if length and length.getint() == 0:
             return True # 0-length arraycopy
@@ -432,6 +440,9 @@
         v1 = self.getvalue(op.getarg(0))
         v2 = self.getvalue(op.getarg(1))
 
+        if v2.is_constant() and v2.box.getint() == 1:
+            self.make_equal_to(op.result, v1)
+            return
         if v1.intbound.known_ge(IntBound(0, 0)) and v2.is_constant():
             val = v2.box.getint()
             if val & (val - 1) == 0 and val > 0: # val == 2**shift
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
@@ -330,18 +330,28 @@
         vrefvalue.setfield(descr_virtual_token, self.getvalue(tokenbox))
 
     def optimize_VIRTUAL_REF_FINISH(self, op):
-        # Set the 'forced' field of the virtual_ref.
-        # In good cases, this is all virtual, so has no effect.
-        # Otherwise, this forces the real object -- but only now, as
-        # opposed to much earlier.  This is important because the object is
-        # typically a PyPy PyFrame, and now is the end of its execution, so
-        # forcing it now does not have catastrophic effects.
+        # This operation is used in two cases.  In normal cases, it
+        # is the end of the frame, and op.getarg(1) is NULL.  In this
+        # case we just clear the vref.virtual_token, because it contains
+        # a stack frame address and we are about to leave the frame.
+        # In that case vref.forced should still be NULL, and remains
+        # NULL; and accessing the frame through the vref later is
+        # *forbidden* and will raise InvalidVirtualRef.
+        #
+        # In the other (uncommon) case, the operation is produced
+        # earlier, because the vref was forced during tracing already.
+        # In this case, op.getarg(1) is the virtual to force, and we
+        # have to store it in vref.forced.
+        #
         vrefinfo = self.optimizer.metainterp_sd.virtualref_info
-        # op.getarg(1) should really never point to null here
+        seo = self.optimizer.send_extra_operation
+
         # - set 'forced' to point to the real object
-        seo = self.optimizer.send_extra_operation
-        seo(ResOperation(rop.SETFIELD_GC, op.getarglist(), None,
-                         descr = vrefinfo.descr_forced))
+        objbox = op.getarg(1)
+        if not self.optimizer.cpu.ts.CONST_NULL.same_constant(objbox):
+            seo(ResOperation(rop.SETFIELD_GC, op.getarglist(), None,
+                             descr = vrefinfo.descr_forced))
+        
         # - set 'virtual_token' to TOKEN_NONE
         args = [op.getarg(0), ConstInt(vrefinfo.TOKEN_NONE)]
         seo(ResOperation(rop.SETFIELD_GC, args, None,
diff --git a/pypy/jit/metainterp/pyjitpl.py b/pypy/jit/metainterp/pyjitpl.py
--- a/pypy/jit/metainterp/pyjitpl.py
+++ b/pypy/jit/metainterp/pyjitpl.py
@@ -4,7 +4,7 @@
 from pypy.rlib.unroll import unrolling_iterable
 from pypy.rlib.debug import debug_start, debug_stop, debug_print
 from pypy.rlib.debug import make_sure_not_resized
-from pypy.rlib import nonconst
+from pypy.rlib import nonconst, rstack
 
 from pypy.jit.metainterp import history, compile, resume
 from pypy.jit.metainterp.history import Const, ConstInt, ConstPtr, ConstFloat
@@ -867,7 +867,6 @@
         any_operation = len(self.metainterp.history.operations) > 0
         jitdriver_sd = self.metainterp.staticdata.jitdrivers_sd[jdindex]
         self.verify_green_args(jitdriver_sd, greenboxes)
-        # xxx we may disable the following line in some context later
         self.debug_merge_point(jitdriver_sd, self.metainterp.in_recursion,
                                greenboxes)
 
@@ -1049,8 +1048,10 @@
         vrefinfo = metainterp.staticdata.virtualref_info
         vref = vrefbox.getref_base()
         if vrefinfo.is_virtual_ref(vref):
+            # XXX write a comment about nullbox
+            nullbox = self.metainterp.cpu.ts.CONST_NULL
             metainterp.history.record(rop.VIRTUAL_REF_FINISH,
-                                      [vrefbox, lastbox], None)
+                                      [vrefbox, nullbox], None)
 
     @arguments()
     def opimpl_ll_read_timestamp(self):
@@ -1844,9 +1845,9 @@
                 else:
                     self.compile(original_boxes, live_arg_boxes, start, resumedescr)
                 # creation of the loop was cancelled!
-                #self.staticdata.log('cancelled, tracing more...')
-                self.staticdata.log('cancelled, stopping tracing')
-                raise SwitchToBlackhole(ABORT_BAD_LOOP)
+                self.staticdata.log('cancelled, tracing more...')
+                #self.staticdata.log('cancelled, stopping tracing')
+                #raise SwitchToBlackhole(ABORT_BAD_LOOP)
 
         # Otherwise, no loop found so far, so continue tracing.
         start = len(self.history.operations)
@@ -1911,6 +1912,7 @@
 
     def compile(self, original_boxes, live_arg_boxes, start, start_resumedescr):
         num_green_args = self.jitdriver_sd.num_green_args
+        original_inputargs = self.history.inputargs
         self.history.inputargs = original_boxes[num_green_args:]
         greenkey = original_boxes[:num_green_args]
         old_loop_tokens = self.get_compiled_merge_points(greenkey)
@@ -1919,7 +1921,11 @@
                                               greenkey, start, start_resumedescr)
         if loop_token is not None: # raise if it *worked* correctly
             self.set_compiled_merge_points(greenkey, old_loop_tokens)
+            self.history.inputargs = None
+            self.history.operations = None
             raise GenerateMergePoint(live_arg_boxes, loop_token)
+
+        self.history.inputargs = original_inputargs
         self.history.operations.pop()     # remove the JUMP
         # FIXME: Why is self.history.inputargs not restored?
 
@@ -1936,10 +1942,12 @@
             target_loop_token = compile.compile_new_bridge(self,
                                                            old_loop_tokens,
                                                            self.resumekey)
-            if target_loop_token is not None: # raise if it *worked* correctly
-                raise GenerateMergePoint(live_arg_boxes, target_loop_token)
         finally:
             self.history.operations.pop()     # remove the JUMP
+        if target_loop_token is not None: # raise if it *worked* correctly
+            self.history.inputargs = None
+            self.history.operations = None
+            raise GenerateMergePoint(live_arg_boxes, target_loop_token)
 
     def compile_bridge_and_loop(self, original_boxes, live_arg_boxes, start,
                                 bridge_arg_boxes, start_resumedescr):
@@ -1974,7 +1982,8 @@
             assert False
         assert target_loop_token is not None
 
-        self.history.operations = original_operations
+        self.history.inputargs = None
+        self.history.operations = None
         raise GenerateMergePoint(live_arg_boxes, old_loop_tokens[0])
 
     def compile_done_with_this_frame(self, exitbox):
@@ -2044,10 +2053,16 @@
 
     def initialize_state_from_guard_failure(self, resumedescr):
         # guard failure: rebuild a complete MIFrame stack
-        self.in_recursion = -1 # always one portal around
-        self.history = history.History()
-        inputargs_and_holes = self.rebuild_state_after_failure(resumedescr)
-        self.history.inputargs = [box for box in inputargs_and_holes if box]
+        # This is stack-critical code: it must not be interrupted by StackOverflow,
+        # otherwise the jit_virtual_refs are left in a dangling state.
+        rstack._stack_criticalcode_start()
+        try:
+            self.in_recursion = -1 # always one portal around
+            self.history = history.History()
+            inputargs_and_holes = self.rebuild_state_after_failure(resumedescr)
+            self.history.inputargs = [box for box in inputargs_and_holes if box]
+        finally:
+            rstack._stack_criticalcode_stop()
 
     def initialize_virtualizable(self, original_boxes):
         vinfo = self.jitdriver_sd.virtualizable_info
diff --git a/pypy/jit/metainterp/resume.py b/pypy/jit/metainterp/resume.py
--- a/pypy/jit/metainterp/resume.py
+++ b/pypy/jit/metainterp/resume.py
@@ -6,7 +6,7 @@
 from pypy.jit.metainterp import jitprof
 from pypy.jit.codewriter.effectinfo import EffectInfo
 from pypy.rpython.lltypesystem import lltype, llmemory, rffi, rstr
-from pypy.rlib import rarithmetic
+from pypy.rlib import rarithmetic, rstack
 from pypy.rlib.objectmodel import we_are_translated, specialize
 from pypy.rlib.debug import have_debug_prints, ll_assert
 from pypy.rlib.debug import debug_start, debug_stop, debug_print
@@ -978,12 +978,18 @@
 
 def blackhole_from_resumedata(blackholeinterpbuilder, jitdriver_sd, storage,
                               all_virtuals=None):
-    resumereader = ResumeDataDirectReader(blackholeinterpbuilder.metainterp_sd,
-                                          storage, all_virtuals)
-    vinfo = jitdriver_sd.virtualizable_info
-    ginfo = jitdriver_sd.greenfield_info
-    vrefinfo = blackholeinterpbuilder.metainterp_sd.virtualref_info
-    resumereader.consume_vref_and_vable(vrefinfo, vinfo, ginfo)
+    # The initialization is stack-critical code: it must not be interrupted by
+    # StackOverflow, otherwise the jit_virtual_refs are left in a dangling state.
+    rstack._stack_criticalcode_start()
+    try:
+        resumereader = ResumeDataDirectReader(blackholeinterpbuilder.metainterp_sd,
+                                              storage, all_virtuals)
+        vinfo = jitdriver_sd.virtualizable_info
+        ginfo = jitdriver_sd.greenfield_info
+        vrefinfo = blackholeinterpbuilder.metainterp_sd.virtualref_info
+        resumereader.consume_vref_and_vable(vrefinfo, vinfo, ginfo)
+    finally:
+        rstack._stack_criticalcode_stop()
     #
     # First get a chain of blackhole interpreters whose length is given
     # by the depth of rd_frame_info_list.  The first one we get must be
diff --git a/pypy/jit/metainterp/test/support.py b/pypy/jit/metainterp/test/support.py
--- a/pypy/jit/metainterp/test/support.py
+++ b/pypy/jit/metainterp/test/support.py
@@ -26,6 +26,10 @@
         def attach_unoptimized_bridge_from_interp(self, greenkey, newloop):
             pass
 
+        def helper_func(self, FUNCPTR, func):
+            from pypy.rpython.annlowlevel import llhelper
+            return llhelper(FUNCPTR, func)
+
         def jit_cell_at_key(self, greenkey):
             assert greenkey == []
             return self._cell
@@ -37,6 +41,7 @@
     func._jit_unroll_safe_ = True
     rtyper = support.annotate(func, values, type_system=type_system)
     graphs = rtyper.annotator.translator.graphs
+    testself.all_graphs = graphs
     result_kind = history.getkind(graphs[0].getreturnvar().concretetype)[0]
 
     class FakeJitDriverSD:
@@ -46,6 +51,8 @@
         greenfield_info = None
         result_type = result_kind
         portal_runner_ptr = "???"
+        on_compile = lambda *args: None
+        on_compile_bridge = lambda *args: None
 
     stats = history.Stats()
     cpu = CPUClass(rtyper, stats, None, False)
diff --git a/pypy/jit/metainterp/test/test_ajit.py b/pypy/jit/metainterp/test/test_ajit.py
--- a/pypy/jit/metainterp/test/test_ajit.py
+++ b/pypy/jit/metainterp/test/test_ajit.py
@@ -1864,7 +1864,7 @@
             return a1.val + b1.val
         res = self.meta_interp(g, [3, 23])
         assert res == 7068153
-        self.check_loop_count(6)
+        self.check_loop_count(7)
         self.check_loops(guard_true=4, guard_class=0, int_add=2, int_mul=2,
                          guard_false=2)
 
@@ -2101,6 +2101,79 @@
         assert self.meta_interp(f, [5, 100]) == 0
         self.check_loops(int_rshift=1, everywhere=True)
 
+    def test_inputarg_reset_bug(self):
+        ## j = 0
+        ## while j < 100:
+        ##     j += 1
+
+        ## c = 0
+        ## j = 0
+        ## while j < 2:
+        ##     j += 1
+        ##     if c == 0:
+        ##         c = 1
+        ##     else:
+        ##         c = 0
+
+        ## j = 0
+        ## while j < 100:
+        ##     j += 1
+
+        def get_printable_location(i):
+            return str(i)
+        
+        myjitdriver = JitDriver(greens = ['i'], reds = ['j', 'c', 'a'],
+                                get_printable_location=get_printable_location)
+        bytecode = "0j10jc20a3"
+        def f():
+            myjitdriver.set_param('threshold', 7)
+            myjitdriver.set_param('trace_eagerness', 1)
+            i = j = c = a = 1
+            while True:
+                myjitdriver.jit_merge_point(i=i, j=j, c=c, a=a)
+                if i >= len(bytecode):
+                    break
+                op = bytecode[i]
+                if op == 'j':
+                    j += 1
+                elif op == 'c':
+                    c = hint(c, promote=True)
+                    c = 1 - c
+                elif op == '2':
+                    if j < 3:
+                        i -= 3
+                        myjitdriver.can_enter_jit(i=i, j=j, c=c, a=a)
+                elif op == '1':
+                    k = j*a
+                    if j < 100:
+                        i -= 2
+                        a += k
+                        myjitdriver.can_enter_jit(i=i, j=j, c=c, a=a)
+                    else:
+                        a += k*2
+                elif op == '0':
+                    j = c = a = 0
+                elif op == 'a':
+                    j += 1
+                    a += 1
+                elif op == '3':
+                    if a < 100:
+                        i -= 2
+                        myjitdriver.can_enter_jit(i=i, j=j, c=c, a=a)
+
+                else:
+                    return ord(op)
+                i += 1
+            return 42
+        assert f() == 42
+        def g():
+            res = 1
+            for i in range(10):
+                res = f()
+            return res
+        res = self.meta_interp(g, [])
+        assert res == 42
+
     def test_read_timestamp(self):
         import time
         from pypy.rlib.rtimer import read_timestamp
diff --git a/pypy/jit/metainterp/test/test_history.py b/pypy/jit/metainterp/test/test_history.py
--- a/pypy/jit/metainterp/test/test_history.py
+++ b/pypy/jit/metainterp/test/test_history.py
@@ -9,3 +9,20 @@
     s = lltype.cast_pointer(lltype.Ptr(S), t)
     const = ConstPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s))
     assert const._getrepr_() == "*T"
+
+def test_same_constant():
+    c1a = ConstInt(0)
+    c1b = ConstInt(0)
+    c2a = ConstPtr(lltype.nullptr(llmemory.GCREF.TO))
+    c2b = ConstPtr(lltype.nullptr(llmemory.GCREF.TO))
+    c3a = Const._new(0.0)
+    c3b = Const._new(0.0)
+    assert     c1a.same_constant(c1b)
+    assert not c1a.same_constant(c2b)
+    assert not c1a.same_constant(c3b)
+    assert not c2a.same_constant(c1b)
+    assert     c2a.same_constant(c2b)
+    assert not c2a.same_constant(c3b)
+    assert not c3a.same_constant(c1b)
+    assert not c3a.same_constant(c2b)
+    assert     c3a.same_constant(c3b)
diff --git a/pypy/jit/metainterp/test/test_jitdriver.py b/pypy/jit/metainterp/test/test_jitdriver.py
--- a/pypy/jit/metainterp/test/test_jitdriver.py
+++ b/pypy/jit/metainterp/test/test_jitdriver.py
@@ -10,8 +10,59 @@
 def getloc2(g):
     return "in jitdriver2, with g=%d" % g
 
+class JitDriverTests(object):
+    def test_on_compile(self):
+        called = {}
+        
+        class MyJitDriver(JitDriver):
+            def on_compile(self, logger, looptoken, operations, type, n, m):
+                called[(m, n, type)] = looptoken
 
-class MultipleJitDriversTests:
+        driver = MyJitDriver(greens = ['n', 'm'], reds = ['i'])
+
+        def loop(n, m):
+            i = 0
+            while i < n + m:
+                driver.can_enter_jit(n=n, m=m, i=i)
+                driver.jit_merge_point(n=n, m=m, i=i)
+                i += 1
+
+        self.meta_interp(loop, [1, 4])
+        assert sorted(called.keys()) == [(4, 1, "entry bridge"), (4, 1, "loop")]
+        self.meta_interp(loop, [2, 4])
+        assert sorted(called.keys()) == [(4, 1, "entry bridge"), (4, 1, "loop"),
+                                         (4, 2, "entry bridge"), (4, 2, "loop")]
+
+    def test_on_compile_bridge(self):
+        called = {}
+        
+        class MyJitDriver(JitDriver):
+            def on_compile(self, logger, looptoken, operations, type, n, m):
+                called[(m, n, type)] = loop
+            def on_compile_bridge(self, logger, orig_token, operations, n):
+                assert 'bridge' not in called
+                called['bridge'] = orig_token
+
+        driver = MyJitDriver(greens = ['n', 'm'], reds = ['i'])
+
+        def loop(n, m):
+            i = 0
+            while i < n + m:
+                driver.can_enter_jit(n=n, m=m, i=i)
+                driver.jit_merge_point(n=n, m=m, i=i)
+                if i >= 4:
+                    i += 2
+                i += 1
+
+        self.meta_interp(loop, [1, 10])
+        assert sorted(called.keys()) == ['bridge', (10, 1, "entry bridge"),
+                                         (10, 1, "loop")]
+
+
+class TestLLtypeSingle(JitDriverTests, LLJitMixin):
+    pass
+
+class MultipleJitDriversTests(object):
 
     def test_simple(self):
         myjitdriver1 = JitDriver(greens=[], reds=['n', 'm'],
diff --git a/pypy/jit/metainterp/test/test_list.py b/pypy/jit/metainterp/test/test_list.py
--- a/pypy/jit/metainterp/test/test_list.py
+++ b/pypy/jit/metainterp/test/test_list.py
@@ -236,4 +236,8 @@
             return a * b
         res = self.meta_interp(f, [37])
         assert res == f(37)
-        self.check_loops(getfield_gc=1, everywhere=True)
+        # There is the one actual field on a, plus 2 getfield's from the list
+        # itself, 1 to get the length (which is then incremented and passed to
+        # the resize func), and then a read of the items field to actually
+        # perform the setarrayitem on
+        self.check_loops(getfield_gc=5, everywhere=True)
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
@@ -3402,6 +3402,56 @@
         '''
         self.optimize_loop(ops, expected)
 
+    def test_arraycopy_dest_not_virtual(self):
+        ops = '''
+        []
+        p1 = new_array(3, descr=arraydescr)
+        p2 = new_array(3, descr=arraydescr)
+        setarrayitem_gc(p1, 2, 10, descr=arraydescr)
+        setarrayitem_gc(p2, 2, 13, descr=arraydescr)
+        escape(p2)
+        call(0, p1, p2, 0, 0, 3, descr=arraycopydescr)
+        escape(p2)
+        jump()
+        '''
+        expected = '''
+        []
+        p2 = new_array(3, descr=arraydescr)
+        setarrayitem_gc(p2, 2, 13, descr=arraydescr)
+        escape(p2)
+        setarrayitem_gc(p2, 0, 0, descr=arraydescr)
+        setarrayitem_gc(p2, 1, 0, descr=arraydescr)
+        setarrayitem_gc(p2, 2, 10, descr=arraydescr)
+        escape(p2)
+        jump()
+        '''
+        self.optimize_loop(ops, expected)
+
+    def test_arraycopy_dest_not_virtual_too_long(self):
+        ops = '''
+        []
+        p1 = new_array(10, descr=arraydescr)
+        p2 = new_array(10, descr=arraydescr)
+        setarrayitem_gc(p1, 2, 10, descr=arraydescr)
+        setarrayitem_gc(p2, 2, 13, descr=arraydescr)
+        escape(p2)
+        call(0, p1, p2, 0, 0, 10, descr=arraycopydescr)
+        escape(p2)
+        jump()
+        '''
+        expected = '''
+        []
+        p2 = new_array(10, descr=arraydescr)
+        setarrayitem_gc(p2, 2, 13, descr=arraydescr)
+        escape(p2)
+        p1 = new_array(10, descr=arraydescr)
+        setarrayitem_gc(p1, 2, 10, descr=arraydescr)
+        call(0, p1, p2, 0, 0, 10, descr=arraycopydescr)
+        escape(p2)
+        jump()
+        '''
+        self.optimize_loop(ops, expected)
+
     def test_bound_lt(self):
         ops = """
         [i0]
@@ -3900,6 +3950,50 @@
         """
         self.optimize_loop(ops, expected)
 
+    def test_add_sub_ovf(self):
+        ops = """
+        [i1]
+        i2 = int_add_ovf(i1, 1)
+        guard_no_overflow() []
+        i3 = int_sub_ovf(i2, 1)
+        guard_no_overflow() []
+        escape(i3)
+        jump(i2)
+        """
+        expected = """
+        [i1]
+        i2 = int_add_ovf(i1, 1)
+        guard_no_overflow() []
+        escape(i1)
+        jump(i2)
+        """
+        self.optimize_loop(ops, expected)
+
+    def test_add_sub_ovf_virtual_unroll(self):
+        ops = """
+        [p15]
+        i886 = getfield_gc_pure(p15, descr=valuedescr)
+        i888 = int_sub_ovf(i886, 1)
+        guard_no_overflow() []
+        escape(i888)
+        i4360 = getfield_gc_pure(p15, descr=valuedescr)
+        i4362 = int_add_ovf(i4360, 1)
+        guard_no_overflow() []
+        i4360p = int_sub_ovf(i4362, 1)
+        guard_no_overflow() []
+        p4364 = new_with_vtable(ConstClass(node_vtable))
+        setfield_gc(p4364, i4362, descr=valuedescr)
+        jump(p4364)
+        """
+        expected = """
+        [i0, i1]
+        escape(i1)
+        i2 = int_add_ovf(i0, 1)
+        guard_no_overflow() []
+        jump(i2, i0)
+        """
+        self.optimize_loop(ops, expected)
+
     def test_framestackdepth_overhead(self):
         ops = """
         [p0, i22]
@@ -4376,7 +4470,6 @@
         i8 = int_floordiv(4, i2)
         i9 = int_rshift(i1, 2)
         i10 = int_floordiv(i1, 0)
-        i11 = int_rshift(i1, 0)
         i12 = int_floordiv(i2, 2)
         i13 = int_floordiv(i2, 3)
         i14 = int_floordiv(i2, 4)
@@ -4453,6 +4546,18 @@
         """
         self.optimize_loop(ops, expected)
 
+    def test_int_div_1(self):
+        ops = """
+        [i0]
+        i1 = int_floordiv(i0, 1)
+        jump(i1)
+        """
+        expected = """
+        [i0]
+        jump(i0)
+        """
+        self.optimize_loop(ops, expected)
+
     def test_subsub_ovf(self):
         ops = """
         [i0]
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
@@ -133,7 +133,8 @@
                                  EffectInfo([adescr], [], []))
     mayforcevirtdescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
                  EffectInfo([nextdescr], [], [],
-                            EffectInfo.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE))
+                            EffectInfo.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE,
+                            can_invalidate=True))
     arraycopydescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
                  EffectInfo([], [], [], oopspecindex=EffectInfo.OS_ARRAYCOPY))
 
diff --git a/pypy/jit/metainterp/test/test_resoperation.py b/pypy/jit/metainterp/test/test_resoperation.py
--- a/pypy/jit/metainterp/test/test_resoperation.py
+++ b/pypy/jit/metainterp/test/test_resoperation.py
@@ -72,7 +72,7 @@
 def test_get_deep_immutable_oplist():
     ops = [rop.ResOperation(rop.rop.INT_ADD, ['a', 'b'], 'c')]
     newops = rop.get_deep_immutable_oplist(ops)
-    py.test.raises(AttributeError, "newops.append('foobar')")
+    py.test.raises(TypeError, "newops.append('foobar')")
     py.test.raises(TypeError, "newops[0] = 'foobar'")
     py.test.raises(AssertionError, "newops[0].setarg(0, 'd')")
     py.test.raises(AssertionError, "newops[0].setdescr('foobar')")
diff --git a/pypy/jit/metainterp/test/test_send.py b/pypy/jit/metainterp/test/test_send.py
--- a/pypy/jit/metainterp/test/test_send.py
+++ b/pypy/jit/metainterp/test/test_send.py
@@ -204,7 +204,6 @@
         # InvalidLoop condition, and was then unrolled, giving two copies
         # of the body in a single bigger loop with no failing guard except
         # the final one.
-        py.test.skip('dissabled "try to trace some more when compile fails"')
         self.check_loop_count(1)
         self.check_loops(guard_class=0,
                                 int_add=2, int_sub=2)
@@ -231,6 +230,7 @@
                 return self.y
         w1 = W1(10)
         w2 = W2(20)
+
         def f(x, y):
             if x & 1:
                 w = w1
@@ -246,7 +246,6 @@
         assert res == f(3, 28)
         res = self.meta_interp(f, [4, 28])
         assert res == f(4, 28)
-        py.test.skip('dissabled "try to trace some more when compile fails"')
         self.check_loop_count(1)
         self.check_loops(guard_class=0,
                                 int_add=2, int_sub=2)
diff --git a/pypy/jit/metainterp/test/test_tl.py b/pypy/jit/metainterp/test/test_tl.py
--- a/pypy/jit/metainterp/test/test_tl.py
+++ b/pypy/jit/metainterp/test/test_tl.py
@@ -58,7 +58,7 @@
             exit:
                 RETURN
         ''')
-        
+
         codes = [code, code2]
         def main(n, inputarg):
             code = codes[n]
@@ -116,7 +116,7 @@
         codes = [code, '']
         def main(num, arg):
             return interp(codes[num], inputarg=arg)
-        
+
         res = self.meta_interp(main, [0, 20], enable_opts='',
                                listops=listops, backendopt=True, policy=policy)
         assert res == 0
@@ -128,7 +128,6 @@
         from pypy.jit.tl.tl import Stack
         methods = [Stack.put,
                    Stack.pick,
-                   Stack.roll,
                    Stack.append,
                    Stack.pop]
         for meth in methods:
diff --git a/pypy/jit/metainterp/test/test_virtualref.py b/pypy/jit/metainterp/test/test_virtualref.py
--- a/pypy/jit/metainterp/test/test_virtualref.py
+++ b/pypy/jit/metainterp/test/test_virtualref.py
@@ -1,9 +1,10 @@
 import py
 from pypy.rpython.lltypesystem import lltype, llmemory, lloperation
+from pypy.rpython.llinterp import LLException
 from pypy.rlib.jit import JitDriver, dont_look_inside, vref_None
-from pypy.rlib.jit import virtual_ref, virtual_ref_finish
+from pypy.rlib.jit import virtual_ref, virtual_ref_finish, InvalidVirtualRef
 from pypy.rlib.objectmodel import compute_unique_id
-from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
+from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin, _get_jitcodes
 from pypy.jit.metainterp.resoperation import rop
 from pypy.jit.metainterp.virtualref import VirtualRefInfo
 
@@ -16,6 +17,29 @@
         self.vrefinfo = VirtualRefInfo(self.warmrunnerstate)
         self.cw.setup_vrefinfo(self.vrefinfo)
 
+    def test_rewrite_graphs(self):
+        class X:
+            pass
+        def fn():
+            x = X()
+            vref = virtual_ref(x)
+            x1 = vref()                  # jit_force_virtual
+            virtual_ref_finish(vref, x)
+        #
+        _get_jitcodes(self, self.CPUClass, fn, [], self.type_system)
+        graph = self.all_graphs[0]
+        assert graph.name == 'fn'
+        self.vrefinfo.replace_force_virtual_with_call([graph])
+        #
+        def check_call(op, fname):
+            assert op.opname == 'direct_call'
+            assert op.args[0].value._obj._name == fname
+        #
+        ops = [op for block, op in graph.iterblockops()]
+        check_call(ops[-3], 'virtual_ref')
+        check_call(ops[-2], 'force_virtual_if_necessary')
+        check_call(ops[-1], 'virtual_ref_finish')
+
     def test_make_vref_simple(self):
         class X:
             pass
@@ -25,9 +49,9 @@
         #
         def f():
             x = X()
-            exctx.topframeref = virtual_ref(x)
+            exctx.topframeref = vref = virtual_ref(x)
             exctx.topframeref = vref_None
-            virtual_ref_finish(x)
+            virtual_ref_finish(vref, x)
             return 1
         #
         self.interp_operations(f, [])
@@ -60,8 +84,9 @@
             exctx._frame = x
             exctx.topframeref = virtual_ref(x)
         def leave():
+            vref = exctx.topframeref
             exctx.topframeref = vref_None
-            virtual_ref_finish(exctx._frame)
+            virtual_ref_finish(vref, exctx._frame)
         def f(n):
             enter(n)
             n = external(n)
@@ -125,7 +150,8 @@
         #
         @dont_look_inside
         def g(vref):
-            debug_print(lltype.Void, '-+-+-+-+- external read:', vref().n)
+            # we cannot do anything with the vref after the call to finish()
+            pass
         #
         def f(n):
             while n > 0:
@@ -136,7 +162,7 @@
                 exctx.topframeref = vref = virtual_ref(x)
                 # here, 'x' should be virtual
                 exctx.topframeref = vref_None
-                virtual_ref_finish(x)
+                virtual_ref_finish(vref, x)
                 # 'x' and 'vref' can randomly escape after the call to
                 # finish().
                 g(vref)
@@ -144,7 +170,7 @@
             return 1
         #
         self.meta_interp(f, [10])
-        self.check_loops(new_with_vtable=2)   # the vref and the X
+        self.check_loops(new_with_vtable=1)   # the vref
         self.check_aborted_count(0)
 
     def test_simple_all_removed(self):
@@ -169,13 +195,13 @@
                 xy.next1 = lltype.malloc(A, 0)
                 xy.next2 = lltype.malloc(A, 0)
                 xy.next3 = lltype.malloc(A, 0)
-                exctx.topframeref = virtual_ref(xy)
+                exctx.topframeref = vref = virtual_ref(xy)
                 n -= externalfn(n)
                 exctx.topframeref = vref_None
                 xy.next1 = lltype.nullptr(A)
                 xy.next2 = lltype.nullptr(A)
                 xy.next3 = lltype.nullptr(A)
-                virtual_ref_finish(xy)
+                virtual_ref_finish(vref, xy)
         #
         self.meta_interp(f, [15])
         self.check_loops(new_with_vtable=0,     # all virtualized
@@ -206,17 +232,17 @@
                 xy.next1 = lltype.malloc(A, 0)
                 xy.next2 = lltype.malloc(A, 0)
                 xy.next3 = lltype.malloc(A, 0)
-                exctx.topframeref = virtual_ref(xy)
+                exctx.topframeref = vref = virtual_ref(xy)
                 n -= externalfn(n)
                 exctx.topframeref = vref_None
                 xy.next1 = lltype.nullptr(A)
                 xy.next2 = lltype.nullptr(A)
                 xy.next3 = lltype.nullptr(A)
-                virtual_ref_finish(xy)
+                virtual_ref_finish(vref, xy)
         #
         self.meta_interp(f, [15])
-        self.check_loops(new_with_vtable=2,     # the vref, and xy so far,
-                         new_array=0)           # but not xy.next1/2/3
+        self.check_loops(new_with_vtable=1,     # the vref: xy doesn't need to be forced
+                         new_array=0)           # and neither xy.next1/2/3
         self.check_aborted_count(0)
 
     def test_simple_force_always(self):
@@ -244,12 +270,12 @@
                 xy.next2 = lltype.malloc(A, 0)
                 xy.next3 = lltype.malloc(A, 0)
                 xy.n = n
-                exctx.topframeref = virtual_ref(xy)
+                exctx.topframeref = vref = virtual_ref(xy)
                 n -= externalfn(n)
                 xy.next1 = lltype.nullptr(A)
                 xy.next2 = lltype.nullptr(A)
                 xy.next3 = lltype.nullptr(A)
-                virtual_ref_finish(xy)
+                virtual_ref_finish(vref, xy)
                 exctx.topframeref = vref_None
         #
         self.meta_interp(f, [15])
@@ -282,19 +308,19 @@
                 xy.next2 = lltype.malloc(A, 0)
                 xy.next3 = lltype.malloc(A, 0)
                 xy.n = n
-                exctx.topframeref = virtual_ref(xy)
+                exctx.topframeref = vref = virtual_ref(xy)
                 n -= externalfn(n)
                 xy.next1 = lltype.nullptr(A)
                 xy.next2 = lltype.nullptr(A)
                 xy.next3 = lltype.nullptr(A)
-                virtual_ref_finish(xy)
+                virtual_ref_finish(vref, xy)
                 exctx.topframeref = vref_None
             return exctx.m
         #
         res = self.meta_interp(f, [30])
         assert res == 13
-        self.check_loops(new_with_vtable=2,   # the vref, XY() at the end
-                         new_array=0)         # but not next1/2/3
+        self.check_loops(new_with_vtable=1,   # the vref, but not XY()
+                         new_array=0)         # and neither next1/2/3
         self.check_loop_count(1)
         self.check_aborted_count(0)
 
@@ -322,7 +348,7 @@
                 xy.next2 = lltype.malloc(A, 0)
                 xy.next3 = lltype.malloc(A, 0)
                 xy.n = n
-                exctx.topframeref = virtual_ref(xy)
+                exctx.topframeref = vref = virtual_ref(xy)
                 if n == 13:
                     externalfn(n)
                 n -= 1
@@ -330,7 +356,7 @@
                 xy.next1 = lltype.nullptr(A)
                 xy.next2 = lltype.nullptr(A)
                 xy.next3 = lltype.nullptr(A)
-                virtual_ref_finish(xy)
+                virtual_ref_finish(vref, xy)
             return exctx.m
         #
         res = self.meta_interp(f, [30])
@@ -366,7 +392,7 @@
                 xy.next4 = lltype.malloc(A, 0)
                 xy.next5 = lltype.malloc(A, 0)
                 xy.n = n
-                exctx.topframeref = virtual_ref(xy)
+                exctx.topframeref = vref = virtual_ref(xy)
                 if n % 6 == 0:
                     xy.next1 = lltype.nullptr(A)
                     xy.next2 = lltype.nullptr(A)
@@ -379,7 +405,7 @@
                 xy.next3 = lltype.nullptr(A)
                 xy.next4 = lltype.nullptr(A)
                 xy.next5 = lltype.nullptr(A)
-                virtual_ref_finish(xy)
+                virtual_ref_finish(vref, xy)
             return exctx.m
         #
         res = self.meta_interp(f, [72])
@@ -389,36 +415,6 @@
                          new_array=2)        # bridge: next4, next5
         self.check_aborted_count(0)
 
-    def test_access_vref_later(self):
-        myjitdriver = JitDriver(greens = [], reds = ['n'])
-        #
-        class XY:
-            pass
-        class ExCtx:
-            pass
-        exctx = ExCtx()
-        #
-        @dont_look_inside
-        def g():
-            return exctx.later().n
-        #
-        def f(n):
-            while n > 0:
-                myjitdriver.can_enter_jit(n=n)
-                myjitdriver.jit_merge_point(n=n)
-                xy = XY()
-                xy.n = n
-                exctx.topframeref = virtual_ref(xy)
-                exctx.later = exctx.topframeref
-                n -= 1
-                exctx.topframeref = vref_None
-                virtual_ref_finish(xy)
-            return g()
-        #
-        res = self.meta_interp(f, [15])
-        assert res == 1
-        self.check_aborted_count(0)
-
     def test_jit_force_virtual_seen(self):
         myjitdriver = JitDriver(greens = [], reds = ['n'])
         #
@@ -435,12 +431,12 @@
                 myjitdriver.jit_merge_point(n=n)
                 xy = XY()
                 xy.n = n
-                exctx.topframeref = virtual_ref(xy)
+                exctx.topframeref = vref = virtual_ref(xy)
                 xy.next1 = lltype.malloc(A, 0)
                 n = exctx.topframeref().n - 1
                 xy.next1 = lltype.nullptr(A)
                 exctx.topframeref = vref_None
-                virtual_ref_finish(xy)
+                virtual_ref_finish(vref, xy)
             return 1
         #
         res = self.meta_interp(f, [15])
@@ -465,12 +461,12 @@
                 if reclevel == 0:
                     return n
                 xy = XY()
-                exctx.topframeref = virtual_ref(xy)
+                exctx.topframeref = vref = virtual_ref(xy)
                 m = f(xy, n, reclevel-1)
                 assert m == n
                 n -= 1
                 exctx.topframeref = vref_None
-                virtual_ref_finish(xy)
+                virtual_ref_finish(vref, xy)
             return 2
         def main(n, reclevel):
             return f(XY(), n, reclevel)
@@ -495,7 +491,7 @@
                 frame.n += 1
                 xy = XY()
                 xy.n = n
-                exctx.topframeref = virtual_ref(xy)
+                exctx.topframeref = vref = virtual_ref(xy)
                 if reclevel > 0:
                     m = f(xy, frame.n, reclevel-1)
                     assert xy.n == m
@@ -503,7 +499,7 @@
                 else:
                     n -= 2
                 exctx.topframeref = vref_None
-                virtual_ref_finish(xy)
+                virtual_ref_finish(vref, xy)
             return frame.n
         def main(n, reclevel):
             return f(XY(), n, reclevel)
@@ -512,6 +508,93 @@
         assert res == main(10, 2)
         self.check_aborted_count(0)
 
+    def test_alloc_virtualref_and_then_alloc_structure(self):
+        myjitdriver = JitDriver(greens = [], reds = ['n'])
+        #
+        class XY:
+            pass
+        class ExCtx:
+            pass
+        exctx = ExCtx()
+        @dont_look_inside
+        def escapexy(xy):
+            print 'escapexy:', xy.n
+            if xy.n % 5 == 0:
+                vr = exctx.vr
+                print 'accessing via vr:', vr()
+                assert vr() is xy
+        #
+        def f(n):
+            while n > 0:
+                myjitdriver.jit_merge_point(n=n)
+                xy = XY()
+                xy.n = n
+                vr = virtual_ref(xy)
+                # force the virtualref to be allocated
+                exctx.vr = vr
+                # force xy to be allocated
+                escapexy(xy)
+                # clean up
+                exctx.vr = vref_None
+                virtual_ref_finish(vr, xy)
+                n -= 1
+            return 1
+        #
+        res = self.meta_interp(f, [15])
+        assert res == 1
+        self.check_loops(new_with_vtable=2)     # vref, xy
+
+    def test_cannot_use_invalid_virtualref(self):
+        myjitdriver = JitDriver(greens = [], reds = ['n'])
+        #
+        class XY:
+            n = 0
+        #
+        def fn(n):
+            res = False
+            while n > 0:
+                myjitdriver.can_enter_jit(n=n)
+                myjitdriver.jit_merge_point(n=n)
+                xy = XY()
+                xy.n = n
+                vref = virtual_ref(xy)
+                virtual_ref_finish(vref, xy)
+                vref() # raises InvalidVirtualRef when jitted
+                n -= 1
+            return res
+        #
+        py.test.raises(InvalidVirtualRef, "fn(10)")
+        py.test.raises(LLException, "self.meta_interp(fn, [10])")
+
+    def test_call_virtualref_already_forced(self):
+        myjitdriver = JitDriver(greens = [], reds = ['n', 'res'])
+        #
+        class XY:
+            n = 0
+        #
+        @dont_look_inside
+        def force_it(vref, n):
+            if n % 6 == 0:
+                return vref().n
+            return 0
+        def fn(n):
+            res = 0
+            while n > 0:
+                myjitdriver.can_enter_jit(n=n, res=res)
+                myjitdriver.jit_merge_point(n=n, res=res)
+                xy = XY()
+                xy.n = n
+                vref = virtual_ref(xy)
+                force_it(vref, n)
+                virtual_ref_finish(vref, xy)
+                res += force_it(vref, n) # doesn't raise, because it was already forced
+                n -= 1
+            return res
+        #
+        assert fn(10) == 6
+        res = self.meta_interp(fn, [10])
+        assert res == 6
+
 
 class TestLLtype(VRefTests, LLJitMixin):
     pass
diff --git a/pypy/jit/metainterp/test/test_ztranslation.py b/pypy/jit/metainterp/test/test_ztranslation.py
--- a/pypy/jit/metainterp/test/test_ztranslation.py
+++ b/pypy/jit/metainterp/test/test_ztranslation.py
@@ -2,7 +2,7 @@
 from pypy.jit.metainterp.warmspot import rpython_ll_meta_interp, ll_meta_interp
 from pypy.jit.backend.llgraph import runner
 from pypy.rlib.jit import JitDriver, unroll_parameters
-from pypy.rlib.jit import PARAMETERS, dont_look_inside
+from pypy.rlib.jit import PARAMETERS, dont_look_inside, hint
 from pypy.jit.metainterp.jitprof import Profiler
 from pypy.rpython.lltypesystem import lltype, llmemory
 
@@ -24,16 +24,21 @@
         # - string concatenation, slicing and comparison
 
         class Frame(object):
-            _virtualizable2_ = ['i']
+            _virtualizable2_ = ['l[*]']
 
             def __init__(self, i):
-                self.i = i
+                self = hint(self, fresh_virtualizable=True,
+                            access_directly=True)
+                self.l = [i]
 
         class OtherFrame(object):
-            _virtualizable2_ = ['i']
+            _virtualizable2_ = ['i', 'l[*]']
 
             def __init__(self, i):
+                self = hint(self, fresh_virtualizable=True,
+                            access_directly=True)
                 self.i = i
+                self.l = [float(i)]
 
         class JitCellCache:
             entry = None
@@ -57,39 +62,45 @@
             jitdriver.set_param("trace_eagerness", 2)
             total = 0
             frame = Frame(i)
-            while frame.i > 3:
+            while frame.l[0] > 3:
                 jitdriver.can_enter_jit(frame=frame, total=total)
                 jitdriver.jit_merge_point(frame=frame, total=total)
-                total += frame.i
-                if frame.i >= 20:
-                    frame.i -= 2
-                frame.i -= 1
+                total += frame.l[0]
+                if frame.l[0] >= 20:
+                    frame.l[0] -= 2
+                frame.l[0] -= 1
             return total * 10
         #
-        myjitdriver2 = JitDriver(greens = ['g'], reds = ['m', 's', 'f'],
+        myjitdriver2 = JitDriver(greens = ['g'],
+                                 reds = ['m', 's', 'f', 'float_s'],
                                  virtualizables = ['f'])
         def f2(g, m, x):
             s = ""
             f = OtherFrame(x)
+            float_s = 0.0
             while m > 0:
-                myjitdriver2.can_enter_jit(g=g, m=m, f=f, s=s)
-                myjitdriver2.jit_merge_point(g=g, m=m, f=f, s=s)
+                myjitdriver2.can_enter_jit(g=g, m=m, f=f, s=s, float_s=float_s)
+                myjitdriver2.jit_merge_point(g=g, m=m, f=f, s=s,
+                                             float_s=float_s)
                 s += 'xy'
                 if s[:2] == 'yz':
                     return -666
                 m -= 1
                 f.i += 3
+                float_s += f.l[0]
             return f.i
         #
         def main(i, j):
             return f(i) - f2(i+j, i, j)
         res = ll_meta_interp(main, [40, 5], CPUClass=self.CPUClass,
-                             type_system=self.type_system)
+                             type_system=self.type_system,
+                             listops=True)
         assert res == main(40, 5)
         res = rpython_ll_meta_interp(main, [40, 5],
                                      CPUClass=self.CPUClass,
                                      type_system=self.type_system,
-                                     ProfilerClass=Profiler)
+                                     ProfilerClass=Profiler,
+                                     listops=True)
         assert res == main(40, 5)
 
     def test_external_exception_handling_translates(self):
diff --git a/pypy/jit/metainterp/typesystem.py b/pypy/jit/metainterp/typesystem.py
--- a/pypy/jit/metainterp/typesystem.py
+++ b/pypy/jit/metainterp/typesystem.py
@@ -5,7 +5,7 @@
 from pypy.rpython.annlowlevel import cast_instance_to_base_obj
 from pypy.jit.metainterp import history
 from pypy.jit.codewriter import heaptracker
-from pypy.rlib.objectmodel import r_dict
+from pypy.rlib.objectmodel import r_dict, specialize
 
 def deref(T):
     if isinstance(T, lltype.Ptr):
@@ -97,12 +97,15 @@
     def cast_to_baseclass(self, value):
         return lltype.cast_opaque_ptr(lltype.Ptr(rclass.OBJECT), value)
 
+    @specialize.ll()
     def getlength(self, array):
         return len(array)
 
+    @specialize.ll()
     def getarrayitem(self, array, i):
         return array[i]
 
+    @specialize.ll()
     def setarrayitem(self, array, i, newvalue):
         array[i] = newvalue
 
@@ -201,12 +204,15 @@
     def cast_to_baseclass(self, value):
         return ootype.cast_from_object(ootype.ROOT, value)
 
+    @specialize.ll()
     def getlength(self, array):
         return array.ll_length()
 
+    @specialize.ll()
     def getarrayitem(self, array, i):
         return array.ll_getitem_fast(i)
 
+    @specialize.ll()
     def setarrayitem(self, array, i, newvalue):
         array.ll_setitem_fast(i, newvalue)
 
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
@@ -2,7 +2,7 @@
 from pypy.rpython.lltypesystem import lltype, llmemory, rffi, rclass
 from pypy.jit.metainterp import history
 from pypy.jit.codewriter import heaptracker
-
+from pypy.rlib.jit import InvalidVirtualRef
 
 class VirtualRefInfo:
 
@@ -38,23 +38,24 @@
 
     def replace_force_virtual_with_call(self, graphs):
         # similar to rvirtualizable2.replace_force_virtualizable_with_call().
-        c_funcptr = None
-        count = 0
+        c_force_virtual_ptr = None
+        force_virtual_count = 0
         for graph in graphs:
             for block in graph.iterblocks():
                 for op in block.operations:
                     if op.opname == 'jit_force_virtual':
                         # first compute c_funcptr, but only if there is any
                         # 'jit_force_virtual' around
-                        if c_funcptr is None:
-                            c_funcptr = self.get_force_virtual_fnptr()
+                        if c_force_virtual_ptr is None:
+                            c_force_virtual_ptr = self.get_force_virtual_fnptr()
                         #
                         op.opname = 'direct_call'
-                        op.args = [c_funcptr, op.args[0]]
-                        count += 1
-        if c_funcptr is not None:
-            log("replaced %d 'jit_force_virtual' with %r" % (count,
-                                                             c_funcptr.value))
+                        op.args = [c_force_virtual_ptr, op.args[0]]
+                        force_virtual_count += 1
+        #
+        if c_force_virtual_ptr is not None:
+            log("replaced %d 'jit_force_virtual' with %r" % (force_virtual_count,
+                                                             c_force_virtual_ptr.value))
 
     # ____________________________________________________________
 
@@ -145,7 +146,8 @@
                 ResumeGuardForcedDescr.force_now(self.cpu, token)
                 assert vref.virtual_token == self.TOKEN_NONE
                 assert vref.forced
-        else:
-            assert vref.forced
+        elif not vref.forced:
+            # token == TOKEN_NONE and the vref was not forced: it's invalid
+            raise InvalidVirtualRef
         return vref.forced
     force_virtual._dont_inline_ = True
diff --git a/pypy/jit/metainterp/warmstate.py b/pypy/jit/metainterp/warmstate.py
--- a/pypy/jit/metainterp/warmstate.py
+++ b/pypy/jit/metainterp/warmstate.py
@@ -566,6 +566,19 @@
             return can_inline_greenargs(*greenargs)
         self.can_inline_greenargs = can_inline_greenargs
         self.can_inline_callable = can_inline_callable
+        if hasattr(jd.jitdriver, 'on_compile'):
+            def on_compile(logger, token, operations, type, greenkey):
+                greenargs = unwrap_greenkey(greenkey)
+                return jd.jitdriver.on_compile(logger, token, operations, type,
+                                               *greenargs)
+            def on_compile_bridge(logger, orig_token, operations, n):
+                return jd.jitdriver.on_compile_bridge(logger, orig_token,
+                                                      operations, n)
+            jd.on_compile = on_compile
+            jd.on_compile_bridge = on_compile_bridge
+        else:
+            jd.on_compile = lambda *args: None
+            jd.on_compile_bridge = lambda *args: None
 
         def get_assembler_token(greenkey, redboxes):
             # 'redboxes' is only used to know the types of red arguments
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
@@ -42,6 +42,7 @@
 config.objspace.usemodules._lsprof = True
 #
 config.objspace.usemodules._ffi = True
+config.objspace.usemodules.micronumpy = True
 #
 set_pypy_opt_level(config, level='jit')
 
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,11 +1,10 @@
 
 try:
-    def f(x):
-        i = 0
-        while i < x:
-            range(i)
-            i += 1
-    f(10000)
+    import numpy
+    a = numpy.array(range(10))
+    b = a + a + a
+    print b[3]
+
 except Exception, e:
     print "Exception: ", type(e)
     print e
diff --git a/pypy/jit/tl/tinyframe/test/test_tinyframe.py b/pypy/jit/tl/tinyframe/test/test_tinyframe.py
--- a/pypy/jit/tl/tinyframe/test/test_tinyframe.py
+++ b/pypy/jit/tl/tinyframe/test/test_tinyframe.py
@@ -96,11 +96,12 @@
         RETURN r1
         ''')
         s = StringIO()
+        prev = sys.stdout
         sys.stdout = s
         try:
             interpret(code)
         finally:
-            sys.stdout = sys.__stdout__
+            sys.stdout = prev
         lines = s.getvalue().splitlines()
         assert lines == [
             '0',
diff --git a/pypy/jit/tl/tl.py b/pypy/jit/tl/tl.py
--- a/pypy/jit/tl/tl.py
+++ b/pypy/jit/tl/tl.py
@@ -40,6 +40,7 @@
         assert n >= 0
         self.stack[n] = elem
 
+    @dont_look_inside
     def roll(self, r):
         if r < -1:
             i = self.stackpos + r
diff --git a/pypy/jit/tool/cpython.vmrss b/pypy/jit/tool/cpython.vmrss
deleted file mode 100644
--- a/pypy/jit/tool/cpython.vmrss
+++ /dev/null
@@ -1,4101 +0,0 @@
-124
-16600
-20620
-20640
-22036
-94084
-94084
-94108
-94108
-94108
-94108
-94108
-94120
-94164
-94160
-94160
-94160
-94160
-94160
-94216
-110644
-123144
-135236
-143680
-148500
-153104
-157088
-160640
-164760
-167992
-163108
-163232
-163232
-163436
-163436
-163436
-163444
-163444
-163444
-163448
-163448
-163448
-163448
-163448
-163448
-167060
-170948
-174432
-177212
-177216
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176508
-176520
-176520
-176520
-176520
-176520
-176520
-176520
-176520
-176520
-176540
-176544
-176544
-176544
-176544
-176544
-176544
-176544
-176544
-176544
-176544
-176544
-176544
-179120
-187120
-189380
-191052
-192156
-193320
-194900
-195860
-198516
-201484
-202600
-202600
-202600
-202600
-202832
-202832
-202836
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-202840
-207784
-212136
-216320
-220508
-224696
-228876
-245088
-245088
-247844
-252032
-256212
-260400
-264592
-268776
-272776
-275060
-279244
-283428
-287616
-291032
-293900
-298080
-302272
-304364
-308548
-310644
-312740
-316924
-319016
-323208
-325296
-327392
-331572
-333668
-335760
-337856
-354328
-356424
-358520
-362700
-364792
-366892
-368984
-371080
-373168
-375260
-377356
-379448
-381540
-383636
-383636
-385732
-387820
-390032
-391160
-392292
-394552
-396816
-397092
-399072
-401340
-403600
-405860
-408008
-408148
-412640
-414900
-417164
-419420
-421680
-423944
-426204
-428464
-430724
-432768
-434980
-436476
-437932
-440332
-441984
-442740
-445152
-447688
-449148
-449960
-452436
-454712
-454896
-457180
-458888
-459688
-462040
-463480
-464408
-466812
-467244
-469224
-471096
-471684
-474136
-474328
-476508
-478872
-481356
-483472
-483780
-486072
-488480
-489668
-490888
-493420
-495704
-496836
-498116
-500520
-502756
-503668
-505400
-507760
-509296
-510204
-512764
-514708
-515508
-517372
-519764
-520648
-522188
-524596
-525524
-527004
-529412
-534224
-536632
-538080
-539216
-541588
-542560
-543384
-543384
-518804
-518804
-518804
-518804
-518804
-518804
-518804
-518804
-518804
-518804
-518804
-518804
-518804
-518804
-518804
-518804
-518804
-519024
-519024
-519024
-519024
-519024
-519024
-519024
-519024
-519024
-519024
-519024
-519024
-519024
-519024
-519024
-519024
-519024
-519024
-519024
-519024
-519024
-519024
-519024
-519024
-519024
-519024
-519024
-519024
-519024
-519024
-519024
-519024
-519024
-519024
-519024
-519024
-519024
-519024
-519024
-519024
-519024
-519024
-519024
-519028
-519028
-519028
-519028
-519028
-519028
-519028
-519028
-519028
-519028
-519028
-519028
-519032
-519032
-519032
-519032
-519036
-519036
-519036
-519036
-519036
-519036
-519036
-519036
-519036
-519036
-519036
-519036
-519036
-519036
-519036
-519036
-519036
-519036
-519036
-519036
-519036
-519036
-519036
-519048
-519048
-519048
-519048
-519048
-519048
-519048
-519048
-519048
-519048
-519048
-519048
-519048
-519048
-519052
-519052
-519052
-519052
-519052
-519052
-519052
-519052
-519052
-519052
-519052
-519052
-519052
-519052
-519052
-519052
-519052
-519052
-519052
-519052
-519052
-519052
-519052
-519052
-519052
-519052
-519052
-519052
-519052
-519052
-519052
-519052
-519052
-519052
-519052
-519052
-519052
-519052
-519052
-519052
-519052
-519052
-519052
-519052
-519052
-519052
-519052
-519052
-519052
-519052
-519052
-519052
-519052
-519052
-519052
-519056
-519056
-519056
-519056
-519056
-519056
-519056
-519056
-519056
-519056
-519056
-519056
-519056
-519056
-519056
-519056
-519056
-519056
-519056
-519056
-519056
-519056
-519056
-519056
-519056
-519056
-519056
-519056
-519056
-519056
-519056
-519056
-519056
-519060
-519060
-519060
-519060
-519060
-519060
-519060
-519060
-519060
-519060
-519060
-519060
-519060
-519060
-519060
-519060
-519060
-519060
-519060
-519060
-519060
-519060
-519064
-519064
-519064
-519064
-519064
-519064
-519064
-519064
-519064
-519064
-519064
-519064
-519064
-519064
-519064
-519064
-519064
-519064
-519064
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-519068
-520592
-520592
-520904
-522740
-522740
-523212
-525256
-525256
-525316
-526552
-526552
-526560
-528508
-528508
-528508
-530040
-530040
-530040
-532684
-532684
-532684
-534948
-534948
-534948
-538028
-538028
-538028
-541404
-541448
-541448
-543784
-543784
-543784
-545184
-545476
-545768
-545832
-545832
-545832
-546016
-546016
-546128
-546184
-546184
-546184
-546184
-546184
-546184
-546184
-546184
-546184
-546184
-546184
-546184
-546184
-546184
-546184
-546184
-546184
-546184
-546228
-546228
-546228
-546228
-546228
-546228
-546228
-546228
-546228
-546228
-546228
-546228
-546228
-546228
-546228
-546708
-546708
-546708
-547988
-550420
-550420
-550420
-552896
-555796
-555796
-555796
-559136
-560280
-560280
-560996
-562504
-563772
-564672
-564672
-565268
-567936
-568884
-569028
-569236
-569292
-569292
-570236
-572960
-573980
-573980
-574508
-577404
-579188
-579188
-579508
-582836
-584468
-584468
-585544
-591292
-591292
-591292
-595868
-597588
-597588
-598404
-602772
-603964
-603964
-605488
-609740
-610468
-610468
-611884
-616440
-617108
-617108
-618156
-622276
-623784
-623784
-624128
-624376
-625544
-626736
-627112
-627112
-627116
-627656
-628836
-628836
-628836
-629160
-630180
-630488
-630488
-630492
-631288
-632144
-632144
-632144
-632172
-632688
-633220
-633220
-633220
-633284
-633756
-633916
-633916
-633916
-634012
-634608
-634608
-634608
-634624
-634732
-635144
-635144
-635144
-635196
-635680
-635868
-635868
-635944
-638440
-639964
-639980
-639980
-640056
-641052
-642064
-642064
-642064
-642248
-643080
-643832
-643832
-643832
-644116
-646500
-647424
-648236
-649032
-649156
-649156
-649256
-651556
-652056
-652504
-652860
-653168
-653440
-653876
-654096
-654304
-654304
-654304
-654756
-655648
-657064
-657064
-657064
-657064
-657488
-657756
-657756
-657756
-658112
-658736
-658736
-658736
-658796
-659304
-659376
-659376
-659376
-659848
-661000
-661172
-661172
-661236
-662240
-663240
-663508
-663508
-663660
-664324
-665512
-665764
-665764
-665764
-666448
-667692
-668112
-668112
-668112
-668624
-669508
-670388
-670536
-670536
-670536
-670564
-671288
-672268
-672268
-672268
-672676
-674504
-675072
-675072
-675072
-675156
-675896
-676700
-676700
-676700
-676820
-677988
-678628
-678628
-678628
-678776
-679744
-680400
-680400
-680400
-705092
-705156
-705156
-705156
-705156
-705156
-705156
-705160
-705160
-705160
-705160
-705160
-705160
-705160
-705160
-705160
-705160
-705160
-705160
-705160
-705160
-705160
-705160
-705160
-705160
-705160
-705160
-705160
-705160
-705160
-705160
-705160
-705160
-705160
-705160
-705160
-705160
-705160
-705160
-705160
-705160
-705160
-705160
-705160
-705264
-705264
-705264
-705400
-705476
-706168
-706292
-706292
-706292
-706504
-706568
-706980
-707012
-707012
-707012
-707196
-707280
-707904
-707904
-707904
-707924
-708112
-708176
-708676
-708676
-708676
-708696
-708892
-708984
-709588
-709588
-709588
-709612
-709804
-709848
-710300
-710300
-710300
-710676
-710520
-710604
-711156
-711156
-711156
-711336
-711352
-711576
-712080
-712080
-712080
-712300
-712408
-712500
-712648
-712648
-712648
-712648
-713060
-713300
-713716
-713716
-713716
-714072
-714196
-714568
-714568
-714568
-714596
-714956
-715112
-715808
-715808
-715808
-717504
-717628
-717660
-717660
-717660
-718620
-719048
-719424
-719424
-719424
-719480
-719924
-720612
-720612
-720612
-720620
-722584
-722848
-722848
-722848
-723060
-724108
-724604
-724604
-724604
-725108
-726168
-726348
-726348
-726348
-727216
-728204
-728204
-728204
-728324
-729396
-730152
-730152
-730152
-730396
-736796
-736800
-736800
-736800
-736800
-736800
-736800
-736800
-736800
-737136
-738296
-738400
-738400
-738400
-739092
-740128
-740128
-740128
-740140
-741092
-741980
-741980
-741980
-742060
-743060
-743796
-743796
-743796
-743836
-744440
-745348
-745348
-745348
-745400
-746108
-746848
-746952
-746952
-746952
-747496
-748608
-748744
-749084
-749084
-749084
-749172
-750172
-751468
-751592
-751592
-751592
-751688
-751928
-752152
-752308
-759152
-760152
-760152
-760152
-756356
-754816
-756356
-756356
-756356
-756688
-756688
-756820
-757152
-757200
-757400
-757432
-757432
-757432
-757632
-757956
-758404
-758844
-759480
-760064
-760552
-760552
-760552
-760560
-761180
-761632
-762288
-762800
-763700
-764504
-764716
-764716
-764716
-764940
-765388
-765936
-767748
-767056
-767300
-767484
-767868
-768316
-768316
-768316
-768316
-768700
-768828
-768700
-769340
-769260
-771008
-771552
-771652
-771716
-772580
-772708
-772740
-772740
-772740
-772292
-772740
-772944
-773188
-773700
-774084
-774084
-774404
-774020
-774532
-774020
-774596
-774340
-774468
-774468
-774468
-774724
-774792
-774980
-775368
-775816
-775816
-776264
-777480
-778292
-778408
-778440
-778440
-778440
-778440
-778440
-778440
-778440
-778440
-778440
-778440
-778440
-778632
-778696
-778952
-779016
-779016
-779016
-779016
-780812
-780812
-780812
-781068
-781580
-781772
-781712
-781868
-782092
-782420
-782796
-782796
-782796
-782796
-782668
-783128
-783436
-783820
-784076
-784332
-784908
-785164
-785500
-786188
-786188
-786188
-786188
-786188
-786188
-786188
-786412
-786896
-787084
-787404
-787532
-787724
-787568
-788108
-788428
-788748
-788752
-789520
-789520
-789520
-788880
-789440
-789452
-789516
-790092
-790284
-790604
-790860
-791052
-791372
-791628
-792012
-792012
-792396
-792780
-792780
-792780
-792780
-792780
-793228
-793228
-793868
-793868
-793996
-793996
-794636
-794636
-794636
-795084
-795084
-795468
-795532
-795980
-795980
-796300
-796364
-796364
-796364
-796364
-796748
-797132
-797132
-797516
-797644
-797644
-798380
-798604
-798860
-798924
-799372
-799564
-799756
-799756
-799756
-799756
-799816
-800292
-800792
-801312
-801816
-802364
-802880
-803456
-803660
-803660
-803660
-803812
-804388
-804960
-805516
-806084
-806668
-807324
-807980
-807980
-807980
-807980
-808416
-809084
-809784
-810492
-811160
-812900
-813476
-813876
-813876
-813876
-813876
-814508
-815152
-815864
-816556
-817260
-817916
-818708
-819272
-819352
-819352
-819352
-819352
-819884
-820308
-820888
-821012
-821012
-821204
-821588
-821588
-821588
-821972
-822228
-822164
-822932
-823252
-823252
-823252
-823252
-823252
-823256
-823612
-823920
-823936
-824140
-824168
-824220
-824280
-824400
-824664
-825776
-825776
-825776
-825776
-832168
-832168
-832168
-832168
-832808
-833492
-833492
-833492
-833492
-833700
-834308
-834428
-834428
-834428
-834780
-836216
-836216
-836216
-836836
-839308
-839308
-839308
-839308
-839416
-840344
-840344
-840344
-840344
-841724
-841724
-841724
-841724
-843800
-843800
-843800
-843800
-845692
-846072
-846072
-846072
-846096
-846736
-847096
-847156
-847156
-847156
-847160
-847180
-847360
-847360
-847360
-847360
-847416
-849248
-849248
-849248
-849248
-849716
-849716
-849716
-849716
-849740
-851168
-851168
-851168
-851168
-854544
-854544
-854544
-854544
-854564
-855332
-855332
-855332
-855332
-857092
-857092
-857092
-857092
-858000
-859388
-859388
-859388
-859388
-861584
-861584
-861584
-861584
-861584
-863464
-863464
-863464
-863464
-864304
-866500
-866500
-866500
-866500
-868952
-868952
-868952
-868952
-869740
-872108
-872108
-872108
-872108
-873208
-875564
-875564
-875564
-875564
-878568
-878568
-878568
-878568
-878576
-880780
-880780
-880780
-880780
-884048
-884048
-884048
-884048
-884048
-884048
-886516
-886516
-886516
-886516
-886516
-886536
-888112
-888112
-888112
-888112
-888112
-888112
-888656
-888984
-888984
-888984
-888984
-888984
-888984
-889076
-890288
-890288
-890288
-890288
-890288
-890288
-890404
-892900
-892900
-892900
-892900
-892900
-892900
-892900
-892900
-895760
-895760
-895760
-895760
-895760
-895760
-895920
-897624
-897624
-897624
-897624
-897624
-897624
-897624
-897624
-897628
-898024
-898024
-898024
-898024
-898024
-898060
-900024
-900024
-900024
-900024
-900024
-900024
-900240
-901436
-901436
-901436
-901436
-901436
-901556
-903116
-903116
-903116
-903116
-903116
-903128
-905084
-905084
-905084
-905084
-905084
-905084
-905096
-906832
-906832
-906832
-906832
-906832
-906832
-908916
-908916
-908916
-908916
-908916
-908916
-908916
-910720
-910720
-910720
-910720
-910720
-910720
-911780
-912072
-912072
-912072
-912072
-914472
-914472
-914472
-914472
-914472
-917120
-917120
-917120
-917120
-917120
-919056
-919056
-919056
-919056
-919056
-920316
-920316
-920316
-920316
-920316
-920892
-920892
-920892
-920892
-920892
-922996
-922996
-922996
-922996
-922996
-925564
-925564
-925564
-925564
-925564
-927780
-927780
-927780
-927780
-928016
-928936
-929048
-930864
-930864
-930864
-930864
-932980
-933304
-933304
-933304
-933304
-933540
-934292
-935452
-935528
-935528
-935528
-935528
-935528
-935528
-935528
-935528
-935600
-936112
-936112
-936208
-936208
-936208
-936208
-936308
-936308
-936316
-936368
-936368
-936368
-936368
-936368
-936368
-936368
-936368
-936368
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-936376
-937404
-937404
-937404
-937404
-939968
-939968
-939968
-939968
-939968
-939968
-939968
-939968
-939968
-939968
-939968
-939968
-939968
-940516
-940516
-940516
-940516
-947168
-947168
-947168
-947168
-951948
-951948
-951948
-951948
-953488
-956916
-956916
-956916
-956916
-952296
-955376
-953420
-953260
-953900
-953516
-953900
-955052
-953516
-953516
-954284
-953324
-953516
-956208
-956208
-956208
-956208
-954668
-948988
-948988
-948988
-948988
-948988
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-945908
-947704
-948068
-948068
-948068
-948068
-948068
-948552
-949024
-949024
-949024
-949024
-949024
-949944
-950492
-950616
-950616
-950616
-950616
-951416
-952000
-952564
-952564
-952564
-952564
-952620
-953296
-953952
-954332
-954332
-954332
-954332
-954532
-955532
-956216
-956216
-956216
-956216
-956216
-956584
-957396
-957704
-957704
-957704
-957704
-957740
-958620
-959444
-959444
-959444
-959444
-959444
-960224
-963784
-963868
-963868
-963868
-963868
-963872
-964684
-972452
-972452
-972452
-972452
-972452
-972452
-973220
-974548
-974548
-974548
-974548
-974548
-975540
-977704
-978792
-978792
-978792
-978792
-978792
-981296
-982700
-983180
-983180
-983180
-983180
-983368
-985060
-987512
-987688
-987688
-987688
-987688
-988180
-990724
-993084
-993124
-993124
-993124
-993124
-993604
-995444
-996640
-996640
-996640
-996640
-996640
-997892
-999160
-1001452
-1001452
-1001452
-1001452
-1001452
-1002264
-1004120
-1004916
-1004916
-1004916
-1004916
-1004916
-1006648
-1010244
-1010548
-1010548
-1010548
-1010548
-1010572
-1011860
-1013748
-1017264
-1017264
-1017264
-1017264
-1017264
-1019096
-1021044
-1021044
-1021044
-1021044
-1021044
-1021536
-1023636
-1024964
-1024964
-1024964
-1024964
-1024964
-1025592
-1027672
-1029384
-1029384
-1029384
-1029384
-1029384
-1030056
-1032244
-1033756
-1033756
-1033756
-1033756
-1033756
-1034384
-1035856
-1036588
-1038428
-1038428
-1038428
-1038428
-1038428
-1039288
-1041088
-1042508
-1042508
-1042508
-1042508
-1042508
-1043544
-1045280
-1046580
-1046580
-1046580
-1046580
-1046580
-1047040
-1048560
-1049872
-1050576
-1050576
-1050576
-1050576
-1050576
-1052016
-1056044
-1057360
-1057360
-1057360
-1057360
-1057360
-1058336
-1059900
-1061244
-1061704
-1061704
-1061704
-1061704
-1061704
-1063148
-1063972
-1065404
-1067064
-1067536
-1067536
-1067536
-1067536
-1067536
-1069284
-1070524
-1072340
-1072836
-1072836
-1072836
-1072836
-1072836
-1073584
-1074592
-1076404
-1076832
-1076832
-1076832
-1076832
-1076832
-1078124
-1079640
-1080220
-1080644
-1080736
-1080736
-1080736
-1080736
-1080924
-1082868
-1083368
-1084412
-1084412
-1084412
-1084412
-1084412
-1085216
-1087068
-1087960
-1087960
-1087960
-1087960
-1087960
-1089788
-1093132
-1095064
-1095064
-1095064
-1095064
-1095064
-1095140
-1097092
-1098948
-1098948
-1098948
-1098948
-1098948
-1098980
-1100812
-1102032
-1102032
-1102032
-1102032
-1102032
-1105464
-1116944
-1119248
-1120364
-1120364
-1120364
-1120364
-1120364
-1121568
-1122908
-1123680
-1124604
-1125076
-1125076
-1125076
-1125076
-1125076
-1126292
-1128160
-1129952
-1129952
-1129952
-1129952
-1129952
-1130496
-1131884
-1133032
-1134204
-1135460
-1135636
-1135636
-1135636
-1135636
-1135636
-1136764
-1138048
-1139412
-1140764
-1141164
-1141188
-1142440
-1142440
-1142440
-1142440
-1142440
-1142440
-1143980
-1145876
-1146576
-1146576
-1146576
-1146576
-1146576
-1146576
-1147680
-1148328
-1148960
-1148960
-1148960
-1148960
-1148960
-1149004
-1150700
-1152228
-1153364
-1153364
-1153520
-1153784
-1154588
-1154680
-1154712
-1154728
-1154784
-1154992
-1155356
-1155620
-1155856
-1156044
-1156420
-1157392
-1158760
-1158980
-1158988
-1159000
-1162724
-1162740
-1162788
-1163112
-1163188
-1163188
-1163188
-1163188
-1163188
-1163384
-1165668
-1166648
-1166652
-1166664
-1166676
-1166688
-1166692
-1166696
-1166700
-1166700
-1172848
-1172852
-1174888
-1176824
-1176836
-1176852
-1176860
-1176876
-1176880
-1176888
-1176892
-1176900
-1176912
-1176944
-1177248
-1177712
-1178172
-1178536
-1178656
-1178780
-1178920
-1179044
-1179188
-1179384
-1180296
-1180300
-1180300
-1180300
-1180300
-1180300
-1180300
-1180372
-1180380
-1180468
-1180524
-1180524
-1180524
-1180524
-1180524
-1180576
-1180580
-1180644
-1180684
-1180684
-1180684
-1180684
-1180684
-1180684
-1180724
-1180756
-1180852
-1180904
-1180904
-1180904
-1180904
-1180904
-1180904
-1181096
-1181400
-1181744
-1181744
-1181744
-1181744
-1181744
-1181744
-1181936
-1181936
-1181936
-1181936
-1181936
-1181936
-1181936
-1181936
-1181936
-1181972
-1182004
-1182004
-1182004
-1182004
-1182004
-1182004
-1182004
-1182004
-1182004
-1182128
-1182156
-1182156
-1182156
-1182156
-1182156
-1182156
-1182156
-1182156
-1182180
-1182180
-1182180
-1182180
-1182180
-1182180
-1182180
-1182368
-1182516
-1182516
-1182516
-1182516
-1182516
-1182516
-1182516
-1182516
-1182516
-1182516
-1182516
-1182516
-1182516
-1182516
-1182516
-1182516
-1182516
-1183576
-1183576
-1183576
-1183576
-1183576
-1183576
-1183576
-1183576
-1183576
-1183576
-1183576
-1183576
-1183576
-1183576
-1183576
-1183576
-1183576
-1183576
-1183576
-1183576
-1183576
-1183576
-1183576
-1183576
-1183576
-1183576
-1183576
-1183576
-1183576
-1183576
-1183576
-1183576
-1183596
-1183772
-1183772
-1183772
-1183772
-1183772
-1183772
-1183772
-1183772
-1183772
-1183776
-1183776
-1183776
-1183776
-1183776
-1183776
-1183776
-1183776
-1183776
-1183952
-1184000
-1184000
-1184000
-1184000
-1184000
-1184000
-1184000
-1184200
-1184832
-1184832
-1184832
-1184832
-1184832
-1184832
-1184928
-1184928
-1184940
-1184940
-1184940
-1184940
-1184940
-1184940
-1184940
-1184940
-1185144
-1185144
-1185144
-1185144
-1185144
-1185144
-1185144
-1185144
-1185144
-1185144
-1185144
-1185144
-1185144
-1185144
-1185196
-1185196
-1185196
-1185196
-1185196
-1185196
-1185196
-1185196
-1185196
-1185268
-1185268
-1185268
-1185268
-1185268
-1185268
-1185268
-1185268
-1186444
-1186776
-1186776
-1186776
-1186776
-1186776
-1187664
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188072
-1188168
-1188168
-1188168
-1188168
-1188168
-1188168
-1188168
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189240
-1189292
-1189292
-1189292
-1189292
-1189292
-1189292
-1189292
-1189532
-1189532
-1189532
-1189532
-1189532
-1189532
-1189532
-1189532
-1189532
-1189532
-1189532
-1189532
-1189532
-1189532
-1189532
-1189532
-1189704
-1189708
-1189708
-1189708
-1189708
-1189708
-1190160
-1190160
-1190160
-1190160
-1190160
-1190160
-1190160
-1190160
-1190160
-1191100
-1191100
-1191100
-1191100
-1191100
-1191316
-1191316
-1191316
-1191316
-1191316
-1191316
-1191316
-1191316
-1191316
-1191316
-1191316
-1191316
-1191316
-1191316
-1191316
-1191316
-1191316
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191748
-1191772
-1191772
-1191772
-1191772
-1191772
-1191772
-1191772
-1191772
-1192964
-1192964
-1192964
-1192964
-1192964
-1192964
-1192964
-1193060
-1193060
-1193060
-1193060
-1193060
-1193060
-1193060
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193072
-1193076
-1193076
-1193076
-1193076
-1193076
-1193076
-1193124
-1193124
-1193360
-1194108
-1194108
-1194108
-1194108
-1194108
-1193380
-1193460
-1193460
-1193460
-1193460
-1193460
-1193460
-1193460
-1193460
-1193792
-1193792
-1193792
-1193792
-1193792
-1193792
-1194000
-1194000
-1194000
-1194000
-1194000
-1194000
-1194000
-1194000
-1194000
-1194000
-1194000
-1194000
-1194000
-1194000
-1194000
-1194000
-1194000
-1194048
-1194048
-1194048
-1194048
-1194048
-1194048
-1194048
-1194048
-1194048
-1194048
-1194048
-1194048
-1194048
-1194048
-1194048
-1194048
-1194328
-1194328
-1194328
-1194328
-1194328
-1194328
-1194328
-1194328
-1194328
-1194328
-1194360
-1194360
-1194360
-1194360
-1194360
-1194360
-1194360
-1194508
-1194508
-1194508
-1194508
-1194508
-1194508
-1194512
-1194668
-1194668
-1194668
-1194668
-1194668
-1194668
-1194668
-1194668
-1194668
-1194668
-1194668
-1194668
-1194668
-1194668
-1194668
-1194668
-1194912
-1194912
-1194912
-1194912
-1194912
-1194912
-1194912
-1194912
-1194912
-1194912
-1194912
-1194912
-1194912
-1194912
-1194912
-1194912
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196596
-1196660
-1196764
-1196764
-1196764
-1196764
-1196764
-1196764
-1196764
-1196764
-1196764
-1196764
-1196764
-1196764
-1196764
-1196764
-1196764
-1196948
-1196948
-1196948
-1196948
-1196948
-1196948
-1196948
-1196948
-1196948
-1196948
-1196948
-1196948
-1196948
-1196948
-1196948
-1196948
-1196948
-1196948
-1196948
-1196948
-1196948
-1196948
-1196948
-1197236
-1197236
-1197236
-1197236
-1197236
-1197236
-1197236
-1197236
-1197236
-1197288
-1197288
-1197288
-1197288
-1197288
-1197288
-1197288
-1197288
-1197288
-1197288
-1197288
-1197288
-1197288
-1197288
-1197288
-1197288
-1197288
-1197288
-1197288
-1197288
-1197288
-1197288
-1197376
-1197384
-1197596
-1197596
-1197596
-1197596
-1197596
-1197596
-1197596
-1197596
-1197588
-1197588
-1197588
-1197588
-1197588
-1197588
-1197588
-1197588
-1197564
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197460
-1197492
-1197508
-1197516
-1197516
-1197516
-1197516
-1197516
-1197516
diff --git a/pypy/module/__builtin__/app_inspect.py b/pypy/module/__builtin__/app_inspect.py
--- a/pypy/module/__builtin__/app_inspect.py
+++ b/pypy/module/__builtin__/app_inspect.py
@@ -5,6 +5,8 @@
 
 import sys
 
+from __pypy__ import lookup_special
+
 def _caller_locals(): 
     # note: the reason why this is working is because the functions in here are
     # compiled by geninterp, so they don't have a frame
@@ -62,7 +64,22 @@
 
     obj = args[0]
 
-    if isinstance(obj, types.ModuleType):
+    dir_meth = None
+    if isinstance(obj, types.InstanceType):
+        try:
+            dir_meth = getattr(obj, "__dir__")
+        except AttributeError:
+            pass
+    else:
+        dir_meth = lookup_special(obj, "__dir__")
+    if dir_meth is not None:
+        result = dir_meth()
+        if not isinstance(result, list):
+            raise TypeError("__dir__() must return a list, not %r" % (
+                type(result),))
+        result.sort()
+        return result
+    elif isinstance(obj, types.ModuleType):
         try:
             result = list(obj.__dict__)
             result.sort()
@@ -76,14 +93,6 @@
         result.sort()
         return result
 
-    elif hasattr(type(obj), '__dir__'):
-        result = type(obj).__dir__(obj)
-        if not isinstance(result, list):
-            raise TypeError("__dir__() must return a list, not %r" % (
-                type(result),))
-        result.sort()
-        return result
-
     else: #(regular item)
         Dict = {}
         try:
diff --git a/pypy/module/__builtin__/test/test_builtin.py b/pypy/module/__builtin__/test/test_builtin.py
--- a/pypy/module/__builtin__/test/test_builtin.py
+++ b/pypy/module/__builtin__/test/test_builtin.py
@@ -120,15 +120,32 @@
     def test_dir_custom(self):
         class Foo(object):
             def __dir__(self):
-                return [1, 3, 2]
+                return ["1", "2", "3"]
         f = Foo()
-        assert dir(f) == [1, 2, 3]
-        #
+        assert dir(f) == ["1", "2", "3"]
+        class Foo:
+            def __dir__(self):
+                return ["apple"]
+        assert dir(Foo()) == ["apple"]
         class Foo(object):
             def __dir__(self):
                 return 42
         f = Foo()
         raises(TypeError, dir, f)
+        import types
+        class Foo(types.ModuleType):
+            def __dir__(self):
+                return ["blah"]
+        assert dir(Foo("a_mod")) == ["blah"]
+
+    def test_dir_custom_lookup(self):
+        class M(type):
+            def __dir__(self, *args): return ["14"]
+        class X(object):
+            __metaclass__ = M
+        x = X()
+        x.__dir__ = lambda x: ["14"]
+        assert dir(x) != ["14"]
 
     def test_format(self):
         assert format(4) == "4"
diff --git a/pypy/module/__pypy__/__init__.py b/pypy/module/__pypy__/__init__.py
--- a/pypy/module/__pypy__/__init__.py
+++ b/pypy/module/__pypy__/__init__.py
@@ -16,6 +16,7 @@
         'debug_stop'                : 'interp_debug.debug_stop',
         'debug_print_once'          : 'interp_debug.debug_print_once',
         'builtinify'                : 'interp_magic.builtinify',
+        'lookup_special'            : 'interp_magic.lookup_special',
     }
 
     def setup_after_space_initialization(self):
diff --git a/pypy/module/__pypy__/interp_magic.py b/pypy/module/__pypy__/interp_magic.py
--- a/pypy/module/__pypy__/interp_magic.py
+++ b/pypy/module/__pypy__/interp_magic.py
@@ -1,9 +1,9 @@
+from pypy.interpreter.baseobjspace import ObjSpace, W_Root
 from pypy.interpreter.error import OperationError
 from pypy.interpreter.gateway import unwrap_spec
 from pypy.rlib.objectmodel import we_are_translated
 from pypy.objspace.std.typeobject import MethodCache
 from pypy.objspace.std.mapdict import IndexCache
-from pypy.module._file.interp_file import W_File
 
 
 def internal_repr(space, w_object):
@@ -59,3 +59,14 @@
     func = space.interp_w(Function, w_func)
     bltn = BuiltinFunction(func)
     return space.wrap(bltn)
+
+ at unwrap_spec(ObjSpace, W_Root, str)
+def lookup_special(space, w_obj, meth):
+    """Lookup up a special method on an object."""
+    if space.is_oldstyle_instance(w_obj):
+        w_msg = space.wrap("this doesn't do what you want on old-style classes")
+        raise OperationError(space.w_TypeError, w_msg)
+    w_descr = space.lookup(w_obj, meth)
+    if w_descr is None:
+        return space.w_None
+    return space.get(w_descr, w_obj)
diff --git a/pypy/module/__pypy__/test/test_special.py b/pypy/module/__pypy__/test/test_special.py
--- a/pypy/module/__pypy__/test/test_special.py
+++ b/pypy/module/__pypy__/test/test_special.py
@@ -36,3 +36,16 @@
         assert not hasattr(A.b, 'im_func')
         assert A.a is not A.__dict__['a']
         assert A.b is A.__dict__['b']
+
+    def test_lookup_special(self):
+        from __pypy__ import lookup_special
+        class X(object):
+            def foo(self): return 42
+        x = X()
+        x.foo = 23
+        x.bar = 80
+        assert lookup_special(x, "foo")() == 42
+        assert lookup_special(x, "bar") is None
+        class X:
+            pass
+        raises(TypeError, lookup_special, X(), "foo")
diff --git a/pypy/module/_ast/test/test_ast.py b/pypy/module/_ast/test/test_ast.py
--- a/pypy/module/_ast/test/test_ast.py
+++ b/pypy/module/_ast/test/test_ast.py
@@ -128,6 +128,9 @@
         assert ns["x"] == ns["lemon"] == 3
         assert ns["apple"] == 4
 
+    def test_empty_module(self):
+        compile(self.ast.Module([]), "<test>", "exec")
+
     def test_ast_types(self):
         ast = self.ast
         expr = ast.Expr()
diff --git a/pypy/module/_file/interp_file.py b/pypy/module/_file/interp_file.py
--- a/pypy/module/_file/interp_file.py
+++ b/pypy/module/_file/interp_file.py
@@ -4,13 +4,13 @@
 import errno
 from pypy.rlib import streamio
 from pypy.rlib.rarithmetic import r_longlong
-from pypy.module._file.interp_stream import W_AbstractStream
-from pypy.module._file.interp_stream import StreamErrors, wrap_streamerror, wrap_oserror_as_ioerror
+from pypy.rlib.rstring import StringBuilder
+from pypy.module._file.interp_stream import (W_AbstractStream, StreamErrors,
+    wrap_streamerror, wrap_oserror_as_ioerror)
 from pypy.module.posix.interp_posix import dispatch_filename
 from pypy.interpreter.error import OperationError, operationerrfmt
-from pypy.interpreter.typedef import TypeDef, GetSetProperty
-from pypy.interpreter.typedef import interp_attrproperty, make_weakref_descr
-from pypy.interpreter.typedef import interp_attrproperty_w
+from pypy.interpreter.typedef import (TypeDef, GetSetProperty,
+    interp_attrproperty, make_weakref_descr, interp_attrproperty_w)
 from pypy.interpreter.gateway import interp2app, unwrap_spec
 
 
@@ -43,7 +43,11 @@
         # assume that the file and stream objects are only visible in the
         # thread that runs __del__, so no race condition should be possible
         self.clear_all_weakrefs()
-        self.direct_close()
+        try:
+            self.direct_close()
+        except StreamErrors, e:
+            operr = wrap_streamerror(self.space, e, self.w_name)
+            operr.write_unraisable(self.space, '__del__ of ', self)
 
     def fdopenstream(self, stream, fd, mode, w_name=None):
         self.fd = fd
@@ -160,14 +164,14 @@
         if n < 0:
             return stream.readall()
         else:
-            result = []
+            result = StringBuilder(n)
             while n > 0:
                 data = stream.read(n)
                 if not data:
                     break
                 n -= len(data)
                 result.append(data)
-            return ''.join(result)
+            return result.build()
 
     @unwrap_spec(size=int)
     def direct_readline(self, size=-1):
@@ -345,11 +349,11 @@
 may be returned, even if no size parameter was given.""")
 
     _decl(locals(), "readline",
-        """readlines([size]) -> list of strings, each a line from the file.
+        """readline([size]) -> next line from the file, as a string.
 
-Call readline() repeatedly and return a list of the lines so read.
-The optional size argument, if given, is an approximate bound on the
-total number of bytes in the lines returned.""")
+Retain newline.  A non-negative size argument limits the maximum
+number of bytes to return (an incomplete line may be returned then).
+Return an empty string at EOF.""")
 
     _decl(locals(), "readlines",
         """readlines([size]) -> list of strings, each a line from the file.
@@ -553,4 +557,4 @@
 @unwrap_spec(file=W_File, encoding="str_or_None", errors="str_or_None")
 def set_file_encoding(space, file, encoding=None, errors=None):
     file.encoding = encoding
-    file.errors = errors
\ No newline at end of file
+    file.errors = errors
diff --git a/pypy/module/_file/test/test_file.py b/pypy/module/_file/test/test_file.py
--- a/pypy/module/_file/test/test_file.py
+++ b/pypy/module/_file/test/test_file.py
@@ -232,6 +232,29 @@
             data = f.read()
             assert data == "15"
 
+    def test_exception_from_close(self):
+        import os
+        f = self.file(self.temppath, 'w')
+        os.close(f.fileno())
+        raises(IOError, f.close)    # bad file descriptor
+
+    def test_exception_from_del(self):
+        import os, gc, sys, cStringIO
+        f = self.file(self.temppath, 'w')
+        g = cStringIO.StringIO()
+        preverr = sys.stderr
+        try:
+            sys.stderr = g
+            os.close(f.fileno())
+            del f
+            gc.collect()     # bad file descriptor in f.__del__()
+        finally:
+            sys.stderr = preverr
+        import errno
+        assert os.strerror(errno.EBADF) in g.getvalue()
+        # the following is a "nice to have" feature that CPython doesn't have
+        if '__pypy__' in sys.builtin_module_names:
+            assert self.temppath in g.getvalue()
 
 
 class AppTestConcurrency(object):
diff --git a/pypy/module/_multibytecodec/interp_multibytecodec.py b/pypy/module/_multibytecodec/interp_multibytecodec.py
--- a/pypy/module/_multibytecodec/interp_multibytecodec.py
+++ b/pypy/module/_multibytecodec/interp_multibytecodec.py
@@ -1,5 +1,5 @@
 from pypy.interpreter.baseobjspace import Wrappable
-from pypy.interpreter.gateway import ObjSpace, interp2app
+from pypy.interpreter.gateway import ObjSpace, interp2app, unwrap_spec
 from pypy.interpreter.typedef import TypeDef
 from pypy.interpreter.error import OperationError
 from pypy.module._multibytecodec import c_codecs
@@ -11,6 +11,7 @@
         self.name = name
         self.codec = codec
 
+    @unwrap_spec(input=str, errors="str_or_None")
     def decode(self, space, input, errors=None):
         if errors is not None and errors != 'strict':
             raise OperationError(space.w_NotImplementedError,    # XXX
@@ -33,8 +34,8 @@
                                  space.wrap("internal codec error"))
         return space.newtuple([space.wrap(output),
                                space.wrap(len(input))])
-    decode.unwrap_spec = ['self', ObjSpace, str, 'str_or_None']
 
+    @unwrap_spec(input=unicode, errors="str_or_None")
     def encode(self, space, input, errors=None):
         if errors is not None and errors != 'strict':
             raise OperationError(space.w_NotImplementedError,    # XXX
@@ -57,7 +58,6 @@
                                  space.wrap("internal codec error"))
         return space.newtuple([space.wrap(output),
                                space.wrap(len(input))])
-    encode.unwrap_spec = ['self', ObjSpace, unicode, 'str_or_None']
 
 
 MultibyteCodec.typedef = TypeDef(
@@ -69,6 +69,7 @@
 MultibyteCodec.typedef.acceptable_as_base_class = False
 
 
+ at unwrap_spec(name=str)
 def getcodec(space, name):
     try:
         codec = c_codecs.getcodec(name)
@@ -76,4 +77,3 @@
         raise OperationError(space.w_LookupError,
                              space.wrap("no such codec is supported."))
     return space.wrap(MultibyteCodec(name, codec))
-getcodec.unwrap_spec = [ObjSpace, str]
diff --git a/pypy/module/_rawffi/callback.py b/pypy/module/_rawffi/callback.py
--- a/pypy/module/_rawffi/callback.py
+++ b/pypy/module/_rawffi/callback.py
@@ -43,7 +43,7 @@
             unwrap_value(space, push_elem, ll_res, 0,
                          callback_ptr.result, w_res)
     except OperationError, e:
-        tbprint(space, space.wrap(e.application_traceback),
+        tbprint(space, space.wrap(e.get_traceback()),
                 space.wrap(e.errorstr(space)))
         # force the result to be zero
         if callback_ptr.result is not None:
diff --git a/pypy/module/_stackless/interp_coroutine.py b/pypy/module/_stackless/interp_coroutine.py
--- a/pypy/module/_stackless/interp_coroutine.py
+++ b/pypy/module/_stackless/interp_coroutine.py
@@ -28,7 +28,7 @@
 
 from pypy.module.exceptions.interp_exceptions import W_SystemExit, _new_exception
 
-from pypy.rlib import rstack # for resume points
+from pypy.rlib import rstack, jit # for resume points
 from pypy.tool import stdlib_opcode as pythonopcode
 
 class _AppThunk(AbstractThunk):
@@ -47,9 +47,19 @@
     def call(self):
         costate = self.costate
         w_result = self.space.call_args(self.w_func, self.args)
-        rstack.resume_point("appthunk", costate, returns=w_result)
         costate.w_tempval = w_result
 
+class _ResumeThunk(AbstractThunk):
+    def __init__(self, space, costate, w_frame):
+        self.space = space
+        self.costate = costate
+        self.w_frame = w_frame
+
+    def call(self):
+        w_result = resume_frame(self.space, self.w_frame)
+        # costate.w_tempval = w_result #XXX?
+
+
 W_CoroutineExit = _new_exception('CoroutineExit', W_SystemExit,
                         """Coroutine killed manually.""")
 
@@ -97,7 +107,6 @@
                 "cannot switch to an unbound Coroutine"))
         state = self.costate
         self.switch()
-        rstack.resume_point("w_switch", state, space)
         w_ret, state.w_tempval = state.w_tempval, space.w_None
         return w_ret
 
@@ -116,7 +125,7 @@
         if isinstance(operror, OperationError):
             w_exctype = operror.w_type
             w_excvalue = operror.get_w_value(space)
-            w_exctraceback = operror.application_traceback
+            w_exctraceback = operror.get_traceback()
             w_excinfo = space.newtuple([w_exctype, w_excvalue, w_exctraceback])
             
             if w_exctype is self.costate.w_CoroutineExit:
@@ -151,7 +160,7 @@
                 space.gettypeobject(pytraceback.PyTraceback.typedef))):
                 raise OperationError(space.w_TypeError,
                       space.wrap("throw: arg 3 must be a traceback or None"))
-            operror.application_traceback = tb
+            operror.set_traceback(tb)
         
         self._kill(operror)
 
@@ -217,75 +226,17 @@
         self.parent = space.interp_w(AppCoroutine, w_parent)
         ec = self.space.getexecutioncontext()
         self.subctx.setstate(space, w_state)
-        self.reconstruct_framechain()
         if space.is_w(w_thunk, space.w_None):
-            self.thunk = None
+            if space.is_w(w_state, space.w_None):
+                self.thunk = None
+            else:
+                self.bind(_ResumeThunk(space, self.costate, self.subctx.topframe))
         else:
             w_func, w_args, w_kwds = space.unpackiterable(w_thunk,
                                                           expected_length=3)
             args = Arguments.frompacked(space, w_args, w_kwds)
             self.bind(_AppThunk(space, self.costate, w_func, args))
 
-    def reconstruct_framechain(self):
-        from pypy.interpreter.pyframe import PyFrame
-        from pypy.rlib.rstack import resume_state_create
-        if self.subctx.topframe is None:
-            self.frame = None
-            return
-
-        space = self.space
-        ec = space.getexecutioncontext()
-        costate = self.costate
-        # now the big fun of recreating tiny things...
-        bottom = resume_state_create(None, "yield_current_frame_to_caller_1")
-        # ("coroutine__bind", state)
-        _bind_frame = resume_state_create(bottom, "coroutine__bind", costate)
-        # ("appthunk", costate, returns=w_result)
-        appthunk_frame = resume_state_create(_bind_frame, "appthunk", costate)
-        chain = appthunk_frame
-        for frame in self.subctx.getframestack():
-            assert isinstance(frame, PyFrame)
-            # ("execute_frame", self, executioncontext, returns=w_exitvalue)
-            chain = resume_state_create(chain, "execute_frame", frame, ec)
-            code = frame.pycode.co_code
-            # ("dispatch", self, co_code, ec, returns=next_instr)
-            chain = resume_state_create(chain, "dispatch", frame, code, ec)
-            # ("handle_bytecode", self, co_code, ec, returns=next_instr)
-            chain = resume_state_create(chain, "handle_bytecode", frame, code,
-                                        ec)
-            instr = frame.last_instr
-            opcode = ord(code[instr])
-            map = pythonopcode.opmap
-            call_ops = [map['CALL_FUNCTION'], map['CALL_FUNCTION_KW'], map['CALL_FUNCTION_VAR'], 
-                        map['CALL_FUNCTION_VAR_KW'], map['CALL_METHOD']]
-            assert opcode in call_ops
-            # ("dispatch_call", self, co_code, next_instr, ec)
-            chain = resume_state_create(chain, "dispatch_call", frame, code,
-                                        instr+3, ec)
-            instr += 1
-            oparg = ord(code[instr]) | ord(code[instr + 1]) << 8
-            nargs = oparg & 0xff
-            nkwds = (oparg >> 8) & 0xff
-            if space.config.objspace.opcodes.CALL_METHOD and opcode == map['CALL_METHOD']:
-                if nkwds == 0:     # only positional arguments
-                    chain = resume_state_create(chain, 'CALL_METHOD', frame,
-                                                nargs)
-                else:              # includes keyword arguments
-                    chain = resume_state_create(chain, 'CALL_METHOD_KW', frame)
-            elif opcode == map['CALL_FUNCTION'] and nkwds == 0:
-                # Only positional arguments
-                # case1: ("CALL_FUNCTION", f, nargs, returns=w_result)
-                chain = resume_state_create(chain, 'CALL_FUNCTION', frame,
-                                            nargs)
-            else:
-                # case2: ("call_function", f, returns=w_result)
-                chain = resume_state_create(chain, 'call_function', frame)
-
-        # ("w_switch", state, space)
-        w_switch_frame = resume_state_create(chain, 'w_switch', costate, space)
-        # ("coroutine_switch", state, returns=incoming_frame)
-        switch_frame = resume_state_create(w_switch_frame, "coroutine_switch", costate)
-        self.frame = switch_frame
 
 # _mixin_ did not work
 for methname in StacklessFlags.__dict__:
@@ -411,3 +362,45 @@
 @unwrap_spec(limit=int)
 def set_stack_depth_limit(space, limit):
     rstack.set_stack_depth_limit(limit)
+
+
+# ___________________________________________________________________
+# unpickling trampoline
+
+def resume_frame(space, w_frame):
+    from pypy.interpreter.pyframe import PyFrame
+    frame = space.interp_w(PyFrame, w_frame, can_be_None=True)
+    w_result = space.w_None
+    operr = None
+    executioncontext = frame.space.getexecutioncontext()
+    while frame is not None:
+        code = frame.pycode.co_code
+        instr = frame.last_instr
+        opcode = ord(code[instr])
+        map = pythonopcode.opmap
+        call_ops = [map['CALL_FUNCTION'], map['CALL_FUNCTION_KW'], map['CALL_FUNCTION_VAR'], 
+                    map['CALL_FUNCTION_VAR_KW'], map['CALL_METHOD']]
+        assert opcode in call_ops
+        instr += 1
+        oparg = ord(code[instr]) | ord(code[instr + 1]) << 8
+        nargs = oparg & 0xff
+        nkwds = (oparg >> 8) & 0xff
+        if nkwds == 0:     # only positional arguments
+            # fast paths leaves things on the stack, pop them
+            if space.config.objspace.opcodes.CALL_METHOD and opcode == map['CALL_METHOD']:
+                frame.dropvalues(nargs + 2)
+            elif opcode == map['CALL_FUNCTION']:
+                frame.dropvalues(nargs + 1)
+
+        # small hack: unlink frame out of the execution context, because
+        # execute_frame will add it there again
+        executioncontext.topframeref = jit.non_virtual_ref(frame.f_backref())
+        frame.last_instr = instr + 1 # continue after the call
+        try:
+            w_result = frame.execute_frame(w_result, operr)
+        except OperationError, operr:
+            pass
+        frame = frame.f_backref()
+    if operr:
+        raise operr
+    return w_result
diff --git a/pypy/module/_stackless/interp_greenlet.py b/pypy/module/_stackless/interp_greenlet.py
--- a/pypy/module/_stackless/interp_greenlet.py
+++ b/pypy/module/_stackless/interp_greenlet.py
@@ -124,7 +124,7 @@
                 space.gettypeobject(pytraceback.PyTraceback.typedef))):
                 raise OperationError(space.w_TypeError,
                       space.wrap("throw: arg 3 must be a traceback or None"))
-            operror.application_traceback = tb
+            operror.set_traceback(tb)
         # Dead greenlet: turn GreenletExit into a regular return
         if self.isdead() and operror.match(space, self.costate.w_GreenletExit):
             args_w = [operror.get_w_value(space)]
diff --git a/pypy/module/_stackless/test/test_coroutine.py b/pypy/module/_stackless/test/test_coroutine.py
--- a/pypy/module/_stackless/test/test_coroutine.py
+++ b/pypy/module/_stackless/test/test_coroutine.py
@@ -8,33 +8,6 @@
         space = gettestobjspace(usemodules=('_stackless',))
         cls.space = space
 
-    def test_pickle_coroutine_empty(self):
-        # this test is limited to basic pickling.
-        # real stacks can only tested with a stackless pypy build.
-        import _stackless as stackless
-        co = stackless.coroutine()
-        import pickle
-        pckl = pickle.dumps(co)
-        co2 = pickle.loads(pckl)
-        # the empty unpickled coroutine can still be used:
-        result = []
-        co2.bind(result.append, 42)
-        co2.switch()
-        assert result == [42]
-
-    def test_pickle_coroutine_bound(self):
-        import pickle
-        import _stackless
-        lst = [4]
-        co = _stackless.coroutine()
-        co.bind(lst.append, 2)
-        pckl = pickle.dumps((co, lst))
-
-        (co2, lst2) = pickle.loads(pckl)
-        assert lst2 == [4]
-        co2.switch()
-        assert lst2 == [4, 2]
-
     def test_raise_propagate(self):
         import _stackless as stackless
         co = stackless.coroutine()
diff --git a/pypy/module/_stackless/test/test_pickle.py b/pypy/module/_stackless/test/test_pickle.py
--- a/pypy/module/_stackless/test/test_pickle.py
+++ b/pypy/module/_stackless/test/test_pickle.py
@@ -19,9 +19,35 @@
 class AppTestPickle:
 
     def setup_class(cls):
-        if not option.runappdirect:
-            py.test.skip('pure appdirect test (run with -A)')
-        cls.space = gettestobjspace(usemodules=('_stackless',))
+        cls.space = gettestobjspace(usemodules=('_stackless',), CALL_METHOD=True)
+
+    def test_pickle_coroutine_empty(self):
+        # this test is limited to basic pickling.
+        # real stacks can only tested with a stackless pypy build.
+        import _stackless as stackless
+        co = stackless.coroutine()
+        import pickle
+        pckl = pickle.dumps(co)
+        co2 = pickle.loads(pckl)
+        # the empty unpickled coroutine can still be used:
+        result = []
+        co2.bind(result.append, 42)
+        co2.switch()
+        assert result == [42]
+
+    def test_pickle_coroutine_bound(self):
+        import pickle
+        import _stackless
+        lst = [4]
+        co = _stackless.coroutine()
+        co.bind(lst.append, 2)
+        pckl = pickle.dumps((co, lst))
+
+        (co2, lst2) = pickle.loads(pckl)
+        assert lst2 == [4]
+        co2.switch()
+        assert lst2 == [4, 2]
+
 
     def test_simple_ish(self):
 
@@ -58,6 +84,113 @@
         finally:
             del sys.modules['mod']
 
+    def test_pickle_again(self):
+
+        import new, sys
+
+        mod = new.module('mod')
+        sys.modules['mod'] = mod
+        try:
+            exec '''
+output = []
+import _stackless
+def f(coro, n, x):
+    if n == 0:
+        coro.switch()
+        return
+    f(coro, n-1, 2*x)
+    output.append(x)
+
+def example():
+    main_coro = _stackless.coroutine.getcurrent()
+    sub_coro = _stackless.coroutine()
+    sub_coro.bind(f, main_coro, 5, 1)
+    sub_coro.switch()
+
+    import pickle
+    pckl = pickle.dumps(sub_coro)
+    new_coro = pickle.loads(pckl)
+    pckl = pickle.dumps(new_coro)
+    newer_coro = pickle.loads(pckl)
+
+    newer_coro.switch()
+
+example()
+assert output == [16, 8, 4, 2, 1]
+''' in mod.__dict__
+        finally:
+            del sys.modules['mod']
+
+    def test_kwargs(self):
+
+        import new, sys
+
+        mod = new.module('mod')
+        sys.modules['mod'] = mod
+        try:
+            exec '''
+output = []
+import _stackless
+def f(coro, n, x, step=4):
+    if n == 0:
+        coro.switch()
+        return
+    f(coro, n-1, 2*x, step=1)
+    output.append(x)
+
+def example():
+    main_coro = _stackless.coroutine.getcurrent()
+    sub_coro = _stackless.coroutine()
+    sub_coro.bind(f, main_coro, 5, 1, 1)
+    sub_coro.switch()
+
+    import pickle
+    pckl = pickle.dumps(sub_coro)
+    new_coro = pickle.loads(pckl)
+
+    new_coro.switch()
+
+example()
+assert output == [16, 8, 4, 2, 1]
+''' in mod.__dict__
+        finally:
+            del sys.modules['mod']
+
+    def test_starstarargs(self):
+
+        import new, sys
+
+        mod = new.module('mod')
+        sys.modules['mod'] = mod
+        try:
+            exec '''
+output = []
+import _stackless
+def f(coro, n, x, step=4):
+    if n == 0:
+        coro.switch()
+        return
+    f(coro, n-1, 2*x, **{'step': 1})
+    output.append(x)
+
+def example():
+    main_coro = _stackless.coroutine.getcurrent()
+    sub_coro = _stackless.coroutine()
+    sub_coro.bind(f, main_coro, 5, 1, 1)
+    sub_coro.switch()
+
+    import pickle
+    pckl = pickle.dumps(sub_coro)
+    new_coro = pickle.loads(pckl)
+
+    new_coro.switch()
+
+example()
+assert output == [16, 8, 4, 2, 1]
+''' in mod.__dict__
+        finally:
+            del sys.modules['mod']
+
     def test_closure(self):
         import new, sys
 
@@ -130,8 +263,55 @@
         finally:
             del sys.modules['mod']
 
+    def test_exception_after_unpickling(self):
+
+        import new, sys
+
+        mod = new.module('mod')
+        sys.modules['mod'] = mod
+        try:
+            exec '''
+output = []
+import _stackless
+def f(coro, n, x):
+    if n == 0:
+        coro.switch()
+        raise ValueError
+    try:
+        f(coro, n-1, 2*x)
+    finally:
+        output.append(x)
+
+def example():
+    main_coro = _stackless.coroutine.getcurrent()
+    sub_coro = _stackless.coroutine()
+    sub_coro.bind(f, main_coro, 5, 1)
+    sub_coro.switch()
+
+    import pickle
+    pckl = pickle.dumps(sub_coro)
+    new_coro = pickle.loads(pckl)
+
+    try:
+        sub_coro.switch()
+    except ValueError:
+        pass
+    else:
+        assert 0
+    try:
+        new_coro.switch()
+    except ValueError:
+        pass
+    else:
+        assert 0
+
+example()
+assert output == [16, 8, 4, 2, 1] * 2
+''' in mod.__dict__
+        finally:
+            del sys.modules['mod']
+
     def test_loop(self):
-        #skip("happily segfaulting")
         import new, sys
 
         mod = new.module('mod')
diff --git a/pypy/module/_stackless/test/test_pickle_infrastructure.py b/pypy/module/_stackless/test/test_pickle_infrastructure.py
deleted file mode 100644
--- a/pypy/module/_stackless/test/test_pickle_infrastructure.py
+++ /dev/null
@@ -1,301 +0,0 @@
-from pypy.conftest import gettestobjspace
-from py.test import skip
-
-
-class BaseAppTestPicklePrerequisites(object):
-    OPTIONS = {}
-    def setup_class(cls):
-        space = gettestobjspace(usemodules=('_stackless',), **cls.OPTIONS)
-        cls.space = space
-
-    def test_pickle_switch_function(object):
-        import _stackless, pickle
-
-        sw = _stackless.coroutine.switch.im_func
-        dump = pickle.dumps(sw)
-        res = pickle.loads(dump)
-
-        assert res is sw
-        assert res.func_code is sw.func_code
-        assert res.func_doc is sw.func_doc
-        assert res.func_globals is sw.func_globals
-
-    def test_pickle_switch_function_code(object):
-        import _stackless, pickle
-
-        sw = _stackless.coroutine.switch.im_func.func_code
-        dump = pickle.dumps(sw)
-        res = pickle.loads(dump)
-
-        assert res is sw
-        
-class AppTestPicklePrerequisites(BaseAppTestPicklePrerequisites):
-    pass
-
-class AppTestPicklePrerequisitesBuiltinShortcut(BaseAppTestPicklePrerequisites):
-    OPTIONS = {"objspace.std.builtinshortcut": True}
-
-class FrameCheck(object):
-
-    def __init__(self, name):
-        self.name = name
-
-    def __eq__(self, frame):
-        return frame.pycode.co_name == self.name
-
-class BytecodeCheck(object):
-
-    def __init__(self, code, op, arg):
-        self.code = code
-        self.op = chr(op)+chr(arg & 0xff) + chr(arg >> 8 & 0xff)
-
-    def __eq__(self, pos):
-        return self.code[pos-3:pos] == self.op
-
-class BaseTestReconstructFrameChain(object):
-    OPTIONS = {}
-
-    def setup_class(cls):
-        space = gettestobjspace(usemodules=('_stackless',), **cls.OPTIONS)
-        cls.space = space
-
-        from pypy.rlib import rstack
-        cls.old_resume_state_create = rstack.resume_state_create
-
-        def tr(prevstate, label, *args):
-            if prevstate is None:
-                prevstate = []
-            return prevstate+[(label, args)]
-        rstack.resume_state_create = tr
-
-        w_opmap = space.appexec([], """():
-        import opcode
-
-        return opcode.opmap
-        """)
-
-        opmap = space.unwrap(w_opmap)
-        cls.CALL_FUNCTION = opmap['CALL_FUNCTION']
-        cls.CALL_FUNCTION_VAR = opmap['CALL_FUNCTION_VAR']
-        cls.CALL_METHOD = opmap['CALL_METHOD']
-
-        cls.callmethod = getattr(cls, cls.callmethod_label)
-
-    def teardown_class(cls):
-        from pypy.rlib import rstack
-        rstack.resume_state_create = cls.old_resume_state_create
-
-    def start(self, w_coro):
-        self.i = 0
-        self.frame_to_check = w_coro.frame
-        w_coro.frame = None # avoid exploding in kill > __del__
-
-    def end(self):
-        assert self.i == len(self.frame_to_check)
-
-    def check_entry(self, label, *args):
-        frame = self.frame_to_check
-        assert frame[self.i] == (label, args)
-        self.i += 1
-
-        
-    def test_two_frames_simple(self):
-        space = self.space
-
-        w_res = space.appexec([], """():
-        import _stackless as stackless
-        import pickle
-
-        main = stackless.coroutine.getcurrent()
-        d = {'main': main}        
-
-        exec \"\"\"
-def f():
-    g(1)
-
-def g(x):
-    main.switch()
-\"\"\" in d
-        f = d['f']
-        g = d['g']
-
-        co = stackless.coroutine()
-        co.bind(f)
-        co.switch()
-
-        s = pickle.dumps(co)
-        co = pickle.loads(s)
-
-        return co, f, g
-        """)
-
-        w_co, w_f, w_g = space.fixedview(w_res)
-
-        ec = space.getexecutioncontext()
-        fcode = w_f.code.co_code
-        gcode = w_g.code.co_code        
-
-        self.start(w_co)
-        e = self.check_entry
-        e('yield_current_frame_to_caller_1')
-        e('coroutine__bind', w_co.costate)
-        e('appthunk', w_co.costate)
-        # f
-        e('execute_frame', FrameCheck('f'), ec)
-        e('dispatch', FrameCheck('f'), fcode, ec)
-        e('handle_bytecode', FrameCheck('f'), fcode, ec)
-        e('dispatch_call', FrameCheck('f'), fcode,
-          BytecodeCheck(fcode, self.CALL_FUNCTION, 1), ec)
-        e('CALL_FUNCTION', FrameCheck('f'), 1)
-        # g
-        e('execute_frame', FrameCheck('g'), ec)
-        e('dispatch', FrameCheck('g'), gcode, ec)
-        e('handle_bytecode', FrameCheck('g'), gcode, ec)
-        e('dispatch_call', FrameCheck('g'), gcode,
-          BytecodeCheck(gcode, self.callmethod, 0), ec)
-        e(self.callmethod_label, FrameCheck('g'), 0)
-        e('w_switch', w_co.costate, space)
-        e('coroutine_switch', w_co.costate)
-        self.end()
-
-    def test_two_frames_stararg(self):
-        space = self.space
-
-        w_res = space.appexec([], """():
-        import _stackless as stackless
-        import pickle
-        
-        main = stackless.coroutine.getcurrent()
-        d = {'main': main}        
-
-        exec \"\"\"        
-def f():
-    g(4, 3, d=2, *(1,))
-
-def g(a, b, c, d):
-    main.switch()
-\"\"\" in d
-        f = d['f']
-        g = d['g']    
-
-        co = stackless.coroutine()
-        co.bind(f)
-        co.switch()
-
-        s = pickle.dumps(co)
-        co = pickle.loads(s)
-
-        return co, f, g
-        """)
-
-        w_co, w_f, w_g = space.fixedview(w_res)
-
-        ec = space.getexecutioncontext()
-        fcode = w_f.code.co_code
-        gcode = w_g.code.co_code        
-
-        self.start(w_co)
-        e = self.check_entry
-        e('yield_current_frame_to_caller_1')
-        e('coroutine__bind', w_co.costate)
-        e('appthunk', w_co.costate)
-        # f
-        e('execute_frame', FrameCheck('f'), ec)
-        e('dispatch', FrameCheck('f'), fcode, ec)
-        e('handle_bytecode', FrameCheck('f'), fcode, ec)
-        e('dispatch_call', FrameCheck('f'), fcode,
-          BytecodeCheck(fcode, self.CALL_FUNCTION_VAR, 2+(1<<8)), ec)
-        e('call_function', FrameCheck('f'))
-        # g
-        e('execute_frame', FrameCheck('g'), ec)
-        e('dispatch', FrameCheck('g'), gcode, ec)
-        e('handle_bytecode', FrameCheck('g'), gcode, ec)
-        e('dispatch_call', FrameCheck('g'), gcode,
-          BytecodeCheck(gcode, self.callmethod, 0), ec)
-        e(self.callmethod_label, FrameCheck('g'), 0)
-        e('w_switch', w_co.costate, space)
-        e('coroutine_switch', w_co.costate)
-        self.end()        
-    
-    def test_two_frames_method(self):
-        space = self.space
-
-        w_res = space.appexec([], """():
-        import _stackless as stackless
-        import pickle
-        import new, sys
-
-        mod = new.module('mod')
-        sys.modules['mod'] = mod
-        
-        main = stackless.coroutine.getcurrent()
-        d = {'main': main}        
-
-        exec \"\"\"                
-def f():
-    a = A()
-    a.m(1)
-
-def g(_, x):
-    main.switch()
-
-class A(object):
-    m = g
-\"\"\" in d
-        f = d['f']
-        g = d['g']
-        A = d['A']
-
-        # to make pickling work
-        mod.A = A
-        A.__module__ = 'mod'
-
-        co = stackless.coroutine()
-        co.bind(f)
-        co.switch()
-
-        s = pickle.dumps(co)
-        co = pickle.loads(s)
-
-        return co, f, g
-        """)
-
-        w_co, w_f, w_g = space.fixedview(w_res)
-
-        ec = space.getexecutioncontext()
-        fcode = w_f.code.co_code
-        gcode = w_g.code.co_code        
-
-        self.start(w_co)
-        e = self.check_entry
-        e('yield_current_frame_to_caller_1')
-        e('coroutine__bind', w_co.costate)
-        e('appthunk', w_co.costate)
-        # f
-        e('execute_frame', FrameCheck('f'), ec)
-        e('dispatch', FrameCheck('f'), fcode, ec)
-        e('handle_bytecode', FrameCheck('f'), fcode, ec)
-        e('dispatch_call', FrameCheck('f'), fcode,
-          BytecodeCheck(fcode, self.callmethod, 1), ec)
-        e(self.callmethod_label, FrameCheck('f'), 1)
-        # g
-        e('execute_frame', FrameCheck('g'), ec)
-        e('dispatch', FrameCheck('g'), gcode, ec)
-        e('handle_bytecode', FrameCheck('g'), gcode, ec)
-        e('dispatch_call', FrameCheck('g'), gcode,
-          BytecodeCheck(gcode, self.callmethod, 0), ec)
-        e(self.callmethod_label, FrameCheck('g'), 0)
-        e('w_switch', w_co.costate, space)
-        e('coroutine_switch', w_co.costate)
-        self.end()
-
-class TestReconstructFrameChain(BaseTestReconstructFrameChain):
-    callmethod_label = 'CALL_FUNCTION'
-
-class TestReconstructFrameChain_CALL_METHOD(BaseTestReconstructFrameChain):
-    OPTIONS = {"objspace.opcodes.CALL_METHOD": True,
-               }
-
-    callmethod_label = 'CALL_METHOD'
-
-                
diff --git a/pypy/module/_weakref/interp__weakref.py b/pypy/module/_weakref/interp__weakref.py
--- a/pypy/module/_weakref/interp__weakref.py
+++ b/pypy/module/_weakref/interp__weakref.py
@@ -1,9 +1,10 @@
 import py
+from pypy.interpreter.argument import Arguments
 from pypy.interpreter.baseobjspace import Wrappable, W_Root
-from pypy.interpreter.argument import Arguments
 from pypy.interpreter.error import OperationError
+from pypy.interpreter.gateway import interp2app, ObjSpace
 from pypy.interpreter.typedef import GetSetProperty, TypeDef
-from pypy.interpreter.gateway import interp2app, ObjSpace
+from pypy.rlib import jit
 import weakref
 
 
@@ -13,7 +14,7 @@
         self.refs_weak = []
         self.cached_weakref_index = -1
         self.cached_proxy_index = -1
-        
+
     def __del__(self):
         """This runs when the interp-level object goes away, and allows
         its lifeline to go away.  The purpose of this is to activate the
@@ -37,6 +38,7 @@
         # weakref callbacks are not invoked eagerly here.  They are
         # invoked by self.__del__() anyway.
 
+    @jit.dont_look_inside
     def get_or_make_weakref(self, space, w_subtype, w_obj, w_callable):
         w_weakreftype = space.gettypeobject(W_Weakref.typedef)
         is_weakreftype = space.is_w(w_weakreftype, w_subtype)
@@ -55,6 +57,7 @@
             self.cached_weakref_index = index
         return w_ref
 
+    @jit.dont_look_inside
     def get_or_make_proxy(self, space, w_obj, w_callable):
         can_reuse = space.is_w(w_callable, space.w_None)
         if can_reuse and self.cached_proxy_index >= 0:
@@ -81,7 +84,7 @@
         w_weakreftype = space.gettypeobject(W_Weakref.typedef)
         for i in range(len(self.refs_weak)):
             w_ref = self.refs_weak[i]()
-            if (w_ref is not None and 
+            if (w_ref is not None and
                 space.is_true(space.isinstance(w_ref, w_weakreftype))):
                 return w_ref
         return space.w_None
@@ -106,6 +109,7 @@
         w_self.w_obj_weak = weakref.ref(w_obj)
         w_self.w_callable = w_callable
 
+    @jit.dont_look_inside
     def dereference(self):
         w_obj = self.w_obj_weak()
         return w_obj
@@ -244,7 +248,7 @@
     lifeline = w_obj.getweakref()
     if lifeline is None:
         lifeline = WeakrefLifeline(space)
-        w_obj.setweakref(space, lifeline) 
+        w_obj.setweakref(space, lifeline)
     return lifeline.get_or_make_proxy(space, w_obj, w_callable)
 
 def descr__new__proxy(space, w_subtype, w_obj, w_callable=None):
diff --git a/pypy/module/bz2/interp_bz2.py b/pypy/module/bz2/interp_bz2.py
--- a/pypy/module/bz2/interp_bz2.py
+++ b/pypy/module/bz2/interp_bz2.py
@@ -363,42 +363,44 @@
 
     def seek(self, offset, whence):
         READMAX = 2**18   # 256KB
-        if whence == 1:
-            if offset >= 0:
-                read = r_longlong(0)
-                while read < offset:
-                    count = offset - read
-                    if count < READMAX:
-                        count = intmask(count)
-                    else:
-                        count = READMAX
-                    read += len(self.read(count))
-            else:
-                pos = self.readlength + offset
-                self.seek(pos, 0)
+
+        # Make offset relative to the start of the file
+        if whence == 2:
+            # Read everything to arrive at the end
+            while len(self.read(READMAX)) > 0:
+                pass
+            offset += self.readlength
+        elif whence == 1:
+            offset += self.readlength
         elif whence == 0:
+            pass
+        else:
+            raise operationerrfmt(self.space.w_ValueError,
+                                  "Invalid value for whence: %d", whence)
+
+        # Make offset relative to the current pos
+        # Rewind iff necessary
+        if offset < self.readlength:
             self.stream.seek(0, 0)
             self.decompressor = W_BZ2Decompressor(self.space)
             self.readlength = r_longlong(0)
             self.buffer = ""
             self.finished = False
-            read = 0
-            while read < offset:
-                count = offset - read
-                if count < READMAX:
-                    count = intmask(count)
-                else:
-                    count = READMAX
-                length = len(self.read(count))
-                read += length
-                if not length:
-                    break
         else:
-            # first measure the length by reading everything left
-            while len(self.read(READMAX)) > 0:
-                pass
-            pos = self.readlength + offset
-            self.seek(pos, 0)
+            offset -= self.readlength
+
+        # Seek
+        read = r_longlong(0)
+        while read < offset:
+            count = offset - read
+            if count < READMAX:
+                count = intmask(count)
+            else:
+                count = READMAX
+            length = len(self.read(count))
+            if not length:
+                break
+            read += length
 
     def readall(self):
         w_result = self.decompressor.decompress(self.stream.readall())
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
@@ -561,6 +561,7 @@
             elif callable.api_func.restype is not lltype.Void:
                 retval = rffi.cast(callable.api_func.restype, result)
         except Exception, e:
+            print 'Fatal error in cpyext, calling', callable.__name__
             if not we_are_translated():
                 import traceback
                 traceback.print_exc()
@@ -965,6 +966,7 @@
     state = space.fromcache(State)
     if state.find_extension(name, path) is not None:
         return
+    old_context = state.package_context
     state.package_context = name, path
     try:
         from pypy.rlib import rdynload
@@ -990,7 +992,7 @@
         generic_cpy_call(space, initfunc)
         state.check_and_raise_exception()
     finally:
-        state.package_context = None, None
+        state.package_context = old_context
     state.fixup_extension(name, path)
 
 @specialize.ll()
diff --git a/pypy/module/cpyext/classobject.py b/pypy/module/cpyext/classobject.py
--- a/pypy/module/cpyext/classobject.py
+++ b/pypy/module/cpyext/classobject.py
@@ -31,4 +31,9 @@
         return w_result
     return w_instance.w_class.lookup(space, name)
 
+ at cpython_api([PyObject, PyObject, PyObject], PyObject)
+def PyClass_New(space, w_bases, w_dict, w_name):
+    w_classobj = space.gettypefor(W_ClassObject)
+    return space.call_function(w_classobj,
+                               w_name, w_bases, w_dict)
 
diff --git a/pypy/module/cpyext/frameobject.py b/pypy/module/cpyext/frameobject.py
--- a/pypy/module/cpyext/frameobject.py
+++ b/pypy/module/cpyext/frameobject.py
@@ -1,6 +1,7 @@
 from pypy.rpython.lltypesystem import rffi, lltype
 from pypy.module.cpyext.api import (
-    cpython_api, bootstrap_function, PyObjectFields, cpython_struct)
+    cpython_api, bootstrap_function, PyObjectFields, cpython_struct,
+    CANNOT_FAIL)
 from pypy.module.cpyext.pyobject import (
     PyObject, Py_DecRef, make_ref, from_ref, track_reference,
     make_typedescr, get_typedescr)
@@ -9,6 +10,7 @@
 from pypy.module.cpyext.funcobject import PyCodeObject
 from pypy.interpreter.pyframe import PyFrame
 from pypy.interpreter.pycode import PyCode
+from pypy.interpreter.pytraceback import PyTraceback
 
 PyFrameObjectStruct = lltype.ForwardReference()
 PyFrameObject = lltype.Ptr(PyFrameObjectStruct)
@@ -80,3 +82,8 @@
     frame = space.interp_w(PyFrame, w_frame)
     record_application_traceback(space, state.operror, frame, 0)
     return 0
+
+ at cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL)
+def PyTraceBack_Check(space, w_obj):
+    obj = space.interpclass_w(w_obj)
+    return obj is not None and isinstance(obj, PyTraceback)
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
@@ -69,6 +69,10 @@
     assert isinstance(w_method, Method)
     return borrow_from(w_method, w_method.w_class)
 
+ at cpython_api([PyObject], PyObject)
+def PyClassMethod_New(space, w_function):
+    return space.call_method(space.builtin, "classmethod", w_function)
+
 def unwrap_list_of_strings(space, w_list):
     return [space.str_w(w_item) for w_item in space.fixedview(w_list)]
 
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
@@ -4,7 +4,7 @@
 from pypy.module.cpyext.api import (
     cpython_api, build_type_checkers, PyObject,
     CONST_STRING, CANNOT_FAIL, Py_ssize_t)
-from pypy.rlib.rarithmetic import r_uint
+from pypy.rlib.rarithmetic import r_uint, intmask, LONG_TEST
 import sys
 
 PyInt_Check, PyInt_CheckExact = build_type_checkers("Int")
@@ -73,13 +73,22 @@
                              space.wrap("an integer is required, got NULL"))
     return space.int_w(w_obj) # XXX this is wrong on win64
 
+ at cpython_api([rffi.SIZE_T], PyObject)
+def PyInt_FromSize_t(space, ival):
+    """Create a new integer object with a value of ival. If the value exceeds
+    LONG_MAX, a long integer object is returned.
+    """
+    if ival < LONG_TEST:
+        return space.wrap(intmask(ival))
+    return space.wrap(ival)
+
 @cpython_api([Py_ssize_t], PyObject)
 def PyInt_FromSsize_t(space, ival):
     """Create a new integer object with a value of ival. If the value is larger
     than LONG_MAX or smaller than LONG_MIN, a long integer object is
     returned.
     """
-    return space.wrap(ival) # XXX this is wrong on win64
+    return space.wrap(ival)
 
 @cpython_api([CONST_STRING, rffi.CCHARPP, rffi.INT_real], PyObject)
 def PyInt_FromString(space, str, pend, base):
diff --git a/pypy/module/cpyext/methodobject.py b/pypy/module/cpyext/methodobject.py
--- a/pypy/module/cpyext/methodobject.py
+++ b/pypy/module/cpyext/methodobject.py
@@ -73,29 +73,29 @@
                 rffi.charp2str(self.ml.c_ml_name) + "() takes no keyword arguments"))
 
         func = rffi.cast(PyCFunction, self.ml.c_ml_meth)
+        length = space.int_w(space.len(w_args))
         if flags & METH_KEYWORDS:
             func = rffi.cast(PyCFunctionKwArgs, self.ml.c_ml_meth)
             return generic_cpy_call(space, func, w_self, w_args, w_kw)
         elif flags & METH_NOARGS:
-            if len(w_args.wrappeditems) == 0:
+            if length == 0:
                 return generic_cpy_call(space, func, w_self, None)
             raise OperationError(space.w_TypeError, space.wrap(
                 rffi.charp2str(self.ml.c_ml_name) + "() takes no arguments"))
         elif flags & METH_O:
-            assert isinstance(w_args, W_TupleObject)
-            if len(w_args.wrappeditems) != 1:
+            if length != 1:
                 raise OperationError(space.w_TypeError,
                         space.wrap("%s() takes exactly one argument (%d given)" %  (
                         rffi.charp2str(self.ml.c_ml_name), 
-                        len(w_args.wrappeditems))))
-            w_arg = w_args.wrappeditems[0]
+                        length)))
+            w_arg = space.getitem(w_args, space.wrap(0))
             return generic_cpy_call(space, func, w_self, w_arg)
         elif flags & METH_VARARGS:
             return generic_cpy_call(space, func, w_self, w_args)
         else: # METH_OLDARGS, the really old style
-            size = len(w_args.wrappeditems)
+            size = length
             if size == 1:
-                w_arg = w_args.wrappeditems[0]
+                w_arg = space.getitem(w_args, space.wrap(0))
             elif size == 0:
                 w_arg = None
             else:
diff --git a/pypy/module/cpyext/number.py b/pypy/module/cpyext/number.py
--- a/pypy/module/cpyext/number.py
+++ b/pypy/module/cpyext/number.py
@@ -49,6 +49,13 @@
     failure.  This is the equivalent of the Python expression long(o)."""
     return space.long(w_obj)
 
+ at cpython_api([PyObject], PyObject)
+def PyNumber_Index(space, w_obj):
+    """Returns the o converted to a Python int or long on success or NULL with a
+    TypeError exception raised on failure.
+    """
+    return space.index(w_obj)
+
 def func_rename(newname):
     return lambda func: func_with_new_name(func, newname)
 
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
@@ -57,7 +57,7 @@
     if operror:
         ptype[0] = make_ref(space, operror.w_type)
         pvalue[0] = make_ref(space, operror.get_w_value(space))
-        ptraceback[0] = make_ref(space, space.wrap(operror.application_traceback))
+        ptraceback[0] = make_ref(space, space.wrap(operror.get_traceback()))
     else:
         ptype[0] = lltype.nullptr(PyObject.TO)
         pvalue[0] = lltype.nullptr(PyObject.TO)
@@ -268,7 +268,7 @@
 
     w_type = operror.w_type
     w_value = operror.get_w_value(space)
-    w_tb = space.wrap(operror.application_traceback)
+    w_tb = space.wrap(operror.get_traceback())
 
     if rffi.cast(lltype.Signed, set_sys_last_vars):
         space.sys.setdictvalue(space, "last_type", w_type)
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
@@ -611,8 +611,8 @@
 	if (result != NULL && n > 0) {
 		for (i = 0; i < n; ++i) {
 			tmp = (PyObject *)va_arg(va, PyObject *);
+			Py_INCREF(tmp);
 			PyTuple_SET_ITEM(result, i, tmp);
-			Py_INCREF(tmp);
 		}
 	}
 	return result;
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
@@ -2,7 +2,7 @@
 from pypy.rpython.lltypesystem import rffi, lltype
 from pypy.module.cpyext.api import (
     cpython_api, cpython_struct, bootstrap_function, build_type_checkers,
-    PyObjectFields, Py_ssize_t, CONST_STRING)
+    PyObjectFields, Py_ssize_t, CONST_STRING, CANNOT_FAIL)
 from pypy.module.cpyext.pyerrors import PyErr_BadArgument
 from pypy.module.cpyext.pyobject import (
     PyObject, PyObjectP, Py_DecRef, make_ref, from_ref, track_reference,
@@ -203,6 +203,10 @@
     ref[0] = rffi.cast(PyObject, py_newstr)
     return 0
 
+ at cpython_api([PyObject, PyObject], rffi.INT, error=CANNOT_FAIL)
+def _PyString_Eq(space, w_str1, w_str2):
+    return space.eq_w(w_str1, w_str2)
+
 @cpython_api([PyObjectP, PyObject], lltype.Void)
 def PyString_Concat(space, ref, w_newpart):
     """Create a new string object in *string containing the contents of newpart
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
@@ -172,12 +172,6 @@
     This is equivalent to (PyBUF_ND)."""
     raise NotImplementedError
 
- at cpython_api([Py_buffer], lltype.Void)
-def PyBuffer_Release(space, view):
-    """Release the buffer view.  This should be called when the buffer
-    is no longer being used as it may free memory from it."""
-    raise NotImplementedError
-
 @cpython_api([rffi.CCHARP], Py_ssize_t, error=CANNOT_FAIL)
 def PyBuffer_SizeFromFormat(space, format):
     """Return the implied ~Py_buffer.itemsize from the struct-stype
@@ -198,13 +192,6 @@
     given shape with the given number of bytes per element."""
     raise NotImplementedError
 
- at cpython_api([Py_buffer, PyObject, rffi.VOIDP, Py_ssize_t, rffi.INT_real, rffi.INT_real], rffi.INT_real, error=-1)
-def PyBuffer_FillInfo(space, view, obj, buf, len, readonly, infoflags):
-    """Fill in a buffer-info structure, view, correctly for an exporter that can
-    only share a contiguous chunk of memory of "unsigned bytes" of the given
-    length.  Return 0 on success and -1 (with raising an error) on error."""
-    raise NotImplementedError
-
 @cpython_api([Py_buffer], PyObject)
 def PyMemoryView_FromBuffer(space, view):
     """Create a memoryview object wrapping the given buffer-info structure view.
@@ -1094,14 +1081,6 @@
     """
     raise NotImplementedError
 
- at cpython_api([PyObject], PyObject)
-def PyImport_ReloadModule(space, m):
-    """Reload a module.  This is best described by referring to the built-in
-    Python function reload(), as the standard reload() function calls this
-    function directly.  Return a new reference to the reloaded module, or NULL
-    with an exception set on failure (the module still exists in this case)."""
-    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
@@ -1140,13 +1119,6 @@
     of the bytecode file, in little-endian byte order."""
     raise NotImplementedError
 
- at cpython_api([], PyObject)
-def PyImport_GetModuleDict(space):
-    """Return the dictionary used for the module administration (a.k.a.
-    sys.modules).  Note that this is a per-interpreter variable."""
-    borrow_from()
-    raise NotImplementedError
-
 @cpython_api([PyObject], PyObject)
 def PyImport_GetImporter(space, path):
     """Return an importer object for a sys.path/pkg.__path__ item
@@ -1701,13 +1673,6 @@
     """
     raise NotImplementedError
 
- at cpython_api([rffi.SIZE_T], PyObject)
-def PyInt_FromSize_t(space, ival):
-    """Create a new integer object with a value of ival. If the value exceeds
-    LONG_MAX, a long integer object is returned.
-    """
-    raise NotImplementedError
-
 @cpython_api([PyObject], rffi.ULONGLONG, error=-1)
 def PyInt_AsUnsignedLongLongMask(space, io):
     """Will first attempt to cast the object to a PyIntObject or
@@ -1920,13 +1885,6 @@
     Reference counts are still not increased in this case."""
     raise NotImplementedError
 
- at cpython_api([PyObject], PyObject)
-def PyNumber_Index(space, o):
-    """Returns the o converted to a Python int or long on success or NULL with a
-    TypeError exception raised on failure.
-    """
-    raise NotImplementedError
-
 @cpython_api([PyObject, rffi.INT_real], PyObject)
 def PyNumber_ToBase(space, n, base):
     """Returns the integer n converted to base as a string with a base
@@ -2254,15 +2212,6 @@
     standard C library function exit(status)."""
     raise NotImplementedError
 
- at cpython_api([PyObject, Py_ssize_t, Py_ssize_t], PyObject)
-def PyTuple_GetSlice(space, p, low, high):
-    """Take a slice of the tuple pointed to by p from low to high and return it
-    as a new tuple.
-
-    This function used an int type for low and high. This might
-    require changes in your code for properly supporting 64-bit systems."""
-    raise NotImplementedError
-
 @cpython_api([], rffi.INT_real, error=CANNOT_FAIL)
 def PyTuple_ClearFreeList(space):
     """Clear the free list. Return the total number of freed items.
@@ -2275,14 +2224,6 @@
     """
     raise NotImplementedError
 
- at cpython_api([PyTypeObjectPtr], lltype.Void)
-def PyType_Modified(space, type):
-    """Invalidate the internal lookup cache for the type and all of its
-    subtypes.  This function must be called after any manual
-    modification of the attributes or base classes of the type.
-    """
-    raise NotImplementedError
-
 @cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL)
 def PyType_IS_GC(space, o):
     """Return true if the type object includes support for the cycle detector; this
diff --git a/pypy/module/cpyext/test/test_classobject.py b/pypy/module/cpyext/test/test_classobject.py
--- a/pypy/module/cpyext/test/test_classobject.py
+++ b/pypy/module/cpyext/test/test_classobject.py
@@ -40,3 +40,14 @@
         assert not isinstance(api.PyObject_GetAttr(w_instance, space.wrap('f')), Function)
         # _PyInstance_Lookup returns the raw descriptor
         assert isinstance(api._PyInstance_Lookup(w_instance, space.wrap('f')), Function)
+
+    def test_pyclass_new(self, space, api):
+        w_bases = space.newtuple([])
+        w_dict = space.newdict()
+        w_name = space.wrap("C")
+        w_class = api.PyClass_New(w_bases, w_dict, w_name)
+        assert not space.isinstance_w(w_class, space.w_type)
+        w_instance = space.call_function(w_class)
+        assert api.PyInstance_Check(w_instance)
+        assert space.is_true(space.call_method(space.builtin, "isinstance",
+                                               w_instance, w_class))
diff --git a/pypy/module/cpyext/test/test_eval.py b/pypy/module/cpyext/test/test_eval.py
--- a/pypy/module/cpyext/test/test_eval.py
+++ b/pypy/module/cpyext/test/test_eval.py
@@ -193,3 +193,32 @@
             return args
         assert module.call_func(f) == ("text", 42, None)
         assert module.call_method("text") == 2
+
+    def test_CallFunctionObjArgs(self):
+        module = self.import_extension('foo', [
+            ("call_func", "METH_VARARGS",
+             """
+                PyObject *t = PyString_FromString("t");
+                PyObject *res = PyObject_CallFunctionObjArgs(
+                   PyTuple_GetItem(args, 0),
+                   Py_None, NULL);
+                Py_DECREF(t);
+                return res;
+             """),
+            ("call_method", "METH_VARARGS",
+             """
+                PyObject *t = PyString_FromString("t");
+                PyObject *count = PyString_FromString("count");
+                PyObject *res = PyObject_CallMethodObjArgs(
+                   PyTuple_GetItem(args, 0),
+                   count, t, NULL);
+                Py_DECREF(t);
+                Py_DECREF(count);
+                return res;
+             """),
+            ])
+        def f(*args):
+            return args
+        assert module.call_func(f) == (None,)
+        assert module.call_method("text") == 2
+        
diff --git a/pypy/module/cpyext/test/test_frameobject.py b/pypy/module/cpyext/test/test_frameobject.py
--- a/pypy/module/cpyext/test/test_frameobject.py
+++ b/pypy/module/cpyext/test/test_frameobject.py
@@ -64,3 +64,31 @@
         # Cython does not work on CPython as well...
         assert exc.traceback.tb_lineno == 42 # should be 48
         assert frame.f_lineno == 42
+
+    def test_traceback_check(self):
+        module = self.import_extension('foo', [
+            ("traceback_check", "METH_NOARGS",
+             """
+                 int check;
+                 PyObject *type, *value, *tb;
+                 PyObject *ret = PyRun_String("XXX", Py_eval_input, 
+                                              Py_None, Py_None);
+                 if (ret) {
+                     Py_DECREF(ret);
+                     PyErr_SetString(PyExc_AssertionError, "should raise");
+                     return NULL;
+                 }
+                 PyErr_Fetch(&type, &value, &tb);
+                 check = PyTraceBack_Check(tb);
+                 Py_XDECREF(type);
+                 Py_XDECREF(value);
+                 Py_XDECREF(tb);
+                 if (check) {
+                     Py_RETURN_TRUE;
+                 }
+                 else {
+                     Py_RETURN_FALSE;
+                 }
+             """),
+            ])
+        assert module.traceback_check()
diff --git a/pypy/module/cpyext/test/test_funcobject.py b/pypy/module/cpyext/test/test_funcobject.py
--- a/pypy/module/cpyext/test/test_funcobject.py
+++ b/pypy/module/cpyext/test/test_funcobject.py
@@ -44,3 +44,19 @@
         assert w_code.co_firstlineno == 3
         rffi.free_charp(filename)
         rffi.free_charp(funcname)
+
+    def test_classmethod(self, space, api):
+        w_function = space.appexec([], """():
+            def method(x): return x
+            return method
+        """)
+        w_class = space.call_function(space.w_type, space.wrap("C"),
+                                      space.newtuple([]), space.newdict())
+        w_instance = space.call_function(w_class)
+        # regular instance method
+        space.setattr(w_class, space.wrap("method"), w_function)
+        assert space.is_w(space.call_method(w_instance, "method"), w_instance)
+        # now a classmethod
+        w_classmethod = api.PyClassMethod_New(w_function)
+        space.setattr(w_class, space.wrap("classmethod"), w_classmethod)
+        assert space.is_w(space.call_method(w_instance, "classmethod"), w_class)
diff --git a/pypy/module/cpyext/test/test_intobject.py b/pypy/module/cpyext/test/test_intobject.py
--- a/pypy/module/cpyext/test/test_intobject.py
+++ b/pypy/module/cpyext/test/test_intobject.py
@@ -50,3 +50,19 @@
             ])
         assert module.from_string() == 0x1234
         assert type(module.from_string()) is int
+
+    def test_size_t(self):
+        module = self.import_extension('foo', [
+            ("values", "METH_NOARGS",
+             """
+                 return Py_BuildValue("NNNN",
+                     PyInt_FromSize_t(123),
+                     PyInt_FromSize_t((size_t)-1),
+                     PyInt_FromSsize_t(123),
+                     PyInt_FromSsize_t((size_t)-1));
+             """),
+            ])
+        values = module.values()
+        types = [type(x) for x in values]
+        assert types == [int, long, int, int]
+        
diff --git a/pypy/module/cpyext/test/test_number.py b/pypy/module/cpyext/test/test_number.py
--- a/pypy/module/cpyext/test/test_number.py
+++ b/pypy/module/cpyext/test/test_number.py
@@ -25,6 +25,15 @@
         assert api.PyInt_CheckExact(w_l)
         w_l = api.PyNumber_Int(space.wrap(2 << 65))
         assert api.PyLong_CheckExact(w_l)
+        w_l = api.PyNumber_Int(space.wrap(42.3))
+        assert api.PyInt_CheckExact(w_l)
+
+    def test_number_index(self, space, api):
+        w_l = api.PyNumber_Index(space.wrap(123L))
+        assert api.PyLong_CheckExact(w_l)
+        w_l = api.PyNumber_Index(space.wrap(42.3))
+        assert w_l is None
+        api.PyErr_Clear()
 
     def test_numbermethods(self, space, api):
         assert "ab" == space.unwrap(
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
@@ -283,3 +283,7 @@
         self.raises(space, api, TypeError, api.PyString_AsEncodedObject,
             space.wrap(2), lltype.nullptr(rffi.CCHARP.TO), lltype.nullptr(rffi.CCHARP.TO)
         )
+
+    def test_eq(self, space, api):
+        assert 1 == api._PyString_Eq(space.wrap("hello"), space.wrap("hello"))
+        assert 0 == api._PyString_Eq(space.wrap("hello"), space.wrap("world"))
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
@@ -22,12 +22,13 @@
                  Py_RETURN_NONE;
              """)])
         import sys, StringIO
+        prev = sys.stdout
         sys.stdout = StringIO.StringIO()
         try:
             module.writestdout()
             assert sys.stdout.getvalue() == "format: 42\n"
         finally:
-            sys.stdout = sys.__stdout__
+            sys.stdout = prev
 
 class TestSysModule(BaseApiTest):
     def test_sysmodule(self, space, api):
diff --git a/pypy/module/cpyext/test/test_tupleobject.py b/pypy/module/cpyext/test/test_tupleobject.py
--- a/pypy/module/cpyext/test/test_tupleobject.py
+++ b/pypy/module/cpyext/test/test_tupleobject.py
@@ -3,8 +3,10 @@
 from pypy.module.cpyext.pyobject import PyObject, PyObjectP, make_ref, from_ref
 from pypy.module.cpyext.test.test_api import BaseApiTest
 from pypy.rpython.lltypesystem import rffi, lltype
+from pypy.conftest import gettestobjspace
 
 class TestTupleObject(BaseApiTest):
+
     def test_tupleobject(self, space, api):
         assert not api.PyTuple_Check(space.w_None)
         assert api.PyTuple_SetItem(space.w_None, 0, space.w_None) == -1
@@ -20,11 +22,29 @@
         ar[0] = rffi.cast(PyObject, make_ref(space, py_tuple))
         api._PyTuple_Resize(ar, 2)
         py_tuple = from_ref(space, ar[0])
-        assert len(py_tuple.wrappeditems) == 2
+        assert space.int_w(space.len(py_tuple)) == 2
         
         api._PyTuple_Resize(ar, 10)
         py_tuple = from_ref(space, ar[0])
-        assert len(py_tuple.wrappeditems) == 10
+        assert space.int_w(space.len(py_tuple)) == 10
         
         api.Py_DecRef(ar[0])
         lltype.free(ar, flavor='raw')
+
+    def test_setitem(self, space, api):
+        atuple = space.newtuple([space.wrap(0), space.wrap("hello")])
+        assert api.PyTuple_Size(atuple) == 2
+        assert space.eq_w(space.getitem(atuple, space.wrap(0)), space.wrap(0))
+        assert space.eq_w(space.getitem(atuple, space.wrap(1)), space.wrap("hello"))
+        w_obj = space.wrap(1)
+        api.Py_IncRef(w_obj)
+        api.PyTuple_SetItem(atuple, 1, w_obj)
+        assert api.PyTuple_Size(atuple) == 2
+        assert space.eq_w(space.getitem(atuple, space.wrap(0)), space.wrap(0))
+        assert space.eq_w(space.getitem(atuple, space.wrap(1)), space.wrap(1))
+
+    def test_getslice(self, space, api):
+        w_tuple = space.newtuple([space.wrap(i) for i in range(10)])
+        w_slice = api.PyTuple_GetSlice(w_tuple, 3, -3)
+        assert space.eq_w(w_slice,
+                          space.newtuple([space.wrap(i) for i in range(3, 7)]))
diff --git a/pypy/module/cpyext/tupleobject.py b/pypy/module/cpyext/tupleobject.py
--- a/pypy/module/cpyext/tupleobject.py
+++ b/pypy/module/cpyext/tupleobject.py
@@ -6,7 +6,7 @@
     borrow_from, make_ref, from_ref)
 from pypy.module.cpyext.pyerrors import PyErr_BadInternalCall
 from pypy.objspace.std.tupleobject import W_TupleObject
-
+from pypy.objspace.std.smalltupleobject import W_SmallTupleObject
 
 PyTuple_Check, PyTuple_CheckExact = build_type_checkers("Tuple")
 
@@ -19,25 +19,30 @@
     if not PyTuple_Check(space, w_t):
         # XXX this should also steal a reference, test it!!!
         PyErr_BadInternalCall(space)
-    assert isinstance(w_t, W_TupleObject)
-    w_t.wrappeditems[pos] = w_obj
+    _setitem_tuple(w_t, pos, w_obj)
     Py_DecRef(space, w_obj) # SetItem steals a reference!
     return 0
 
+def _setitem_tuple(w_t, pos, w_obj):
+    if isinstance(w_t, W_TupleObject):
+        w_t.wrappeditems[pos] = w_obj
+    elif isinstance(w_t, W_SmallTupleObject):
+        w_t.setitem(pos, w_obj)
+    else:
+        assert False
+
 @cpython_api([PyObject, Py_ssize_t], PyObject)
 def PyTuple_GetItem(space, w_t, pos):
     if not PyTuple_Check(space, w_t):
         PyErr_BadInternalCall(space)
-    assert isinstance(w_t, W_TupleObject)
-    w_obj = w_t.wrappeditems[pos]
+    w_obj = space.getitem(w_t, space.wrap(pos))
     return borrow_from(w_t, w_obj)
 
 @cpython_api([PyObject], Py_ssize_t, error=CANNOT_FAIL)
 def PyTuple_GET_SIZE(space, w_t):
     """Return the size of the tuple p, which must be non-NULL and point to a tuple;
     no error checking is performed. """
-    assert isinstance(w_t, W_TupleObject)
-    return len(w_t.wrappeditems)
+    return space.int_w(space.len(w_t))
 
 @cpython_api([PyObject], Py_ssize_t, error=-1)
 def PyTuple_Size(space, ref):
@@ -63,15 +68,21 @@
     py_tuple = from_ref(space, ref[0])
     if not PyTuple_Check(space, py_tuple):
         PyErr_BadInternalCall(space)
-    assert isinstance(py_tuple, W_TupleObject)
     py_newtuple = PyTuple_New(space, newsize)
     
     to_cp = newsize
-    oldsize = len(py_tuple.wrappeditems)
+    oldsize = space.int_w(space.len(py_tuple))
     if oldsize < newsize:
         to_cp = oldsize
     for i in range(to_cp):
-        py_newtuple.wrappeditems[i] = py_tuple.wrappeditems[i]
+        _setitem_tuple(py_newtuple, i, space.getitem(py_tuple, space.wrap(i)))
     Py_DecRef(space, ref[0])
     ref[0] = make_ref(space, py_newtuple)
     return 0
+
+ at cpython_api([PyObject, Py_ssize_t, Py_ssize_t], PyObject)
+def PyTuple_GetSlice(space, w_obj, low, high):
+    """Take a slice of the tuple pointed to by p from low to high and return it
+    as a new tuple.
+    """
+    return space.getslice(w_obj, space.wrap(low), space.wrap(high))
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
@@ -650,3 +650,13 @@
     name = space.str_w(w_name)
     w_obj = w_type.lookup(name)
     return borrow_from(w_type, w_obj)
+
+ at cpython_api([PyTypeObjectPtr], lltype.Void)
+def PyType_Modified(space, w_obj):
+    """Invalidate the internal lookup cache for the type and all of its
+    subtypes.  This function must be called after any manual
+    modification of the attributes or base classes of the type.
+    """
+    # PyPy already takes care of direct modifications to type.__dict__
+    # (which is a W_DictProxyObject).
+    pass
diff --git a/pypy/module/micronumpy/__init__.py b/pypy/module/micronumpy/__init__.py
--- a/pypy/module/micronumpy/__init__.py
+++ b/pypy/module/micronumpy/__init__.py
@@ -1,13 +1,23 @@
 
-from pypy.interpreter.mixedmodule import MixedModule 
+from pypy.interpreter.mixedmodule import MixedModule
 
 class Module(MixedModule):
 
     applevel_name = 'numpy'
-    
+
     interpleveldefs = {
-        'zeros'    : 'numarray.zeros',
-        'minimum'  : 'ufunc.minimum',
-        }
+        'array': 'interp_numarray.SingleDimArray',
+        'zeros': 'interp_numarray.zeros',
+
+        # ufuncs
+        'absolute': 'interp_ufuncs.absolute',
+        'copysign': 'interp_ufuncs.copysign',
+        'exp': 'interp_ufuncs.exp',
+        'maximum': 'interp_ufuncs.maximum',
+        'minimum': 'interp_ufuncs.minimum',
+        'negative': 'interp_ufuncs.negative',
+        'reciprocal': 'interp_ufuncs.reciprocal',
+        'sign': 'interp_ufuncs.sign',
+    }
 
     appleveldefs = {}
diff --git a/pypy/module/micronumpy/bench/add.py b/pypy/module/micronumpy/bench/add.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/micronumpy/bench/add.py
@@ -0,0 +1,10 @@
+
+import numpy
+
+def f():
+    a = numpy.zeros(10000000)
+    a = a + a + a + a + a
+    # To ensure that the computation isn't totally optimized away.
+    a[0] = 3.0
+
+f()
diff --git a/pypy/module/micronumpy/bench/iterate.py b/pypy/module/micronumpy/bench/iterate.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/micronumpy/bench/iterate.py
@@ -0,0 +1,11 @@
+
+import numpy
+
+def f():
+    sum = 0
+    a = numpy.zeros(10000000)
+    for i in range(10000000):
+        sum += a[i]
+    return sum
+
+f()
diff --git a/pypy/module/micronumpy/interp_numarray.py b/pypy/module/micronumpy/interp_numarray.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/micronumpy/interp_numarray.py
@@ -0,0 +1,257 @@
+from pypy.interpreter.baseobjspace import ObjSpace, W_Root, Wrappable
+from pypy.interpreter.error import operationerrfmt
+from pypy.interpreter.gateway import interp2app, unwrap_spec
+from pypy.interpreter.typedef import TypeDef
+from pypy.rlib import jit
+from pypy.rpython.lltypesystem import lltype
+from pypy.tool.sourcetools import func_with_new_name
+
+
+def dummy1(v):
+    assert isinstance(v, float)
+    return v
+
+def dummy2(v):
+    assert isinstance(v, float)
+    return v
+
+TP = lltype.Array(lltype.Float, hints={'nolength': True})
+
+numpy_driver = jit.JitDriver(greens = ['signature'],
+                             reds = ['result_size', 'i', 'self', 'result'])
+
+class Signature(object):
+    def __init__(self):
+        self.transitions = {}
+
+    def transition(self, target):
+        if target in self.transitions:
+            return self.transitions[target]
+        self.transitions[target] = new = Signature()
+        return new
+
+def add(v1, v2):
+    return v1 + v2
+def sub(v1, v2):
+    return v1 - v2
+def mul(v1, v2):
+    return v1 * v2
+def div(v1, v2):
+    return v1 / v2
+
+class BaseArray(Wrappable):
+    def __init__(self):
+        self.invalidates = []
+
+    def invalidated(self):
+        for arr in self.invalidates:
+            arr.force_if_needed()
+        self.invalidates = []
+
+    def _binop_impl(function):
+        signature = Signature()
+        def impl(self, space, w_other):
+            new_sig = self.signature.transition(signature)
+            if isinstance(w_other, BaseArray):
+                res = Call2(
+                    function,
+                    self,
+                    w_other,
+                    new_sig.transition(w_other.signature)
+                )
+                w_other.invalidates.append(res)
+            else:
+                w_other = FloatWrapper(space.float_w(w_other))
+                res = Call2(
+                    function,
+                    self,
+                    w_other,
+                    new_sig.transition(w_other.signature)
+                )
+            self.invalidates.append(res)
+            return space.wrap(res)
+        return func_with_new_name(impl, "binop_%s_impl" % function.__name__)
+
+    descr_add = _binop_impl(add)
+    descr_sub = _binop_impl(sub)
+    descr_mul = _binop_impl(mul)
+    descr_div = _binop_impl(div)
+
+    def get_concrete(self):
+        raise NotImplementedError
+
+    def descr_len(self, space):
+        return self.get_concrete().descr_len(space)
+
+    @unwrap_spec(item=int)
+    def descr_getitem(self, space, item):
+        return self.get_concrete().descr_getitem(space, item)
+
+    @unwrap_spec(item=int, value=float)
+    def descr_setitem(self, space, item, value):
+        self.invalidated()
+        return self.get_concrete().descr_setitem(space, item, value)
+
+
+class FloatWrapper(BaseArray):
+    """
+    Intermediate class representing a float literal.
+    """
+    _immutable_fields_ = ["float_value"]
+    signature = Signature()
+
+    def __init__(self, float_value):
+        BaseArray.__init__(self)
+        self.float_value = float_value
+
+    def find_size(self):
+        raise ValueError
+
+    def eval(self, i):
+        return self.float_value
+
+class VirtualArray(BaseArray):
+    """
+    Class for representing virtual arrays, such as binary ops or ufuncs
+    """
+    def __init__(self, signature):
+        BaseArray.__init__(self)
+        self.forced_result = None
+        self.signature = signature
+
+    def compute(self):
+        i = 0
+        signature = self.signature
+        result_size = self.find_size()
+        result = SingleDimArray(result_size)
+        while i < result_size:
+            numpy_driver.jit_merge_point(signature=signature,
+                                         result_size=result_size, i=i,
+                                         self=self, result=result)
+            result.storage[i] = self.eval(i)
+            i += 1
+        return result
+
+    def force_if_needed(self):
+        if self.forced_result is None:
+            self.forced_result = self.compute()
+
+    def get_concrete(self):
+        self.force_if_needed()
+        return self.forced_result
+
+    def eval(self, i):
+        if self.forced_result is not None:
+            return self.forced_result.eval(i)
+        return self._eval(i)
+
+class Call1(VirtualArray):
+    _immutable_fields_ = ["function", "values"]
+
+    def __init__(self, function, values, signature):
+        VirtualArray.__init__(self, signature)
+        self.function = function
+        self.values = values
+
+    def find_size(self):
+        return self.values.find_size()
+
+    def _eval(self, i):
+        return self.function(self.values.eval(i))
+
+class Call2(VirtualArray):
+    """
+    Intermediate class for performing binary operations.
+    """
+    _immutable_fields_ = ["function", "left", "right"]
+    def __init__(self, function, left, right, signature):
+        VirtualArray.__init__(self, signature)
+        self.function = function
+        self.left = left
+        self.right = right
+
+    def find_size(self):
+        try:
+            return self.left.find_size()
+        except ValueError:
+            pass
+        return self.right.find_size()
+
+    def _eval(self, i):
+        lhs, rhs = self.left.eval(i), self.right.eval(i)
+        return self.function(lhs, rhs)
+
+
+class SingleDimArray(BaseArray):
+    signature = Signature()
+
+    def __init__(self, size):
+        BaseArray.__init__(self)
+        self.size = size
+        self.storage = lltype.malloc(TP, size, zero=True,
+                                     flavor='raw', track_allocation=False)
+        # XXX find out why test_zjit explodes with trackign of allocations
+
+    def get_concrete(self):
+        return self
+
+    def find_size(self):
+        return self.size
+
+    def eval(self, i):
+        return self.storage[i]
+
+    def getindex(self, space, item):
+        if item >= self.size:
+            raise operationerrfmt(space.w_IndexError,
+              '%d above array size', item)
+        if item < 0:
+            item += self.size
+        if item < 0:
+            raise operationerrfmt(space.w_IndexError,
+              '%d below zero', item)
+        return item
+
+    def descr_len(self, space):
+        return space.wrap(self.size)
+
+    @unwrap_spec(item=int)
+    def descr_getitem(self, space, item):
+        item = self.getindex(space, item)
+        return space.wrap(self.storage[item])
+
+    @unwrap_spec(item=int, value=float)
+    def descr_setitem(self, space, item, value):
+        item = self.getindex(space, item)
+        self.invalidated()
+        self.storage[item] = value
+
+    def __del__(self):
+        lltype.free(self.storage, flavor='raw')
+
+def descr_new_numarray(space, w_type, w_size_or_iterable):
+    l = space.listview(w_size_or_iterable)
+    arr = SingleDimArray(len(l))
+    i = 0
+    for w_elem in l:
+        arr.storage[i] = space.float_w(space.float(w_elem))
+        i += 1
+    return space.wrap(arr)
+
+ at unwrap_spec(ObjSpace, int)
+def zeros(space, size):
+    return space.wrap(SingleDimArray(size))
+
+
+BaseArray.typedef = TypeDef(
+    'numarray',
+    __new__ = interp2app(descr_new_numarray),
+    __len__ = interp2app(BaseArray.descr_len),
+    __getitem__ = interp2app(BaseArray.descr_getitem),
+    __setitem__ = interp2app(BaseArray.descr_setitem),
+
+    __add__ = interp2app(BaseArray.descr_add),
+    __sub__ = interp2app(BaseArray.descr_sub),
+    __mul__ = interp2app(BaseArray.descr_mul),
+    __div__ = interp2app(BaseArray.descr_div),
+)
\ No newline at end of file
diff --git a/pypy/module/micronumpy/interp_ufuncs.py b/pypy/module/micronumpy/interp_ufuncs.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/micronumpy/interp_ufuncs.py
@@ -0,0 +1,66 @@
+import math
+
+from pypy.interpreter.gateway import unwrap_spec
+from pypy.module.micronumpy.interp_numarray import BaseArray, Call1, Call2, Signature
+from pypy.rlib import rfloat
+from pypy.tool.sourcetools import func_with_new_name
+
+
+def ufunc(func):
+    signature = Signature()
+    @unwrap_spec(array=BaseArray)
+    def impl(space, array):
+        w_res = Call1(func, array, array.signature.transition(signature))
+        array.invalidates.append(w_res)
+        return w_res
+    return func_with_new_name(impl, "%s_dispatcher" % func.__name__)
+
+def ufunc2(func):
+    signature = Signature()
+    @unwrap_spec(larray=BaseArray, rarray=BaseArray)
+    def impl(space, larray, rarray):
+        new_sig = larray.signature.transition(signature).transition(rarray.signature)
+        w_res = Call2(func, larray, rarray, new_sig)
+        larray.invalidates.append(w_res)
+        rarray.invalidates.append(w_res)
+        return w_res
+    return func_with_new_name(impl, "%s_dispatcher" % func.__name__)
+
+ at ufunc
+def absolute(value):
+    return abs(value)
+
+ at ufunc2
+def copysign(lvalue, rvalue):
+    return rfloat.copysign(lvalue, rvalue)
+
+ at ufunc
+def exp(value):
+    try:
+        return math.exp(value)
+    except OverflowError:
+        return rfloat.INFINITY
+
+ at ufunc2
+def maximum(lvalue, rvalue):
+    return max(lvalue, rvalue)
+
+ at ufunc2
+def minimum(lvalue, rvalue):
+    return min(lvalue, rvalue)
+
+ at ufunc
+def negative(value):
+    return -value
+
+ at ufunc
+def reciprocal(value):
+    if value == 0.0:
+        return rfloat.copysign(rfloat.INFINITY, value)
+    return 1.0 / value
+
+ at ufunc
+def sign(value):
+    if value == 0.0:
+        return 0.0
+    return rfloat.copysign(1.0, value)
diff --git a/pypy/module/micronumpy/numarray.py b/pypy/module/micronumpy/numarray.py
deleted file mode 100644
--- a/pypy/module/micronumpy/numarray.py
+++ /dev/null
@@ -1,123 +0,0 @@
-
-from pypy.interpreter.baseobjspace import Wrappable
-from pypy.interpreter.error import OperationError
-from pypy.interpreter.typedef import TypeDef
-from pypy.interpreter.gateway import interp2app, unwrap_spec, NoneNotWrapped
-from pypy.rlib.debug import make_sure_not_resized
-
-class BaseNumArray(Wrappable):
-    pass
-
-class NumArray(BaseNumArray):
-    def __init__(self, space, dim, dtype):
-        self.dim = dim
-        self.space = space
-        # ignore dtype for now
-        self.storage = [0] * dim
-        make_sure_not_resized(self.storage)
-
-    @unwrap_spec(index=int)
-    def descr_getitem(self, index):
-        space = self.space
-        try:
-            return space.wrap(self.storage[index])
-        except IndexError:
-            raise OperationError(space.w_IndexError,
-                                 space.wrap("list index out of range"))
-
-    @unwrap_spec(index=int, value=int)
-    def descr_setitem(self, index, value):
-        space = self.space
-        try:
-            self.storage[index] = value
-        except IndexError:
-            raise OperationError(space.w_IndexError,
-                                 space.wrap("list index out of range"))
-        return space.w_None
-
-    def descr_len(self):
-        return self.space.wrap(len(self.storage))
-
-NumArray.typedef = TypeDef(
-    'NumArray',
-    __getitem__ = interp2app(NumArray.descr_getitem),
-    __setitem__ = interp2app(NumArray.descr_setitem),
-    __len__     = interp2app(NumArray.descr_len),
-)
-
-def compute_pos(space, indexes, dim):
-    current = 1
-    pos = 0
-    for i in range(len(indexes)):
-        index = indexes[i]
-        d = dim[i]
-        if index >= d or index <= -d - 1:
-            raise OperationError(space.w_IndexError,
-                                 space.wrap("invalid index"))
-        if index < 0:
-            index = d + index
-        pos += index * current
-        current *= d
-    return pos
-
-class MultiDimArray(BaseNumArray):
-    def __init__(self, space, dim, dtype):
-        self.dim = dim
-        self.space = space
-        # ignore dtype for now
-        size = 1
-        for el in dim:
-            size *= el
-        self.storage = [0] * size
-        make_sure_not_resized(self.storage)
-
-    def _unpack_indexes(self, space, w_index):
-        indexes = [space.int_w(w_i) for w_i in space.fixedview(w_index)]
-        if len(indexes) != len(self.dim):
-            raise OperationError(space.w_IndexError, space.wrap(
-                'Wrong index'))
-        return indexes
-
-    def descr_getitem(self, w_index):
-        space = self.space
-        indexes = self._unpack_indexes(space, w_index)
-        pos = compute_pos(space, indexes, self.dim)
-        return space.wrap(self.storage[pos])
-
-    @unwrap_spec(value=int)
-    def descr_setitem(self, w_index, value):
-        space = self.space
-        indexes = self._unpack_indexes(space, w_index)
-        pos = compute_pos(space, indexes, self.dim)
-        self.storage[pos] = value
-        return space.w_None
-
-    def descr_len(self):
-        return self.space.wrap(self.dim[0])
-
-MultiDimArray.typedef = TypeDef(
-    'NumArray',
-    __getitem__ = interp2app(MultiDimArray.descr_getitem),
-    __setitem__ = interp2app(MultiDimArray.descr_setitem),
-    __len__     = interp2app(MultiDimArray.descr_len),
-)
-
-def unpack_dim(space, w_dim):
-    if space.is_true(space.isinstance(w_dim, space.w_int)):
-        return [space.int_w(w_dim)]
-    dim_w = space.fixedview(w_dim)
-    return [space.int_w(w_i) for w_i in dim_w]
-
-def unpack_dtype(space, w_dtype):
-    if space.is_w(w_dtype, space.w_int):
-        return 'i'
-    else:
-        raise NotImplementedError
-
-def zeros(space, w_dim, w_dtype):
-    dim = unpack_dim(space, w_dim)
-    dtype = unpack_dtype(space, w_dtype)
-    if len(dim) == 1:
-        return space.wrap(NumArray(space, dim[0], dtype))
-    else:
-        return space.wrap(MultiDimArray(space, dim, dtype))
diff --git a/pypy/module/micronumpy/test/test_base.py b/pypy/module/micronumpy/test/test_base.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/micronumpy/test/test_base.py
@@ -0,0 +1,19 @@
+from pypy.conftest import gettestobjspace
+from pypy.module.micronumpy.interp_numarray import SingleDimArray, FloatWrapper
+
+
+class BaseNumpyAppTest(object):
+    def setup_class(cls):
+        cls.space = gettestobjspace(usemodules=('micronumpy',))
+
+
+class TestSignature(object):
+    def test_binop_signature(self, space):
+        ar = SingleDimArray(10)
+        v1 = ar.descr_add(space, ar)
+        v2 = ar.descr_add(space, FloatWrapper(2.0))
+        assert v1.signature is not v2.signature
+        v3 = ar.descr_add(space, FloatWrapper(1.0))
+        assert v2.signature is v3.signature
+        v4 = ar.descr_add(space, ar)
+        assert v1.signature is v4.signature
\ No newline at end of file
diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/micronumpy/test/test_numarray.py
@@ -0,0 +1,141 @@
+import py
+
+from pypy.module.micronumpy.test.test_base import BaseNumpyAppTest
+
+
+class AppTestNumArray(BaseNumpyAppTest):
+    def test_type(self):
+        from numpy import array
+        ar = array(range(5))
+        assert type(ar) is type(ar + ar)
+
+    def test_init(self):
+        from numpy import zeros
+        a = zeros(15)
+        # Check that storage was actually zero'd.
+        assert a[10] == 0.0
+        # And check that changes stick.
+        a[13] = 5.3
+        assert a[13] == 5.3
+
+    def test_iterator_init(self):
+        from numpy import array
+        a = array(range(5))
+        assert a[3] == 3
+
+    def test_getitem(self):
+        from numpy import array
+        a = array(range(5))
+        raises(IndexError, "a[5]")
+        a = a + a
+        raises(IndexError, "a[5]")
+        assert a[-1] == 8
+        raises(IndexError, "a[-6]")
+
+    def test_setitem(self):
+        from numpy import array
+        a = array(range(5))
+        a[-1] = 5.0
+        assert a[4] == 5.0
+        raises(IndexError, "a[5] = 0.0")
+        raises(IndexError, "a[-6] = 3.0")
+
+    def test_len(self):
+        from numpy import array
+        a = array(range(5))
+        assert len(a) == 5
+        assert len(a + a) == 5
+
+    def test_add(self):
+        from numpy import array
+        a = array(range(5))
+        b = a + a
+        for i in range(5):
+            assert b[i] == i + i
+
+    def test_add_other(self):
+        from numpy import array
+        a = array(range(5))
+        b = array(reversed(range(5)))
+        c = a + b
+        for i in range(5):
+            assert c[i] == 4
+
+    def test_add_constant(self):
+        from numpy import array
+        a = array(range(5))
+        b = a + 5
+        for i in range(5):
+            assert b[i] == i + 5
+
+    def test_subtract(self):
+        from numpy import array
+        a = array(range(5))
+        b = a - a
+        for i in range(5):
+            assert b[i] == 0
+
+    def test_subtract_other(self):
+        from numpy import array
+        a = array(range(5))
+        b = array([1, 1, 1, 1, 1])
+        c = a - b
+        for i in range(5):
+            assert c[i] == i - 1
+
+    def test_subtract_constant(self):
+        from numpy import array
+        a = array(range(5))
+        b = a - 5
+        for i in range(5):
+            assert b[i] == i - 5
+
+    def test_mul(self):
+        from numpy import array
+        a = array(range(5))
+        b = a * a
+        for i in range(5):
+            assert b[i] == i * i
+
+    def test_mul_constant(self):
+        from numpy import array
+        a = array(range(5))
+        b = a * 5
+        for i in range(5):
+            assert b[i] == i * 5
+
+    def test_div(self):
+        from numpy import array
+        a = array(range(1, 6))
+        b = a / a
+        for i in range(5):
+            assert b[i] == 1
+
+    def test_div_other(self):
+        from numpy import array
+        a = array(range(5))
+        b = array([2, 2, 2, 2, 2])
+        c = a / b
+        for i in range(5):
+            assert c[i] == i / 2.0
+
+    def test_div_constant(self):
+        from numpy import array
+        a = array(range(5))
+        b = a / 5.0
+        for i in range(5):
+            assert b[i] == i / 5.0
+
+    def test_auto_force(self):
+        from numpy import array
+        a = array(range(5))
+        b = a - 1
+        a[2] = 3
+        for i in range(5):
+            assert b[i] == i - 1
+
+        a = array(range(5))
+        b = a + a
+        c = b + b
+        b[1] = 5
+        assert c[1] == 4
\ No newline at end of file
diff --git a/pypy/module/micronumpy/test/test_numpy.py b/pypy/module/micronumpy/test/test_numpy.py
deleted file mode 100644
--- a/pypy/module/micronumpy/test/test_numpy.py
+++ /dev/null
@@ -1,65 +0,0 @@
-
-from pypy.conftest import gettestobjspace
-
-class AppTestNumpy(object):
-    def setup_class(cls):
-        cls.space = gettestobjspace(usemodules=('micronumpy',))
-    
-    def test_zeroes(self):
-        from numpy import zeros
-        ar = zeros(3, dtype=int)
-        assert ar[0] == 0
-    
-    def test_setitem_getitem(self):
-        from numpy import zeros
-        ar = zeros(8, dtype=int)
-        assert ar[0] == 0
-        ar[1] = 3
-        assert ar[1] == 3
-        raises((TypeError, ValueError), ar.__getitem__, 'xyz')
-        raises(IndexError, ar.__getitem__, 38)
-        assert ar[-2] == 0
-        assert ar[-7] == 3
-        assert len(ar) == 8
-
-    def test_minimum(self):
-        from numpy import zeros, minimum
-        ar = zeros(5, dtype=int)
-        ar2 = zeros(5, dtype=int)
-        ar[0] = 3
-        ar[1] = -3
-        ar[2] = 8
-        ar2[3] = -1
-        ar2[4] = 8
-        x = minimum(ar, ar2)
-        assert x[0] == 0
-        assert x[1] == -3
-        assert x[2] == 0
-        assert x[3] == -1
-        assert x[4] == 0
-        assert len(x) == 5
-        raises(ValueError, minimum, ar, zeros(3, dtype=int))
-
-class AppTestMultiDim(object):
-    def setup_class(cls):
-        cls.space = gettestobjspace(usemodules=('micronumpy',))
-
-    def test_multidim(self):
-        from numpy import zeros
-        ar = zeros((3, 3), dtype=int)
-        assert ar[0, 2] == 0
-        raises(IndexError, ar.__getitem__, (3, 0))
-        assert ar[-2, 1] == 0
-
-    def test_multidim_getset(self):
-        from numpy import zeros
-        ar = zeros((3, 3, 3), dtype=int)
-        ar[1, 2, 1] = 3
-        assert ar[1, 2, 1] == 3
-        assert ar[-2, 2, 1] == 3
-        assert ar[2, 2, 1] == 0
-        assert ar[-2, 2, -2] == 3
-
-    def test_len(self):
-        from numpy import zeros
-        assert len(zeros((3, 2, 1), dtype=int)) == 3
diff --git a/pypy/module/micronumpy/test/test_ufuncs.py b/pypy/module/micronumpy/test/test_ufuncs.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/micronumpy/test/test_ufuncs.py
@@ -0,0 +1,85 @@
+
+from pypy.module.micronumpy.test.test_base import BaseNumpyAppTest
+
+
+class AppTestUfuncs(BaseNumpyAppTest):
+    def test_negative(self):
+        from numpy import array, negative
+
+        a = array([-5.0, 0.0, 1.0])
+        b = negative(a)
+        for i in range(3):
+            assert b[i] == -a[i]
+
+        a = array([-5.0, 1.0])
+        b = negative(a)
+        a[0] = 5.0
+        assert b[0] == 5.0
+
+    def test_abs(self):
+        from numpy import array, absolute
+
+        a = array([-5.0, -0.0, 1.0])
+        b = absolute(a)
+        for i in range(3):
+            assert b[i] == abs(a[i])
+
+    def test_minimum(self):
+        from numpy import array, minimum
+
+        a = array([-5.0, -0.0, 1.0])
+        b = array([ 3.0, -2.0,-3.0])
+        c = minimum(a, b)
+        for i in range(3):
+            assert c[i] == min(a[i], b[i])
+
+    def test_maximum(self):
+        from numpy import array, maximum
+
+        a = array([-5.0, -0.0, 1.0])
+        b = array([ 3.0, -2.0,-3.0])
+        c = maximum(a, b)
+        for i in range(3):
+            assert c[i] == max(a[i], b[i])
+
+    def test_sign(self):
+        from numpy import array, sign
+
+        reference = [-1.0, 0.0, 0.0, 1.0]
+        a = array([-5.0, -0.0, 0.0, 6.0])
+        b = sign(a)
+        for i in range(4):
+            assert b[i] == reference[i]
+
+    def test_reciporocal(self):
+        from numpy import array, reciprocal
+
+        reference = [-0.2, float("inf"), float("-inf"), 2.0]
+        a = array([-5.0, 0.0, -0.0, 0.5])
+        b = reciprocal(a)
+        for i in range(4):
+            assert b[i] == reference[i]
+
+    def test_copysign(self):
+        from numpy import array, copysign
+
+        reference = [5.0, -0.0, 0.0, -6.0]
+        a = array([-5.0, 0.0, 0.0, 6.0])
+        b = array([5.0, -0.0, 3.0, -6.0])
+        c = copysign(a, b)
+        for i in range(4):
+            assert c[i] == reference[i]
+
+    def test_exp(self):
+        import math
+        from numpy import array, exp
+
+        a = array([-5.0, -0.0, 0.0, 12345678.0, float("inf"),
+                   -float('inf'), -12343424.0])
+        b = exp(a)
+        for i in range(4):
+            try:
+                res = math.exp(a[i])
+            except OverflowError:
+                res = float('inf')
+            assert b[i] == res
diff --git a/pypy/module/micronumpy/test/test_zjit.py b/pypy/module/micronumpy/test/test_zjit.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/micronumpy/test/test_zjit.py
@@ -0,0 +1,94 @@
+from pypy.jit.metainterp.test.support import LLJitMixin
+from pypy.module.micronumpy.interp_numarray import (SingleDimArray, Signature,
+    FloatWrapper, Call1, Call2, add, mul)
+from pypy.module.micronumpy.interp_ufuncs import negative
+
+
+class FakeSpace(object):
+    pass
+
+class TestNumpyJIt(LLJitMixin):
+    def setup_class(cls):
+        cls.space = FakeSpace()
+
+    def test_add(self):
+        space = self.space
+
+        def f(i):
+            ar = SingleDimArray(i)
+            v = Call2(add, ar, ar, Signature())
+            return v.get_concrete().storage[3]
+
+        result = self.meta_interp(f, [5], listops=True, backendopt=True)
+        self.check_loops({'getarrayitem_raw': 2, 'float_add': 1,
+                          'setarrayitem_raw': 1, 'int_add': 1,
+                          'int_lt': 1, 'guard_true': 1, 'jump': 1})
+        assert result == f(5)
+
+    def test_floatadd(self):
+        space = self.space
+
+        def f(i):
+            ar = SingleDimArray(i)
+            v = Call2(add, ar, FloatWrapper(4.5), Signature())
+            return v.get_concrete().storage[3]
+
+        result = self.meta_interp(f, [5], listops=True, backendopt=True)
+        self.check_loops({"getarrayitem_raw": 1, "float_add": 1,
+                          "setarrayitem_raw": 1, "int_add": 1,
+                          "int_lt": 1, "guard_true": 1, "jump": 1})
+        assert result == f(5)
+
+    def test_already_forecd(self):
+        space = self.space
+
+        def f(i):
+            ar = SingleDimArray(i)
+            v1 = Call2(add, ar, FloatWrapper(4.5), Signature())
+            v2 = Call2(mul, v1, FloatWrapper(4.5), Signature())
+            v1.force_if_needed()
+            return v2.get_concrete().storage[3]
+
+        result = self.meta_interp(f, [5], listops=True, backendopt=True)
+        # This is the sum of the ops for both loops, however if you remove the
+        # optimization then you end up with 2 float_adds, so we can still be
+        # sure it was optimized correctly.
+        self.check_loops({"getarrayitem_raw": 2, "float_mul": 1, "float_add": 1,
+                           "setarrayitem_raw": 2, "int_add": 2,
+                           "int_lt": 2, "guard_true": 2, "jump": 2})
+        assert result == f(5)
+
+    def test_ufunc(self):
+        space = self.space
+        def f(i):
+            ar = SingleDimArray(i)
+            v1 = Call2(add, ar, ar, Signature())
+            v2 = negative(space, v1)
+            return v2.get_concrete().storage[3]
+
+        result = self.meta_interp(f, [5], listops=True, backendopt=True)
+        self.check_loops({"getarrayitem_raw": 2, "float_add": 1, "float_neg": 1,
+                          "setarrayitem_raw": 1, "int_add": 1,
+                          "int_lt": 1, "guard_true": 1, "jump": 1,
+        })
+        assert result == f(5)
+
+    def test_appropriate_specialization(self):
+        space = self.space
+        def f(i):
+            add_sig = Signature()
+            mul_sig = Signature()
+            ar = SingleDimArray(i)
+
+            v1 = Call2(add, ar, ar, ar.signature.transition(add_sig))
+            v2 = negative(space, v1)
+            v2.get_concrete()
+
+            for i in xrange(5):
+                v1 = Call2(mul, ar, ar, ar.signature.transition(mul_sig))
+                v2 = negative(space, v1)
+                v2.get_concrete()
+
+        self.meta_interp(f, [5], listops=True, backendopt=True)
+        # This is 3, not 2 because there is a bridge for the exit.
+        self.check_loop_count(3)
\ No newline at end of file
diff --git a/pypy/module/micronumpy/ufunc.py b/pypy/module/micronumpy/ufunc.py
deleted file mode 100644
--- a/pypy/module/micronumpy/ufunc.py
+++ /dev/null
@@ -1,21 +0,0 @@
-
-from numarray import NumArray
-from pypy.interpreter.baseobjspace import ObjSpace, W_Root
-from pypy.interpreter.error import OperationError
-
-def minimum(space, w_a, w_b):
-    if not isinstance(w_a, NumArray) or not isinstance(w_b, NumArray):
-        raise OperationError(space.w_TypeError,
-                             space.wrap("expecting NumArrat object"))
-    if w_a.dim != w_b.dim:
-        raise OperationError(space.w_ValueError,
-                             space.wrap("minimum of arrays of different length"))
-    res = NumArray(space, w_a.dim, 'i')
-    for i in range(len(w_a.storage)):
-        one = w_a.storage[i]
-        two = w_b.storage[i]
-        if one < two:
-            res.storage[i] = one
-        else:
-            res.storage[i] = two
-    return space.wrap(res)
diff --git a/pypy/module/oracle/__init__.py b/pypy/module/oracle/__init__.py
--- a/pypy/module/oracle/__init__.py
+++ b/pypy/module/oracle/__init__.py
@@ -28,6 +28,7 @@
 
     appleveldefs = {
         'version': 'app_oracle.version',
+        'paramstyle': 'app_oracle.paramstyle',
         'makedsn': 'app_oracle.makedsn',
         'TimestampFromTicks': 'app_oracle.TimestampFromTicks',
     }
diff --git a/pypy/module/oracle/app_oracle.py b/pypy/module/oracle/app_oracle.py
--- a/pypy/module/oracle/app_oracle.py
+++ b/pypy/module/oracle/app_oracle.py
@@ -1,4 +1,5 @@
 version = '5.0.0'
+paramstyle = 'named'
 
 class Warning(StandardError):
     pass
diff --git a/pypy/module/oracle/config.py b/pypy/module/oracle/config.py
--- a/pypy/module/oracle/config.py
+++ b/pypy/module/oracle/config.py
@@ -16,6 +16,7 @@
         return space.str_w(w_obj)
 
     def w_string(space, buf, len=-1):
+        #assert type(len) is int
         if len < 0:
             return space.wrap(rffi.charp2str(buf))
         else:
diff --git a/pypy/module/oracle/interp_connect.py b/pypy/module/oracle/interp_connect.py
--- a/pypy/module/oracle/interp_connect.py
+++ b/pypy/module/oracle/interp_connect.py
@@ -159,9 +159,20 @@
         # set the internal and external names; these are needed for global
         # transactions but are limited in terms of the lengths of the strings
         if twophase:
-            raise OperationError(
-                interp_error.get(space).w_NotSupportedError,
-                space.wrap("XXX write me"))
+            status = roci.OCIAttrSet(
+                self.serverHandle, roci.OCI_HTYPE_SERVER,
+                "cx_Oracle", 0,
+                roci.OCI_ATTR_INTERNAL_NAME,
+                self.environment.errorHandle)
+            self.environment.checkForError(
+                status, "Connection_Connect(): set internal name")
+            status = roci.OCIAttrSet(
+                self.serverHandle, roci.OCI_HTYPE_SERVER,
+                "cx_Oracle", 0,
+                roci.OCI_ATTR_EXTERNAL_NAME,
+                self.environment.errorHandle)
+            self.environment.checkForError(
+                status, "Connection_Connect(): set external name")
 
         # allocate the session handle
         handleptr = lltype.malloc(rffi.CArrayPtr(roci.OCISession).TO,
@@ -371,6 +382,7 @@
         finally:
             stringBuffer.clear()
             lltype.free(foundptr, flavor='raw')
+            lltype.free(handleptr, flavor='raw')
 
         # eliminate the authorization handle immediately, if applicable
         if authInfo:
diff --git a/pypy/module/oracle/interp_cursor.py b/pypy/module/oracle/interp_cursor.py
--- a/pypy/module/oracle/interp_cursor.py
+++ b/pypy/module/oracle/interp_cursor.py
@@ -459,7 +459,7 @@
                 self.environment.checkForError(
                     status,
                     "Cursor_ItemDescription(): name")
-                name = rffi.charpsize2str(nameptr[0], lenptr[0])
+                name = rffi.charpsize2str(nameptr[0], rffi.cast(lltype.Signed, lenptr[0]))
             finally:
                 lltype.free(nameptr, flavor='raw')
                 lltype.free(lenptr, flavor='raw')
diff --git a/pypy/module/oracle/interp_object.py b/pypy/module/oracle/interp_object.py
--- a/pypy/module/oracle/interp_object.py
+++ b/pypy/module/oracle/interp_object.py
@@ -38,7 +38,7 @@
             self.environment.checkForError(
                 status,
                 "ObjectType_Initialize(): get schema name")
-            self.schema = rffi.charpsize2str(nameptr[0], lenptr[0])
+            self.schema = rffi.charpsize2str(nameptr[0], rffi.cast(lltype.Signed, lenptr[0]))
 
             # determine the name of the type
             status = roci.OCIAttrGet(
@@ -50,7 +50,7 @@
             self.environment.checkForError(
                 status,
                 "ObjectType_Initialize(): get schema name")
-            self.name = rffi.charpsize2str(nameptr[0], lenptr[0])
+            self.name = rffi.charpsize2str(nameptr[0], rffi.cast(lltype.Signed, lenptr[0]))
         finally:
             lltype.free(nameptr, flavor='raw')
             lltype.free(lenptr, flavor='raw')
@@ -301,7 +301,7 @@
             connection.environment.checkForError(
                 status,
                 "ObjectAttribute_Initialize(): get name")
-            self.name = rffi.charpsize2str(nameptr[0], lenptr[0])
+            self.name = rffi.charpsize2str(nameptr[0], rffi.cast(lltype.Signed, lenptr[0]))
         finally:
             lltype.free(nameptr, flavor='raw')
             lltype.free(lenptr, flavor='raw')
@@ -428,7 +428,7 @@
         strValue = rffi.cast(roci.Ptr(roci.OCIString), value)[0]
         ptr = roci.OCIStringPtr(environment.handle, strValue)
         size = roci.OCIStringSize(environment.handle, strValue)
-        return config.w_string(space, ptr, size)
+        return config.w_string(space, ptr, rffi.cast(lltype.Signed, size))
     elif typeCode == roci.OCI_TYPECODE_NUMBER:
         return transform.OracleNumberToPythonFloat(
             environment,
diff --git a/pypy/module/oracle/interp_pool.py b/pypy/module/oracle/interp_pool.py
--- a/pypy/module/oracle/interp_pool.py
+++ b/pypy/module/oracle/interp_pool.py
@@ -100,11 +100,13 @@
                 status, "SessionPool_New(): create pool")
 
             self.w_name = config.w_string(space, poolnameptr[0],
-                                          poolnamelenptr[0])
+                              rffi.cast(lltype.Signed, poolnamelenptr[0]))
         finally:
             user_buf.clear()
             password_buf.clear()
             dsn_buf.clear()
+            lltype.free(poolnameptr, flavor='raw')
+            lltype.free(poolnamelenptr, flavor='raw')
 
         return space.wrap(self)
 
@@ -128,10 +130,19 @@
 
         self.checkConnected(space)
 
+        if __args__.keywords:
+             keywords = __args__.keywords + ["pool"]
+        else:
+             keywords = ["pool"]
+        if __args__.keywords_w:
+             keywords_w = __args__.keywords_w + [space.wrap(self)]
+        else:
+             keywords_w = [space.wrap(self)]
+             
         newargs = Arguments(space,
                             __args__.arguments_w,
-                            __args__.keywords + ["pool"],
-                            __args__.keywords_w + [space.wrap(self)])
+                            keywords,
+                            keywords_w)
         return space.call_args(self.w_connectionType, newargs)
 
     def release(self, space, w_connection):
diff --git a/pypy/module/oracle/interp_variable.py b/pypy/module/oracle/interp_variable.py
--- a/pypy/module/oracle/interp_variable.py
+++ b/pypy/module/oracle/interp_variable.py
@@ -279,6 +279,7 @@
                     self.actualLength, self.returnCode,
                     allocatedElements, actualElementsPtr,
                     roci.OCI_DEFAULT)
+                nameBuffer.clear()
             else:
                 status = roci.OCIBindByPos(
                     self.boundCursorHandle, bindHandlePtr,
@@ -601,6 +602,7 @@
     def getValueProc(self, space, pos):
         ptr = rffi.ptradd(self.data, pos * self.bufferSize)
         length = rffi.cast(roci.Ptr(roci.ub4), ptr)[0]
+        length = rffi.cast(lltype.Signed, length)
 
         ptr = rffi.ptradd(ptr, rffi.sizeof(roci.ub4))
         return space.wrap(rffi.charpsize2str(ptr, length))
@@ -732,6 +734,7 @@
             finally:
                 rffi.keep_buffer_alive_until_here(textbuf, text)
                 lltype.free(sizeptr, flavor='raw')
+                format_buf.clear()
 
             if isinstance(self, VT_NumberAsString):
                 return w_strvalue
@@ -778,6 +781,8 @@
                 format_buf.ptr, format_buf.size,
                 None, 0,
                 dataptr)
+            text_buf.clear()
+            format_buf.clear()
             self.environment.checkForError(
                 status, "NumberVar_SetValue(): from long")
             return
@@ -810,6 +815,8 @@
                 format_buf.ptr, format_buf.size,
                 nls_params, len(nls_params),
                 dataptr)
+            text_buf.clear()
+            format_buf.clear()
             self.environment.checkForError(
                 status, "NumberVar_SetValue(): from decimal")
             return
diff --git a/pypy/module/oracle/roci.py b/pypy/module/oracle/roci.py
--- a/pypy/module/oracle/roci.py
+++ b/pypy/module/oracle/roci.py
@@ -73,7 +73,8 @@
     defines = '''
     OCI_ATTR_SERVER OCI_ATTR_SESSION OCI_ATTR_USERNAME OCI_ATTR_PASSWORD
     OCI_ATTR_STMT_TYPE OCI_ATTR_PARAM OCI_ATTR_PARAM_COUNT OCI_ATTR_ROW_COUNT
-    OCI_ATTR_NAME OCI_ATTR_SCALE OCI_ATTR_PRECISION OCI_ATTR_IS_NULL
+    OCI_ATTR_NAME OCI_ATTR_INTERNAL_NAME OCI_ATTR_EXTERNAL_NAME
+    OCI_ATTR_SCALE OCI_ATTR_PRECISION OCI_ATTR_IS_NULL
     OCI_ATTR_DATA_SIZE OCI_ATTR_DATA_TYPE OCI_ATTR_REF_TDO
     OCI_ATTR_SCHEMA_NAME OCI_ATTR_TYPE_NAME OCI_ATTR_TYPECODE
     OCI_ATTR_NUM_TYPE_ATTRS OCI_ATTR_LIST_TYPE_ATTRS
diff --git a/pypy/module/oracle/test/test_connect.py b/pypy/module/oracle/test/test_connect.py
--- a/pypy/module/oracle/test/test_connect.py
+++ b/pypy/module/oracle/test/test_connect.py
@@ -41,6 +41,10 @@
         if hasattr(self, 'cnx'):
             self.cnx.close()
 
+    def test_constants(self):
+        assert '.' in oracle.version
+        assert oracle.paramstyle == 'named'
+
     def test_connect(self):
         self.cnx = oracle.connect(self.username, self.password,
                                   self.tnsentry, threaded=True)
@@ -49,6 +53,13 @@
         assert self.cnx.tnsentry == self.tnsentry
         assert isinstance(self.cnx.version, str)
 
+    def test_connect_twophase(self):
+        self.cnx = oracle.connect(self.username, self.password,
+                                  self.tnsentry, twophase=True)
+        assert self.cnx.username == self.username
+        assert self.cnx.password == self.password
+        assert self.cnx.tnsentry == self.tnsentry
+
     def test_singleArg(self):
         self.cnx = oracle.connect("%s/%s@%s" % (self.username, self.password,
                                                 self.tnsentry))
diff --git a/pypy/module/pypyjit/__init__.py b/pypy/module/pypyjit/__init__.py
--- a/pypy/module/pypyjit/__init__.py
+++ b/pypy/module/pypyjit/__init__.py
@@ -7,13 +7,15 @@
     interpleveldefs = {
         'set_param':    'interp_jit.set_param',
         'residual_call': 'interp_jit.residual_call',
+        'set_compile_hook': 'interp_jit.set_compile_hook',
     }
 
     def setup_after_space_initialization(self):
         # force the __extend__ hacks to occur early
-        import pypy.module.pypyjit.interp_jit
+        from pypy.module.pypyjit.interp_jit import pypyjitdriver
         # add the 'defaults' attribute
         from pypy.rlib.jit import PARAMETERS
         space = self.space
+        pypyjitdriver.space = space
         w_obj = space.wrap(PARAMETERS)
         space.setattr(space.wrap(self), space.wrap('defaults'), w_obj)
diff --git a/pypy/module/pypyjit/interp_jit.py b/pypy/module/pypyjit/interp_jit.py
--- a/pypy/module/pypyjit/interp_jit.py
+++ b/pypy/module/pypyjit/interp_jit.py
@@ -12,6 +12,8 @@
 from pypy.interpreter.pycode import PyCode, CO_GENERATOR
 from pypy.interpreter.pyframe import PyFrame
 from pypy.interpreter.pyopcode import ExitFrame
+from pypy.interpreter.gateway import unwrap_spec
+from pypy.interpreter.baseobjspace import ObjSpace, W_Root
 from opcode import opmap
 from pypy.rlib.objectmodel import we_are_translated
 
@@ -49,13 +51,43 @@
     greens = ['next_instr', 'is_being_profiled', 'pycode']
     virtualizables = ['frame']
 
-##    def compute_invariants(self, reds, next_instr, pycode):
-##        # compute the information that really only depends on next_instr
-##        # and pycode
-##        frame = reds.frame
-##        valuestackdepth = frame.valuestackdepth
-##        blockstack = frame.blockstack
-##        return (valuestackdepth, blockstack)
+    def on_compile(self, logger, looptoken, operations, type, next_instr,
+                   is_being_profiled, ll_pycode):
+        from pypy.rpython.annlowlevel import cast_base_ptr_to_instance
+        
+        space = self.space
+        cache = space.fromcache(Cache)
+        if space.is_true(cache.w_compile_hook):
+            memo = {}
+            list_w = [space.wrap(logger.repr_of_resop(memo, op))
+                      for op in operations]
+            pycode = cast_base_ptr_to_instance(PyCode, ll_pycode)
+            try:
+                space.call_function(cache.w_compile_hook,
+                                    space.wrap('main'),
+                                    space.wrap(type),
+                                    space.newtuple([pycode,
+                                    space.wrap(next_instr),
+                                    space.wrap(is_being_profiled)]),
+                                    space.newlist(list_w))
+            except OperationError, e:
+                e.write_unraisable(space, "jit hook ", cache.w_compile_hook)
+
+    def on_compile_bridge(self, logger, orig_looptoken, operations, n):
+        space = self.space
+        cache = space.fromcache(Cache)
+        if space.is_true(cache.w_compile_hook):
+            memo = {}
+            list_w = [space.wrap(logger.repr_of_resop(memo, op))
+                      for op in operations]
+            try:
+                space.call_function(cache.w_compile_hook,
+                                    space.wrap('main'),
+                                    space.wrap('bridge'),
+                                    space.wrap(n),
+                                    space.newlist(list_w))
+            except OperationError, e:
+                e.write_unraisable(space, "jit hook ", cache.w_compile_hook)
 
 pypyjitdriver = PyPyJitDriver(get_printable_location = get_printable_location,
                               get_jitcell_at = get_jitcell_at,
@@ -157,3 +189,28 @@
     '''For testing.  Invokes callable(...), but without letting
     the JIT follow the call.'''
     return space.call_args(w_callable, __args__)
+
+class Cache(object):
+    def __init__(self, space):
+        self.w_compile_hook = space.w_None
+
+ at unwrap_spec(ObjSpace, W_Root)
+def set_compile_hook(space, w_hook):
+    """ set_compile_hook(hook)
+
+    Set a compiling hook that will be called each time a loop is compiled.
+    The hook will be called with the following signature:
+    hook(merge_point_type, loop_type, greenkey or guard_number, operations)
+
+    for now merge point type is always `main`
+
+    loop_type can be either `loop` `entry_bridge` or `bridge`
+    in case loop is not `bridge`, greenkey will be a set of constants
+    for jit merge point. in case it's `main` it'll be a tuple
+    (code, offset, is_being_profiled)
+
+    XXX write down what else
+    """
+    cache = space.fromcache(Cache)
+    cache.w_compile_hook = w_hook
+    return space.w_None
diff --git a/pypy/module/pypyjit/policy.py b/pypy/module/pypyjit/policy.py
--- a/pypy/module/pypyjit/policy.py
+++ b/pypy/module/pypyjit/policy.py
@@ -14,7 +14,7 @@
             modname, _ = modname.split('.', 1)
         if modname in ['pypyjit', 'signal', 'micronumpy', 'math', 'exceptions',
                        'imp', 'sys', 'array', '_ffi', 'itertools', 'operator',
-                       'posix', '_socket', '_sre', '_lsprof']:
+                       'posix', '_socket', '_sre', '_lsprof', '_weakref']:
             return True
         return False
 
diff --git a/pypy/module/pypyjit/test/test_jit_hook.py b/pypy/module/pypyjit/test/test_jit_hook.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/pypyjit/test/test_jit_hook.py
@@ -0,0 +1,89 @@
+
+import py
+from pypy.conftest import gettestobjspace, option
+from pypy.interpreter.pycode import PyCode
+from pypy.interpreter.gateway import interp2app
+from pypy.jit.metainterp.history import LoopToken
+from pypy.jit.metainterp.resoperation import ResOperation, rop
+from pypy.jit.metainterp.logger import Logger
+from pypy.rpython.annlowlevel import (cast_instance_to_base_ptr,
+                                      cast_base_ptr_to_instance)
+from pypy.module.pypyjit.interp_jit import pypyjitdriver
+from pypy.jit.tool.oparser import parse
+from pypy.jit.metainterp.typesystem import llhelper
+
+class MockSD(object):
+    class cpu:
+        ts = llhelper
+
+class AppTestJitHook(object):
+    def setup_class(cls):
+        if option.runappdirect:
+            py.test.skip("Can't run this test with -A")
+        space = gettestobjspace(usemodules=('pypyjit',))
+        cls.space = space
+        w_f = space.appexec([], """():
+        def f():
+            pass
+        return f
+        """)
+        ll_code = cast_instance_to_base_ptr(w_f.code)
+        logger = Logger(MockSD())
+
+        oplist = parse("""
+        [i1, i2]
+        i3 = int_add(i1, i2)
+        guard_true(i3) []
+        """).operations
+
+        def interp_on_compile():
+            pypyjitdriver.on_compile(logger, LoopToken(), oplist, 'loop',
+                                     0, False, ll_code)
+
+        def interp_on_compile_bridge():
+            pypyjitdriver.on_compile_bridge(logger, LoopToken(), oplist, 0)
+        
+        cls.w_on_compile = space.wrap(interp2app(interp_on_compile))
+        cls.w_on_compile_bridge = space.wrap(interp2app(interp_on_compile_bridge))
+
+    def test_on_compile(self):
+        import pypyjit
+        all = []
+
+        def hook(*args):
+            assert args[0] == 'main'
+            assert args[1] in ['loop', 'bridge']
+            all.append(args[2:])
+        
+        self.on_compile()
+        pypyjit.set_compile_hook(hook)
+        assert not all
+        self.on_compile()
+        assert len(all) == 1
+        assert all[0][0][0].co_name == 'f'
+        assert all[0][0][1] == 0
+        assert all[0][0][2] == False
+        assert len(all[0][1]) == 2
+        assert 'int_add' in all[0][1][0]
+        self.on_compile_bridge()
+        assert len(all) == 2
+        pypyjit.set_compile_hook(None)
+        self.on_compile()
+        assert len(all) == 2
+
+    def test_on_compile_exception(self):
+        import pypyjit, sys, cStringIO
+
+        def hook(*args):
+            1/0
+
+        pypyjit.set_compile_hook(hook)
+        s = cStringIO.StringIO()
+        prev = sys.stderr
+        sys.stderr = s
+        try:
+            self.on_compile()
+        finally:
+            sys.stderr = prev
+        assert 'jit hook' in s.getvalue()
+        assert 'ZeroDivisionError' in s.getvalue()
diff --git a/pypy/module/pypyjit/test_pypy_c/test_model.py b/pypy/module/pypyjit/test_pypy_c/test_model.py
--- a/pypy/module/pypyjit/test_pypy_c/test_model.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_model.py
@@ -20,7 +20,7 @@
     def setup_method(self, meth):
         self.filepath = self.tmpdir.join(meth.im_func.func_name + '.py')
 
-    def run(self, func_or_src, args=[], **jitopts):
+    def run(self, func_or_src, args=[], import_site=False, **jitopts):
         src = py.code.Source(func_or_src)
         if isinstance(func_or_src, types.FunctionType):
             funcname = func_or_src.func_name
@@ -39,7 +39,9 @@
         # run a child pypy-c with logging enabled
         logfile = self.filepath.new(ext='.log')
         #
-        cmdline = [sys.executable, '-S']
+        cmdline = [sys.executable]
+        if not import_site:
+            cmdline.append('-S')
         for key, value in jitopts.iteritems():
             cmdline += ['--jit', '%s=%s' % (key, value)]
         cmdline.append(str(self.filepath))
@@ -465,7 +467,7 @@
                 j = ntohs(1) # ID: ntohs
                 a = 0
             return i
-        log = self.run(f)
+        log = self.run(f, import_site=True)
         loop, = log.loops_by_id('ntohs')
         assert loop.match_by_id('ntohs', """
             guard_not_invalidated(descr=...)
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
@@ -270,9 +270,8 @@
             i17 = int_add_ovf(i8, 1)
             guard_no_overflow(descr=<Guard5>)
             i18 = force_token()
-            i20 = int_sub(i17, 1)
             --TICK--
-            jump(p0, p1, p2, p3, p4, p5, i20, p7, i17, i9, p10, p11, p12, descr=<Loop0>)
+            jump(p0, p1, p2, p3, p4, p5, i8, p7, i17, i9, p10, p11, p12, descr=<Loop0>)
         """)
 
     def test_default_and_kw(self):
@@ -481,10 +480,14 @@
         assert log.result == (1000, 998)
         loop, = log.loops_by_filename(self.filepath)
         assert loop.match_by_id('append', """
-            p14 = new_with_vtable(ConstClass(W_IntObject))
-            setfield_gc(p14, i12, descr=<SignedFieldDescr .*W_IntObject.inst_intval .*>)
-            call(ConstClass(ll_append__listPtr_objectPtr), p8, p14, descr=...)
+            i13 = getfield_gc(p8, descr=<SignedFieldDescr list.length .*>)
+            i15 = int_add(i13, 1)
+            call(ConstClass(_ll_list_resize_ge__listPtr_Signed), p8, i15, descr=<VoidCallDescr>)
             guard_no_exception(descr=<Guard4>)
+            p17 = getfield_gc(p8, descr=<GcPtrFieldDescr list.items .*>)
+            p19 = new_with_vtable(ConstClass(W_IntObject))
+            setfield_gc(p19, i12, descr=<SignedFieldDescr .*W_IntObject.inst_intval .*>)
+            setarrayitem_gc(p17, i13, p19, descr=<GcPtrArrayDescr>)
         """)
 
     def test_range_iter(self):
@@ -1676,3 +1679,55 @@
         loop, = log.loops_by_filename(self.filepath)
         import pdb;pdb.set_trace()
         assert loop.match_by_id('div', "")  # optimized away
+
+    def test_oldstyle_newstyle_mix(self):
+        def main():
+            class A:
+                pass
+
+            class B(object, A):
+                def __init__(self, x):
+                    self.x = x
+
+            i = 0
+            b = B(1)
+            while i < 100:
+                v = b.x # ID: loadattr
+                i += v
+            return i
+
+        log = self.run(main, [], threshold=80)
+        loop, = log.loops_by_filename(self.filepath)
+        loop.match_by_id('loadattr',
+        '''
+        guard_not_invalidated(descr=...)
+        i19 = call(ConstClass(ll_dict_lookup), _, _, _, descr=...)
+        guard_no_exception(descr=...)
+        i21 = int_and(i19, _)
+        i22 = int_is_true(i21)
+        guard_true(i22, descr=...)
+        i26 = call(ConstClass(ll_dict_lookup), _, _, _, descr=...)
+        guard_no_exception(descr=...)
+        i28 = int_and(i26, _)
+        i29 = int_is_true(i28)
+        guard_true(i29, descr=...)
+        ''')
+
+    def test_python_contains(self):
+        def main():
+            class A(object):
+                def __contains__(self, v):
+                    return True
+
+            i = 0
+            a = A()
+            while i < 100:
+                i += i in a # ID: contains
+
+            log = self.run(main, [], threshold=80)
+            loop, = log.loops_by_filename(self.filemath)
+            # XXX: haven't confirmed his is correct, it's probably missing a
+            # few instructions
+            loop.match_by_id("contains", """
+                i1 = int_add(i0, 1)
+            """)
diff --git a/pypy/module/sys/__init__.py b/pypy/module/sys/__init__.py
--- a/pypy/module/sys/__init__.py
+++ b/pypy/module/sys/__init__.py
@@ -150,7 +150,7 @@
             if operror is None:
                 return space.w_None
             else:
-                return space.wrap(operror.application_traceback)
+                return space.wrap(operror.get_traceback())
         return None 
 
     def get_w_default_encoder(self):
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
@@ -43,16 +43,21 @@
     #
     encoding = base_encoding
     if rlocale.HAVE_LANGINFO and rlocale.CODESET:
-        oldlocale = rlocale.setlocale(rlocale.LC_CTYPE, None)
-        rlocale.setlocale(rlocale.LC_CTYPE, "")
-        loc_codeset = rlocale.nl_langinfo(rlocale.CODESET)
-        if loc_codeset:
-            codecmod = space.getbuiltinmodule('_codecs')
-            w_res = space.call_function(space.getattr(codecmod,
-                                                      space.wrap('lookup')),
-                                        space.wrap(loc_codeset))
-            if space.is_true(w_res):
-                encoding = loc_codeset
+        try:
+            oldlocale = rlocale.setlocale(rlocale.LC_CTYPE, None)
+            rlocale.setlocale(rlocale.LC_CTYPE, "")
+            try:
+                loc_codeset = rlocale.nl_langinfo(rlocale.CODESET)
+                if loc_codeset:
+                    codecmod = space.getbuiltinmodule('_codecs')
+                    w_res = space.call_method(codecmod, 'lookup',
+                                              space.wrap(loc_codeset))
+                    if space.is_true(w_res):
+                        encoding = loc_codeset
+            finally:
+                rlocale.setlocale(rlocale.LC_CTYPE, oldlocale)
+        except rlocale.LocaleError:
+            pass
     return encoding
 
 def getfilesystemencoding(space):
diff --git a/pypy/module/sys/vm.py b/pypy/module/sys/vm.py
--- a/pypy/module/sys/vm.py
+++ b/pypy/module/sys/vm.py
@@ -40,24 +40,24 @@
             break
         depth -= 1
         f = ec.getnextframe_nohidden(f)
+    f.mark_as_escaped()
     return space.wrap(f)
 
 def setrecursionlimit(space, w_new_limit):
-    """setrecursionlimit() is ignored (and not needed) on PyPy.
-
-On CPython it would set the maximum number of nested calls that can
-occur before a RuntimeError is raised.  On PyPy overflowing the stack
-also causes RuntimeErrors, but the limit is checked at a lower level.
-(The limit is currenty hard-coded at 768 KB, corresponding to roughly
-1480 Python calls on Linux.)"""
+    """setrecursionlimit() sets the maximum number of nested calls that
+can occur before a RuntimeError is raised.  On PyPy the limit is
+approximative and checked at a lower level.  The default 1000
+reserves 768KB of stack space, which should suffice (on Linux,
+depending on the compiler settings) for ~1400 calls.  Setting the
+value to N reserves N/1000 times 768KB of stack space.
+"""
+    from pypy.rlib.rstack import _stack_set_length_fraction
     new_limit = space.int_w(w_new_limit)
     if new_limit <= 0:
         raise OperationError(space.w_ValueError,
                              space.wrap("recursion limit must be positive"))
-    # for now, don't rewrite a warning but silently ignore the
-    # recursion limit.
-    #space.warn('setrecursionlimit() is ignored (and not needed) on PyPy', space.w_RuntimeWarning)
     space.sys.recursionlimit = new_limit
+    _stack_set_length_fraction(new_limit * 0.001)
 
 def getrecursionlimit(space):
     """Return the last value set by setrecursionlimit().
@@ -91,7 +91,7 @@
         return space.newtuple([space.w_None,space.w_None,space.w_None])
     else:
         return space.newtuple([operror.w_type, operror.get_w_value(space),
-                               space.wrap(operror.application_traceback)])
+                               space.wrap(operror.get_traceback())])
 
 def exc_clear(space):
     """Clear global information on the current exception.  Subsequent calls
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
@@ -8,15 +8,12 @@
         space = gettestobjspace(usemodules=('_stackless', '_socket'))
         cls.space = space
         # cannot test the unpickle part on top of py.py
-        cls.w_can_unpickle = space.wrap(bool(option.runappdirect))
 
     def test_pickle(self):
         import new, sys
 
         mod = new.module('mod')
         sys.modules['mod'] = mod
-        mod.can_unpickle = self.can_unpickle
-        mod.skip = skip
         try:
             exec '''
 import pickle, sys
@@ -45,8 +42,6 @@
 t = stackless.tasklet(demo)(lev)
 stackless.run()
 assert seen == range(1, lev+1) + range(lev, 0, -1)
-if not can_unpickle:
-    skip("cannot test the unpickling part on top of py.py")
 print "now running the clone"
 tt = pickle.loads(blob)
 tt.insert()
@@ -64,8 +59,6 @@
 
         mod = new.module('mod')
         sys.modules['mod'] = mod
-        mod.can_unpickle = self.can_unpickle
-        mod.skip = skip
         try:
             exec '''
 import pickle, sys
diff --git a/pypy/module/test_lib_pypy/test_tputil.py b/pypy/module/test_lib_pypy/test_tputil.py
--- a/pypy/module/test_lib_pypy/test_tputil.py
+++ b/pypy/module/test_lib_pypy/test_tputil.py
@@ -28,9 +28,9 @@
         from tputil import make_proxy 
         l = []
         tp = make_proxy(l.append, type=list)
-        x = len(tp)
+        x = tp[0:1]
         assert len(l) == 1
-        assert l[0].opname == '__len__'
+        assert l[0].opname == '__getslice__'
        
     def test_simple(self):
         from tputil import make_proxy 
diff --git a/pypy/module/zipimport/test/test_zipimport.py b/pypy/module/zipimport/test/test_zipimport.py
--- a/pypy/module/zipimport/test/test_zipimport.py
+++ b/pypy/module/zipimport/test/test_zipimport.py
@@ -1,7 +1,7 @@
 
 from pypy.conftest import gettestobjspace
 import marshal
-import py
+import py, os
 import time
 import struct
 from pypy.module.imp.importing import get_pyc_magic, _w_long
@@ -15,6 +15,7 @@
     cpy's regression tests
     """
     compression = ZIP_STORED
+    pathsep = '/'
     
     def make_pyc(cls, space, co, mtime):
         data = marshal.dumps(co)
@@ -57,6 +58,7 @@
         test_pyc = cls.make_pyc(space, co, now)
         cls.w_test_pyc = space.wrap(test_pyc)
         cls.w_compression = space.wrap(cls.compression)
+        cls.w_pathsep = space.wrap(cls.pathsep)
         #ziptestmodule = tmpdir.ensure('ziptestmodule.zip').write(
         ziptestmodule = tmpdir.join("somezip.zip")
         cls.w_tmpzip = space.wrap(str(ziptestmodule))
@@ -100,6 +102,7 @@
         from zipfile import ZipFile, ZipInfo
         z = ZipFile(self.zipfile, 'w')
         write_files = self.write_files
+        filename = filename.replace('/', self.pathsep)
         write_files.append((filename, data))
         for filename, data in write_files:
             zinfo = ZipInfo(filename, time.localtime(self.now))
@@ -121,6 +124,7 @@
             del _zip_directory_cache[self.zipfile]
 
     def test_cache_subdir(self):
+        import os
         self.writefile('x.py', '')
         self.writefile('sub/__init__.py', '')
         self.writefile('sub/yy.py', '')
@@ -130,7 +134,7 @@
 
         assert main_importer is not sub_importer
         assert main_importer.prefix == ""
-        assert sub_importer.prefix == "sub/"
+        assert sub_importer.prefix == "sub" + os.path.sep
 
     def test_good_bad_arguments(self):
         from zipimport import zipimporter
@@ -262,7 +266,7 @@
         import zipimport
         data = "saddsadsa"
         self.writefile("xxx", data)
-        self.writefile("xx"+os.sep+"__init__.py", "5")
+        self.writefile("xx/__init__.py", "5")
         self.writefile("yy.py", "3")
         self.writefile('uu.pyc', self.test_pyc)
         z = zipimport.zipimporter(self.zipfile)
@@ -287,8 +291,7 @@
         """
         import os
         import zipimport
-        self.writefile(
-            os.sep.join(("directory", "package", "__init__.py")), "")
+        self.writefile("directory/package/__init__.py", "")
         importer = zipimport.zipimporter(self.zipfile + "/directory")
         # Grab this so if the assertion fails, py.test will display its
         # value.  Not sure why it doesn't the assertion uses import.archive
@@ -296,15 +299,14 @@
         archive = importer.archive
         realprefix = importer.prefix
         allbutlast = self.zipfile.split(os.path.sep)[:-1]
-        prefix = 'directory/'
+        prefix = 'directory' + os.path.sep
         assert archive == self.zipfile
         assert realprefix == prefix
 
     def test_subdirectory_importer(self):
         import os
         import zipimport
-        self.writefile(
-            os.sep.join(("directory", "package", "__init__.py")), "")
+        self.writefile("directory/package/__init__.py", "")
         z = zipimport.zipimporter(self.zipfile + "/directory")
         mod = z.load_module("package")
         assert z.is_package("package")
@@ -313,14 +315,9 @@
     def test_subdirectory_twice(self):
         import os, zipimport
  
-        self.writefile(
-            os.sep.join(("package", "__init__.py")), "")
-        self.writefile(
-            os.sep.join(("package", "subpackage",
-                         "__init__.py")), "")
-        self.writefile(
-            os.sep.join(("package", "subpackage",
-                         "foo.py")), "")
+        self.writefile("package/__init__.py", "")
+        self.writefile("package/subpackage/__init__.py", "")
+        self.writefile("package/subpackage/foo.py", "")
         import sys
         print sys.path
         mod = __import__('package.subpackage.foo', None, None, [])
@@ -331,8 +328,7 @@
         """
         import os
         import zipimport
-        self.writefile(
-                     os.sep.join(("directory", "package", "__init__.py")), "")
+        self.writefile("directory/package/__init__.py", "")
         importer = zipimport.zipimporter(self.zipfile + "/directory")
         l = [i for i in zipimport._zip_directory_cache]
         assert len(l)
@@ -370,3 +366,8 @@
         except ImportError:
             py.test.skip("zlib not available, cannot test compressed zipfiles")
         cls.make_class()
+
+
+if os.sep != '/':
+    class AppTestNativePathSep(AppTestZipimport):
+        pathsep = os.sep
diff --git a/pypy/objspace/descroperation.py b/pypy/objspace/descroperation.py
--- a/pypy/objspace/descroperation.py
+++ b/pypy/objspace/descroperation.py
@@ -207,34 +207,51 @@
         return space.get_and_call_function(w_descr, w_obj, w_name)
 
     def is_true(space, w_obj):
-        w_descr = space.lookup(w_obj, '__nonzero__')
+        method = "__nonzero__"
+        w_descr = space.lookup(w_obj, method)
         if w_descr is None:
-            w_descr = space.lookup(w_obj, '__len__')
+            method = "__len__"
+            w_descr = space.lookup(w_obj, method)
             if w_descr is None:
                 return True
         w_res = space.get_and_call_function(w_descr, w_obj)
         # more shortcuts for common cases
-        if w_res is space.w_False:
+        if space.is_w(w_res, space.w_False):
             return False
-        if w_res is space.w_True:
+        if space.is_w(w_res, space.w_True):
             return True
         w_restype = space.type(w_res)
-        if (space.is_w(w_restype, space.w_bool) or
-            space.is_w(w_restype, space.w_int)):
+        # Note there is no check for bool here because the only possible
+        # instances of bool are w_False and w_True, which are checked above.
+        if (space.is_w(w_restype, space.w_int) or
+            space.is_w(w_restype, space.w_long)):
             return space.int_w(w_res) != 0
         else:
-            raise OperationError(space.w_TypeError,
-                                 space.wrap('__nonzero__ should return '
-                                            'bool or int'))
+            msg = "%s should return bool or integer" % (method,)
+            raise OperationError(space.w_TypeError, space.wrap(msg))
 
-    def nonzero(self, w_obj):
-        if self.is_true(w_obj):
-            return self.w_True
+    def nonzero(space, w_obj):
+        if space.is_true(w_obj):
+            return space.w_True
         else:
-            return self.w_False
+            return space.w_False
 
-##    def len(self, w_obj):
-##        XXX needs to check that the result is an int (or long?) >= 0
+    def len(space, w_obj):
+        w_descr = space.lookup(w_obj, '__len__')
+        if w_descr is None:
+            name = space.type(w_obj).getname(space)
+            msg = "'%s' has no length" % (name,)
+            raise OperationError(space.w_TypeError, space.wrap(msg))
+        w_res = space.get_and_call_function(w_descr, w_obj)
+        space._check_len_result(w_res)
+        return w_res
+
+    def _check_len_result(space, w_obj):
+        # Will complain if result is too big.
+        result = space.int_w(w_obj)
+        if result < 0:
+            raise OperationError(space.w_ValueError,
+                                 space.wrap("__len__() should return >= 0"))
 
     def iter(space, w_obj):
         w_descr = space.lookup(w_obj, '__iter__')
@@ -376,6 +393,9 @@
         w_descr = space.lookup(w_container, '__contains__')
         if w_descr is not None:
             return space.get_and_call_function(w_descr, w_container, w_item)
+        return space._contains(w_container, w_item)
+
+    def _contains(space, w_container, w_item):
         w_iter = space.iter(w_container)
         while 1:
             try:
diff --git a/pypy/objspace/std/callmethod.py b/pypy/objspace/std/callmethod.py
--- a/pypy/objspace/std/callmethod.py
+++ b/pypy/objspace/std/callmethod.py
@@ -12,7 +12,7 @@
 
 from pypy.interpreter import function
 from pypy.objspace.descroperation import object_getattribute
-from pypy.rlib import jit, rstack # for resume points
+from pypy.rlib import jit
 from pypy.objspace.std.mapdict import LOOKUP_METHOD_mapdict, \
     LOOKUP_METHOD_mapdict_fill_cache_method
 
@@ -51,6 +51,7 @@
             # this handles directly the common case
             #   module.function(args..)
             w_value = w_obj.getdictvalue(space, name)
+            # xxx we could also use the mapdict cache in that case, probably
         else:
             typ = type(w_descr)
             if typ is function.Function or typ is function.FunctionWithFixedCode:
@@ -64,7 +65,7 @@
                             not jit.we_are_jitted()):
                         # let mapdict cache stuff
                         LOOKUP_METHOD_mapdict_fill_cache_method(
-                            f.getcode(), nameindex, w_obj, w_type, w_descr)
+                            space, f.getcode(), name, nameindex, w_obj, w_type)
                     return
     if w_value is None:
         w_value = space.getattr(w_obj, w_name)
@@ -83,7 +84,6 @@
         w_callable = f.peekvalue(n_args + (2 * n_kwargs) + 1)
         try:
             w_result = f.space.call_valuestack(w_callable, n, f)
-            rstack.resume_point("CALL_METHOD", f, n_args, returns=w_result)
         finally:
             f.dropvalues(n_args + 2)
     else:
@@ -108,7 +108,6 @@
             w_result = f.space.call_args_and_c_profile(f, w_callable, args)
         else:
             w_result = f.space.call_args(w_callable, args)
-        rstack.resume_point("CALL_METHOD_KW", f, returns=w_result)
     f.pushvalue(w_result)
 
 
diff --git a/pypy/objspace/std/floattype.py b/pypy/objspace/std/floattype.py
--- a/pypy/objspace/std/floattype.py
+++ b/pypy/objspace/std/floattype.py
@@ -14,10 +14,8 @@
 float_as_integer_ratio = SMM("as_integer_ratio", 1)
 float_hex = SMM("hex", 1)
 
-float_conjugate = SMM("conjugate", 1, doc="Returns self, the complex conjugate of any float.")
-
-def float_conjugate__ANY(space, w_float):
-    return space.pos(w_float)
+def descr_conjugate(space, w_float):
+    return space.float(w_float)
 
 register_all(vars(), globals())
 
@@ -168,10 +166,10 @@
         if total_digits > min(const_one, const_two) // 4:
             raise OperationError(space.w_ValueError, space.wrap("way too long"))
         if i < length and (s[i] == "p" or s[i] == "P"):
+            i += 1
             if i == length:
                 raise OperationError(space.w_ValueError,
                                      space.wrap("invalid hex string"))
-            i += 1
             exp_sign = 1
             if s[i] == "-" or s[i] == "+":
                 if s[i] == "-":
@@ -264,7 +262,7 @@
     return space.call_function(w_cls, w_float)
 
 def descr_get_real(space, w_obj):
-    return w_obj
+    return space.float(w_obj)
 
 def descr_get_imag(space, w_obj):
     return space.wrap(0.0)
@@ -280,6 +278,7 @@
                                        as_classmethod=True),
     fromhex = gateway.interp2app(descr_fromhex,
                                  as_classmethod=True),
+    conjugate = gateway.interp2app(descr_conjugate),
     real = typedef.GetSetProperty(descr_get_real),
     imag = typedef.GetSetProperty(descr_get_imag),
 )
diff --git a/pypy/objspace/std/inttype.py b/pypy/objspace/std/inttype.py
--- a/pypy/objspace/std/inttype.py
+++ b/pypy/objspace/std/inttype.py
@@ -11,14 +11,19 @@
 
 # ____________________________________________________________
 
-int_conjugate = SMM("conjugate", 1, doc="Returns self, the complex conjugate of any int.")
+def descr_conjugate(space, w_int):
+    "Returns self, the complex conjugate of any int."
+    return space.int(w_int)
 
-def int_conjugate__ANY(space, w_int):
-    return space.pos(w_int)
+def descr_bit_length(space, w_int):
+    """int.bit_length() -> int
 
-int_bit_length = SMM("bit_length", 1, doc="int.bit_length() -> int\n\nNumber of bits necessary to represent self in binary.\n>>> bin(37)\n'0b100101'\n>>> (37).bit_length()\n6")
-
-def int_bit_length__ANY(space, w_int):
+    Number of bits necessary to represent self in binary.
+    >>> bin(37)
+    '0b100101'
+    >>> (37).bit_length()
+    6
+    """
     val = space.int_w(w_int)
     if val < 0:
         val = -val
@@ -28,8 +33,6 @@
         val >>= 1
     return space.wrap(bits)
 
-register_all(vars(), globals())
-
 
 def wrapint(space, x):
     if space.config.objspace.std.withsmallint:
@@ -179,7 +182,7 @@
     return space.wrap(1)
 
 def descr_get_real(space, w_obj):
-    return w_obj
+    return space.int(w_obj)
 
 def descr_get_imag(space, w_obj):
     return space.wrap(0)
@@ -196,6 +199,8 @@
 non-string. If the argument is outside the integer range a long object
 will be returned instead.''',
     __new__ = gateway.interp2app(descr__new__),
+    conjugate = gateway.interp2app(descr_conjugate),
+    bit_length = gateway.interp2app(descr_bit_length),
     numerator = typedef.GetSetProperty(descr_get_numerator),
     denominator = typedef.GetSetProperty(descr_get_denominator),
     real = typedef.GetSetProperty(descr_get_real),
diff --git a/pypy/objspace/std/longtype.py b/pypy/objspace/std/longtype.py
--- a/pypy/objspace/std/longtype.py
+++ b/pypy/objspace/std/longtype.py
@@ -4,12 +4,8 @@
 from pypy.objspace.std.stdtypedef import StdTypeDef, SMM
 from pypy.objspace.std.strutil import string_to_bigint, ParseStringError
 
-long_conjugate = SMM("conjugate", 1, doc="Returns self, the complex conjugate of any long.")
-
-def long_conjugate__ANY(space, w_int):
-    return space.pos(w_int)
-
-register_all(vars(), globals())
+def descr_conjugate(space, w_int):
+    return space.long(w_int)
 
 
 def descr__new__(space, w_longtype, w_x=0, w_base=gateway.NoneNotWrapped):
@@ -104,7 +100,7 @@
     return space.newlong(1)
 
 def descr_get_real(space, w_obj):
-    return w_obj
+    return space.long(w_obj)
 
 def descr_get_imag(space, w_obj):
     return space.newlong(0)
@@ -128,6 +124,7 @@
 string, use the optional base.  It is an error to supply a base when
 converting a non-string.''',
     __new__ = gateway.interp2app(descr__new__),
+    conjugate = gateway.interp2app(descr_conjugate),
     numerator = typedef.GetSetProperty(descr_get_numerator),
     denominator = typedef.GetSetProperty(descr_get_denominator),
     real = typedef.GetSetProperty(descr_get_real),
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
@@ -8,6 +8,7 @@
 from pypy.objspace.std.dictmultiobject import IteratorImplementation
 from pypy.objspace.std.dictmultiobject import _is_sane_hash
 from pypy.objspace.std.objectobject import W_ObjectObject
+from pypy.objspace.std.typeobject import TypeCell
 
 # ____________________________________________________________
 # attribute shapes
@@ -753,22 +754,40 @@
         w_descr = w_type.getattribute_if_not_from_object()
         if w_descr is not None:
             return space._handle_getattribute(w_descr, w_obj, w_name)
-
         version_tag = w_type.version_tag()
         if version_tag is not None:
             name = space.str_w(w_name)
-            w_descr = w_type.lookup(name)
+            # We need to care for obscure cases in which the w_descr is
+            # a TypeCell, which may change without changing the version_tag
+            assert space.config.objspace.std.withmethodcache
+            _, w_descr = w_type._pure_lookup_where_with_method_cache(
+                name, version_tag)
+            #
             selector = ("", INVALID)
-            if w_descr is not None and space.is_data_descr(w_descr):
+            if w_descr is None:
+                selector = (name, DICT) #common case: no such attr in the class
+            elif isinstance(w_descr, TypeCell):
+                pass              # we have a TypeCell in the class: give up
+            elif space.is_data_descr(w_descr):
+                # we have a data descriptor, which means the dictionary value
+                # (if any) has no relevance.
                 from pypy.interpreter.typedef import Member
                 descr = space.interpclass_w(w_descr)
-                if isinstance(descr, Member):
+                if isinstance(descr, Member):    # it is a slot -- easy case
                     selector = ("slot", SLOTS_STARTING_FROM + descr.index)
             else:
+                # There is a non-data descriptor in the class.  If there is
+                # also a dict attribute, use the latter, caching its position.
+                # If not, we loose.  We could do better in this case too,
+                # but we don't care too much; the common case of a method
+                # invocation is handled by LOOKUP_METHOD_xxx below.
                 selector = (name, DICT)
+            #
             if selector[1] != INVALID:
                 index = map.index(selector)
                 if index >= 0:
+                    # Note that if map.terminator is a DevolvedDictTerminator,
+                    # map.index() will always return -1 if selector[1]==DICT.
                     _fill_cache(pycode, nameindex, map, version_tag, index)
                     return w_obj._mapdict_read_storage(index)
     if space.config.objspace.std.withmethodcachecounter:
@@ -788,11 +807,26 @@
             return True
     return False
 
-def LOOKUP_METHOD_mapdict_fill_cache_method(pycode, nameindex, w_obj, w_type, w_method):
+def LOOKUP_METHOD_mapdict_fill_cache_method(space, pycode, name, nameindex,
+                                            w_obj, w_type):
     version_tag = w_type.version_tag()
     if version_tag is None:
         return
     map = w_obj._get_mapdict_map()
-    if map is None:
+    if map is None or isinstance(map.terminator, DevolvedDictTerminator):
+        return
+    # We know here that w_obj.getdictvalue(space, name) just returned None,
+    # so the 'name' is not in the instance.  We repeat the lookup to find it
+    # in the class, this time taking care of the result: it can be either a
+    # quasi-constant class attribute, or actually a TypeCell --- which we
+    # must not cache.  (It should not be None here, but you never know...)
+    assert space.config.objspace.std.withmethodcache
+    _, w_method = w_type._pure_lookup_where_with_method_cache(name,
+                                                              version_tag)
+    if w_method is None or isinstance(w_method, TypeCell):
         return
     _fill_cache(pycode, nameindex, map, version_tag, -1, w_method)
+
+# XXX fix me: if a function contains a loop with both LOAD_ATTR and
+# XXX LOOKUP_METHOD on the same attribute name, it keeps trashing and
+# XXX rebuilding the cache
diff --git a/pypy/objspace/std/model.py b/pypy/objspace/std/model.py
--- a/pypy/objspace/std/model.py
+++ b/pypy/objspace/std/model.py
@@ -15,6 +15,7 @@
     _registered_implementations.add(implcls)
 
 option_to_typename = {
+    "withsmalltuple" : ["smalltupleobject.W_SmallTupleObject"],
     "withsmallint"   : ["smallintobject.W_SmallIntObject"],
     "withsmalllong"  : ["smalllongobject.W_SmallLongObject"],
     "withstrslice"   : ["strsliceobject.W_StringSliceObject"],
@@ -71,6 +72,7 @@
         from pypy.objspace.std import smallintobject
         from pypy.objspace.std import smalllongobject
         from pypy.objspace.std import tupleobject
+        from pypy.objspace.std import smalltupleobject
         from pypy.objspace.std import listobject
         from pypy.objspace.std import dictmultiobject
         from pypy.objspace.std import stringobject
@@ -253,6 +255,9 @@
                 (listobject.W_ListObject,
                                        rangeobject.delegate_range2list),
                 ]
+        if config.objspace.std.withsmalltuple:
+            self.typeorder[smalltupleobject.W_SmallTupleObject] += [
+                (tupleobject.W_TupleObject, smalltupleobject.delegate_SmallTuple2Tuple)]
 
         # put W_Root everywhere
         self.typeorder[W_Root] = []
diff --git a/pypy/objspace/std/objspace.py b/pypy/objspace/std/objspace.py
--- a/pypy/objspace/std/objspace.py
+++ b/pypy/objspace/std/objspace.py
@@ -266,6 +266,7 @@
         return None
 
     def unwrap(self, w_obj):
+        """NOT_RPYTHON"""
         if isinstance(w_obj, Wrappable):
             return w_obj
         if isinstance(w_obj, model.W_Object):
@@ -295,9 +296,10 @@
         return newlong(self, val)
 
     def newtuple(self, list_w):
+        from pypy.objspace.std.tupletype import wraptuple
         assert isinstance(list_w, list)
         make_sure_not_resized(list_w)
-        return W_TupleObject(list_w)
+        return wraptuple(self, list_w)
 
     def newlist(self, list_w):
         return W_ListObject(list_w)
diff --git a/pypy/objspace/std/smalltupleobject.py b/pypy/objspace/std/smalltupleobject.py
new file mode 100644
--- /dev/null
+++ b/pypy/objspace/std/smalltupleobject.py
@@ -0,0 +1,157 @@
+from pypy.interpreter.error import OperationError
+from pypy.objspace.std.model import registerimplementation, W_Object
+from pypy.objspace.std.register_all import register_all
+from pypy.objspace.std.inttype import wrapint
+from pypy.objspace.std.multimethod import FailedToImplement
+from pypy.rlib.rarithmetic import intmask
+from pypy.objspace.std.sliceobject import W_SliceObject, normalize_simple_slice
+from pypy.objspace.std import slicetype
+from pypy.interpreter import gateway
+from pypy.rlib.debug import make_sure_not_resized
+from pypy.rlib.unroll import unrolling_iterable
+from pypy.objspace.std.tupleobject import W_TupleObject
+
+class W_SmallTupleObject(W_Object):
+    from pypy.objspace.std.tupletype import tuple_typedef as typedef
+
+    def tolist(self):
+        raise NotImplementedError
+
+    def length(self):
+        raise NotImplementedError
+
+    def getitem(self, index):
+        raise NotImplementedError
+
+    def hash(self, space):
+        raise NotImplementedError
+
+    def eq(self, space, w_other):
+        raise NotImplementedError
+
+    def setitem(self, index, w_item):
+        raise NotImplementedError
+
+    def unwrap(w_tuple, space):
+        items = [space.unwrap(w_item) for w_item in w_tuple.tolist()]
+        return tuple(items)
+
+def make_specialized_class(n):
+    iter_n = unrolling_iterable(range(n))
+    class cls(W_SmallTupleObject):
+
+        def __init__(self, values):
+            assert len(values) == n
+            for i in iter_n:
+                setattr(self, 'w_value%s' % i, values[i])
+
+        def tolist(self):
+            l = [None] * n
+            for i in iter_n:
+                l[i] = getattr(self, 'w_value%s' % i)
+            return l
+
+        def length(self):
+            return n
+
+        def getitem(self, index):
+            for i in iter_n:
+                if index == i:
+                    return getattr(self,'w_value%s' % i)
+            raise IndexError
+
+        def setitem(self, index, w_item):
+            for i in iter_n:
+                if index == i:
+                    setattr(self, 'w_value%s' % i, w_item)
+                    return
+            raise IndexError
+
+        def eq(self, space, w_other):
+            if self.length() != w_other.length():
+                return space.w_False
+            for i in iter_n:
+                item1 = self.getitem(i)
+                item2 = w_other.getitem(i)
+                if not space.eq_w(item1, item2):
+                    return space.w_False
+            return space.w_True
+
+        def hash(self, space):
+            mult = 1000003
+            x = 0x345678
+            z = self.length()
+            for i in iter_n:
+                w_item = self.getitem(i)
+                y = space.int_w(space.hash(w_item))
+                x = (x ^ y) * mult
+                z -= 1
+                mult += 82520 + z + z
+            x += 97531
+            return space.wrap(intmask(x))
+
+    cls.__name__ = "W_SmallTupleObject%s" % n
+    return cls
+
+W_SmallTupleObject2 = make_specialized_class(2)
+W_SmallTupleObject3 = make_specialized_class(3)
+W_SmallTupleObject4 = make_specialized_class(4)
+W_SmallTupleObject5 = make_specialized_class(5)
+W_SmallTupleObject6 = make_specialized_class(6)
+W_SmallTupleObject7 = make_specialized_class(7)
+W_SmallTupleObject8 = make_specialized_class(8)
+
+registerimplementation(W_SmallTupleObject)
+
+def delegate_SmallTuple2Tuple(space, w_small):
+    return W_TupleObject(w_small.tolist())
+
+def len__SmallTuple(space, w_tuple):
+    return space.wrap(w_tuple.length())
+
+def getitem__SmallTuple_ANY(space, w_tuple, w_index):
+    index = space.getindex_w(w_index, space.w_IndexError, "tuple index")
+    if index < 0:
+        index += w_tuple.length()
+    try:
+        return w_tuple.getitem(index)
+    except IndexError:
+        raise OperationError(space.w_IndexError,
+                             space.wrap("tuple index out of range"))
+
+def getitem__SmallTuple_Slice(space, w_tuple, w_slice):
+    length = w_tuple.length()
+    start, stop, step, slicelength = w_slice.indices4(space, length)
+    assert slicelength >= 0
+    subitems = [None] * slicelength
+    for i in range(slicelength):
+        subitems[i] = w_tuple.getitem(start)
+        start += step
+    return space.newtuple(subitems)
+
+def mul_smalltuple_times(space, w_tuple, w_times):
+    try:
+        times = space.getindex_w(w_times, space.w_OverflowError)
+    except OperationError, e:
+        if e.match(space, space.w_TypeError):
+            raise FailedToImplement
+        raise
+    if times == 1 and space.type(w_tuple) == space.w_tuple:
+        return w_tuple
+    items = w_tuple.tolist()
+    return space.newtuple(items * times)
+
+def mul__SmallTuple_ANY(space, w_tuple, w_times):
+    return mul_smalltuple_times(space, w_tuple, w_times)
+
+def mul__ANY_SmallTuple(space, w_times, w_tuple):
+    return mul_smalltuple_times(space, w_tuple, w_times)
+
+def eq__SmallTuple_SmallTuple(space, w_tuple1, w_tuple2):
+    return w_tuple1.eq(space, w_tuple2)
+
+def hash__SmallTuple(space, w_tuple):
+    return w_tuple.hash(space)
+
+from pypy.objspace.std import tupletype
+register_all(vars(), tupletype)
diff --git a/pypy/objspace/std/stringobject.py b/pypy/objspace/std/stringobject.py
--- a/pypy/objspace/std/stringobject.py
+++ b/pypy/objspace/std/stringobject.py
@@ -252,15 +252,30 @@
 
     res_w = []
     start = 0
-    while maxsplit != 0:
-        next = value.find(by, start)
-        if next < 0:
-            break
-        res_w.append(sliced(space, value, start, next, w_self))
-        start = next + bylen
-        maxsplit -= 1   # NB. if it's already < 0, it stays < 0
+    if bylen == 1 and maxsplit < 0:
+        # fast path: uses str.rfind(character) and str.count(character)
+        by = by[0]    # annotator hack: string -> char
+        count = value.count(by)
+        res_w = [None] * (count + 1)
+        end = len(value)
+        while count >= 0:
+            assert end >= 0
+            prev = value.rfind(by, 0, end)
+            start = prev + 1
+            assert start >= 0
+            res_w[count] = sliced(space, value, start, end, w_self)
+            count -= 1
+            end = prev
+    else:
+        while maxsplit != 0:
+            next = value.find(by, start)
+            if next < 0:
+                break
+            res_w.append(sliced(space, value, start, next, w_self))
+            start = next + bylen
+            maxsplit -= 1   # NB. if it's already < 0, it stays < 0
+        res_w.append(sliced(space, value, start, len(value), w_self))
 
-    res_w.append(sliced(space, value, start, len(value), w_self))
     return space.newlist(res_w)
 
 def str_rsplit__String_None_ANY(space, w_self, w_none, w_maxsplit=-1):
diff --git a/pypy/objspace/std/test/test_floatobject.py b/pypy/objspace/std/test/test_floatobject.py
--- a/pypy/objspace/std/test/test_floatobject.py
+++ b/pypy/objspace/std/test/test_floatobject.py
@@ -63,6 +63,19 @@
     def setup_class(cls):
         cls.w_py26 = cls.space.wrap(sys.version_info >= (2, 6))
 
+    def test_conjugate(self):
+        assert (1.).conjugate() == 1.
+        assert (-1.).conjugate() == -1.
+
+        class F(float):
+            pass
+        assert F(1.).conjugate() == 1.
+
+        class F(float):
+            def __pos__(self):
+                return 42.
+        assert F(1.).conjugate() == 1.
+
     def test_negatives(self):
         assert -1.1 < 0
         assert -0.1 < 0
@@ -417,6 +430,11 @@
         f = 1.1234e200
         assert f.__format__("G") == "1.1234E+200"
 
+    def test_float_real(self):
+        class A(float): pass
+        b = A(5).real
+        assert type(b) is float
+
 
 class AppTestFloatHex:
     def w_identical(self, x, y):
@@ -746,3 +764,6 @@
                 pass
             else:
                 self.identical(x, float.fromhex(x.hex()))
+
+    def test_invalid(self):
+        raises(ValueError, float.fromhex, "0P")
diff --git a/pypy/objspace/std/test/test_intobject.py b/pypy/objspace/std/test/test_intobject.py
--- a/pypy/objspace/std/test/test_intobject.py
+++ b/pypy/objspace/std/test/test_intobject.py
@@ -285,6 +285,19 @@
 
 class AppTestInt:
 
+    def test_conjugate(self):
+        assert (1).conjugate() == 1
+        assert (-1).conjugate() == -1
+
+        class I(int):
+            pass
+        assert I(1).conjugate() == 1
+
+        class I(int):
+            def __pos__(self):
+                return 42
+        assert I(1).conjugate() == 1
+
     def test_trunc(self):
         import math
         assert math.trunc(1) == 1
@@ -480,6 +493,11 @@
         ]:
             assert val.bit_length() == bits
 
+    def test_int_real(self):
+        class A(int): pass
+        b = A(5).real
+        assert type(b) is int
+
 
 class AppTestIntOptimizedAdd(AppTestInt):
     def setup_class(cls):
diff --git a/pypy/objspace/std/test/test_longobject.py b/pypy/objspace/std/test/test_longobject.py
--- a/pypy/objspace/std/test/test_longobject.py
+++ b/pypy/objspace/std/test/test_longobject.py
@@ -300,6 +300,11 @@
 
         assert type(L(7).conjugate()) is long
 
+        class L(long):
+            def __pos__(self):
+                return 43
+        assert L(7).conjugate() == 7L
+
     def test_bit_length(self):
         assert 8L.bit_length() == 4
         assert (-1<<40).bit_length() == 41
@@ -323,3 +328,7 @@
         assert type(as_long) is long
         assert as_long == 64
 
+    def test_long_real(self):
+        class A(long): pass
+        b = A(5).real
+        assert type(b) is long
diff --git a/pypy/objspace/std/test/test_mapdict.py b/pypy/objspace/std/test/test_mapdict.py
--- a/pypy/objspace/std/test/test_mapdict.py
+++ b/pypy/objspace/std/test/test_mapdict.py
@@ -902,7 +902,53 @@
             return c.m()
         val = f()
         assert val == 42
-        f() 
+        f()
+
+    def test_bug_lookup_method_devolved_dict_caching(self):
+        class A(object):
+            def method(self):
+                return 42
+        a = A()
+        a.__dict__[1] = 'foo'
+        got = a.method()
+        assert got == 42
+        a.__dict__['method'] = lambda: 43
+        got = a.method()
+        assert got == 43
+
+    def test_bug_method_change(self):
+        class A(object):
+            def method(self):
+                return 42
+        a = A()
+        got = a.method()
+        assert got == 42
+        A.method = lambda self: 43
+        got = a.method()
+        assert got == 43
+        A.method = lambda self: 44
+        got = a.method()
+        assert got == 44
+
+    def test_bug_slot_via_changing_member_descr(self):
+        class A(object):
+            __slots__ = ['a', 'b', 'c', 'd']
+        x = A()
+        x.a = 'a'
+        x.b = 'b'
+        x.c = 'c'
+        x.d = 'd'
+        got = x.a
+        assert got == 'a'
+        A.a = A.b
+        got = x.a
+        assert got == 'b'
+        A.a = A.c
+        got = x.a
+        assert got == 'c'
+        A.a = A.d
+        got = x.a
+        assert got == 'd'
 
 class AppTestGlobalCaching(AppTestWithMapDict):
     def setup_class(cls):
diff --git a/pypy/objspace/std/test/test_smalltupleobject.py b/pypy/objspace/std/test/test_smalltupleobject.py
new file mode 100644
--- /dev/null
+++ b/pypy/objspace/std/test/test_smalltupleobject.py
@@ -0,0 +1,86 @@
+from pypy.objspace.std.tupleobject import W_TupleObject
+from pypy.objspace.std.smalltupleobject import W_SmallTupleObject
+from pypy.interpreter.error import OperationError
+from pypy.objspace.std.test.test_tupleobject import AppTestW_TupleObject
+from pypy.conftest import gettestobjspace
+
+class AppTestW_SmallTupleObject(AppTestW_TupleObject):
+
+    def setup_class(cls):
+        cls.space = gettestobjspace(**{"objspace.std.withsmalltuple": True})
+        cls.w_issmall = cls.space.appexec([], """():
+            import __pypy__
+            def issmall(obj):
+                assert "SmallTuple" in __pypy__.internal_repr(obj)
+            return issmall
+        """)
+
+    def test_smalltuple(self):
+        self.issmall((1,2))
+        self.issmall((1,2,3))
+
+    def test_slicing_to_small(self):
+        self.issmall((1, 2, 3)[0:2])    # SmallTuple2
+        self.issmall((1, 2, 3)[0:2:1])
+
+        self.issmall((1, 2, 3, 4)[0:3])    # SmallTuple3
+        self.issmall((1, 2, 3, 4)[0:3:1])
+
+    def test_adding_to_small(self):
+        self.issmall((1,)+(2,))       # SmallTuple2
+        self.issmall((1,1)+(2,))      # SmallTuple3
+        self.issmall((1,)+(2,3))
+
+    def test_multiply_to_small(self):
+        self.issmall((1,)*2)
+        self.issmall((1,)*3)
+
+    def test_slicing_from_small(self):
+        assert (1,2)[0:1:1] == (1,)
+        assert (1,2,3)[0:2:1] == (1,2)
+
+    def test_eq(self):
+        a = (1,2,3)
+        b = (1,2,3)
+        assert a == b
+
+        c = (1,3,2)
+        assert a != c
+
+    def test_hash(self):
+        a = (1,2,3)
+        b = (1,2,3)
+        assert hash(a) == hash(b)
+
+        c = (1,3,2)
+        assert hash(a) != hash(c)
+
+class TestW_SmallTupleObject():
+
+    def setup_class(cls):
+        cls.space = gettestobjspace(**{"objspace.std.withsmalltuple": True})
+
+    def test_issmalltupleobject(self):
+        w_tuple = self.space.newtuple([self.space.wrap(1), self.space.wrap(2)])
+        assert isinstance(w_tuple, W_SmallTupleObject)
+
+    def test_hash_agains_normal_tuple(self):
+        normalspace = gettestobjspace(**{"objspace.std.withsmalltuple": False})
+        w_tuple = normalspace.newtuple([self.space.wrap(1), self.space.wrap(2)])
+
+        smallspace = gettestobjspace(**{"objspace.std.withsmalltuple": True})
+        w_smalltuple = smallspace.newtuple([self.space.wrap(1), self.space.wrap(2)])
+
+        assert isinstance(w_smalltuple, W_SmallTupleObject)
+        assert isinstance(w_tuple, W_TupleObject)
+        assert not normalspace.is_true(normalspace.eq(w_tuple, w_smalltuple))
+        assert smallspace.is_true(smallspace.eq(w_tuple, w_smalltuple))
+        assert smallspace.is_true(smallspace.eq(normalspace.hash(w_tuple), smallspace.hash(w_smalltuple)))
+
+    def test_setitem(self):
+        w_smalltuple = self.space.newtuple([self.space.wrap(1), self.space.wrap(2)])
+        w_smalltuple.setitem(0, self.space.wrap(5))
+        list_w = w_smalltuple.tolist()
+        assert len(list_w) == 2
+        assert self.space.eq_w(list_w[0], self.space.wrap(5))
+        assert self.space.eq_w(list_w[1], self.space.wrap(2))
diff --git a/pypy/objspace/std/tupleobject.py b/pypy/objspace/std/tupleobject.py
--- a/pypy/objspace/std/tupleobject.py
+++ b/pypy/objspace/std/tupleobject.py
@@ -23,7 +23,7 @@
         return "%s(%s)" % (w_self.__class__.__name__, ', '.join(reprlist))
 
     def unwrap(w_tuple, space):
-        items = [space.unwrap(w_item) for w_item in w_tuple.wrappeditems] # XXX generic mixed types unwrap
+        items = [space.unwrap(w_item) for w_item in w_tuple.wrappeditems]
         return tuple(items)
 
 registerimplementation(W_TupleObject)
@@ -56,12 +56,12 @@
     for i in range(slicelength):
         subitems[i] = items[start]
         start += step
-    return W_TupleObject(subitems)
+    return space.newtuple(subitems)
 
 def getslice__Tuple_ANY_ANY(space, w_tuple, w_start, w_stop):
     length = len(w_tuple.wrappeditems)
     start, stop = normalize_simple_slice(space, length, w_start, w_stop)
-    return W_TupleObject(w_tuple.wrappeditems[start:stop])
+    return space.newtuple(w_tuple.wrappeditems[start:stop])
 
 def contains__Tuple_ANY(space, w_tuple, w_obj):
     for w_item in w_tuple.wrappeditems:
@@ -76,7 +76,7 @@
 def add__Tuple_Tuple(space, w_tuple1, w_tuple2):
     items1 = w_tuple1.wrappeditems
     items2 = w_tuple2.wrappeditems
-    return W_TupleObject(items1 + items2)
+    return space.newtuple(items1 + items2)
 
 def mul_tuple_times(space, w_tuple, w_times):
     try:
@@ -88,7 +88,7 @@
     if times == 1 and space.type(w_tuple) == space.w_tuple:
         return w_tuple
     items = w_tuple.wrappeditems
-    return W_TupleObject(items * times)
+    return space.newtuple(items * times)
 
 def mul__Tuple_ANY(space, w_tuple, w_times):
     return mul_tuple_times(space, w_tuple, w_times)
@@ -162,7 +162,7 @@
     return intmask(x)
 
 def getnewargs__Tuple(space, w_tuple):
-    return space.newtuple([W_TupleObject(w_tuple.wrappeditems)])
+    return space.newtuple([space.newtuple(w_tuple.wrappeditems)])
 
 def tuple_count__Tuple_ANY(space, w_tuple, w_obj):
     count = 0
diff --git a/pypy/objspace/std/tupletype.py b/pypy/objspace/std/tupletype.py
--- a/pypy/objspace/std/tupletype.py
+++ b/pypy/objspace/std/tupletype.py
@@ -3,6 +3,31 @@
 from pypy.objspace.std.register_all import register_all
 from pypy.objspace.std.stdtypedef import StdTypeDef, SMM
 
+def wraptuple(space, list_w):
+    from pypy.objspace.std.tupleobject import W_TupleObject
+    from pypy.objspace.std.smalltupleobject import W_SmallTupleObject2
+    from pypy.objspace.std.smalltupleobject import W_SmallTupleObject3
+    from pypy.objspace.std.smalltupleobject import W_SmallTupleObject4
+    from pypy.objspace.std.smalltupleobject import W_SmallTupleObject5
+    from pypy.objspace.std.smalltupleobject import W_SmallTupleObject6
+    from pypy.objspace.std.smalltupleobject import W_SmallTupleObject7
+    from pypy.objspace.std.smalltupleobject import W_SmallTupleObject8
+    if space.config.objspace.std.withsmalltuple:
+        if len(list_w) == 2:
+            return W_SmallTupleObject2(list_w)
+        if len(list_w) == 3:
+            return W_SmallTupleObject3(list_w)
+        if len(list_w) == 4:
+            return W_SmallTupleObject4(list_w)
+        if len(list_w) == 5:
+            return W_SmallTupleObject5(list_w)
+        if len(list_w) == 6:
+            return W_SmallTupleObject6(list_w)
+        if len(list_w) == 7:
+            return W_SmallTupleObject7(list_w)
+        if len(list_w) == 8:
+            return W_SmallTupleObject8(list_w)
+    return W_TupleObject(list_w)
 
 tuple_count = SMM("count", 2,
                   doc="count(obj) -> number of times obj appears in the tuple")
diff --git a/pypy/objspace/test/test_descroperation.py b/pypy/objspace/test/test_descroperation.py
--- a/pypy/objspace/test/test_descroperation.py
+++ b/pypy/objspace/test/test_descroperation.py
@@ -524,6 +524,31 @@
         assert issubclass(B, B)
         assert issubclass(23, B)
 
+    def test_truth_of_long(self):
+        class X(object):
+            def __len__(self): return 1L
+            __nonzero__ = __len__
+        assert X()
+        del X.__nonzero__
+        assert X()
+
+    def test_len_overflow(self):
+        import sys
+        class X(object):
+            def __len__(self):
+                return sys.maxsize + 1
+        raises(OverflowError, len, X())
+
+    def test_len_underflow(self):
+        import sys
+        class X(object):
+            def __len__(self):
+                return -1
+        raises(ValueError, len, X())
+        class Y(object):
+            def __len__(self):
+                return -1L
+        raises(ValueError, len, Y())
 
 class AppTestWithBuiltinShortcut(AppTest_Descroperation):
     OPTIONS = {'objspace.std.builtinshortcut': True}
diff --git a/pypy/objspace/trace.py b/pypy/objspace/trace.py
--- a/pypy/objspace/trace.py
+++ b/pypy/objspace/trace.py
@@ -110,10 +110,10 @@
         self.result.append(EnterFrame(frame))
         self.ec.enter(frame)
 
-    def leave(self, frame, w_exitvalue):
+    def leave(self, frame, w_exitvalue, got_exception):
         """ called just after evaluating of a frame is suspended/finished. """
         self.result.append(LeaveFrame(frame))
-        self.ec.leave(frame, w_exitvalue)
+        self.ec.leave(frame, w_exitvalue, got_exception)
 
     def bytecode_trace(self, frame):
         """ called just before execution of a bytecode. """
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
@@ -50,6 +50,7 @@
 
     def rtype_simple_call(self, hop):
         [v] = hop.inputargs(self)
+        hop.exception_is_here()
         v = hop.genop('jit_force_virtual', [v], resulttype = OBJECTPTR)
         return hop.genop('cast_pointer', [v], resulttype = hop.r_result)
 
@@ -65,6 +66,7 @@
     lowleveltype = OBJECT
     def rtype_simple_call(self, hop):
         [v] = hop.inputargs(self)
+        hop.exception_is_here()
         v = hop.genop('jit_force_virtual', [v], resulttype = OBJECT)
         return hop.genop('oodowncast', [v], resulttype = hop.r_result)
     
diff --git a/pypy/rlib/debug.py b/pypy/rlib/debug.py
--- a/pypy/rlib/debug.py
+++ b/pypy/rlib/debug.py
@@ -140,6 +140,40 @@
             return hop.inputconst(lltype.Bool, False)
 
 
+def debug_offset():
+    """ Return an offset in log file
+    """
+    return -1
+
+class Entry(ExtRegistryEntry):
+    _about_ = debug_offset
+
+    def compute_result_annotation(self):
+        from pypy.annotation import model as annmodel
+        return annmodel.SomeInteger()
+
+    def specialize_call(self, hop):
+        from pypy.rpython.lltypesystem import lltype
+        hop.exception_cannot_occur()
+        return hop.genop('debug_offset', [], resulttype=lltype.Signed)
+
+
+def debug_flush():
+    """ Flushes the debug file
+    """
+    pass
+
+class Entry(ExtRegistryEntry):
+    _about_ = debug_flush
+
+    def compute_result_annotation(self):
+        return None
+    
+    def specialize_call(self, hop):
+        hop.exception_cannot_occur()
+        return hop.genop('debug_flush', [])
+
+
 def llinterpcall(RESTYPE, pythonfunction, *args):
     """When running on the llinterp, this causes the llinterp to call to
     the provided Python function with the run-time value of the given args.
diff --git a/pypy/rlib/jit.py b/pypy/rlib/jit.py
--- a/pypy/rlib/jit.py
+++ b/pypy/rlib/jit.py
@@ -113,7 +113,7 @@
                         flags['fresh_virtualizable'] = True
                     s_x = annmodel.SomeInstance(s_x.classdef,
                                                 s_x.can_be_None,
-                                                flags)        
+                                                flags)
         return s_x
 
     def specialize_call(self, hop, **kwds_i):
@@ -179,29 +179,10 @@
     pass
 
 
-##def force_virtualizable(virtualizable):
-##    pass
-
-##class Entry(ExtRegistryEntry):
-##    _about_ = force_virtualizable
-
-##    def compute_result_annotation(self):
-##        from pypy.annotation import model as annmodel
-##        return annmodel.s_None
-
-##    def specialize_call(self, hop):
-##        [vinst] = hop.inputargs(hop.args_r[0])
-##        cname = inputconst(lltype.Void, None)
-##        cflags = inputconst(lltype.Void, {})
-##        hop.exception_cannot_occur()
-##        return hop.genop('jit_force_virtualizable', [vinst, cname, cflags],
-##                         resulttype=lltype.Void)
-
 # ____________________________________________________________
 # VRefs
 
 def virtual_ref(x):
-    
     """Creates a 'vref' object that contains a reference to 'x'.  Calls
     to virtual_ref/virtual_ref_finish must be properly nested.  The idea
     is that the object 'x' is supposed to be JITted as a virtual between
@@ -212,10 +193,10 @@
     return DirectJitVRef(x)
 virtual_ref.oopspec = 'virtual_ref(x)'
 
-def virtual_ref_finish(x):
-    """See docstring in virtual_ref(x).  Note that virtual_ref_finish
-    takes as argument the real object, not the vref."""
+def virtual_ref_finish(vref, x):
+    """See docstring in virtual_ref(x)"""
     keepalive_until_here(x)   # otherwise the whole function call is removed
+    _virtual_ref_finish(vref, x)
 virtual_ref_finish.oopspec = 'virtual_ref_finish(x)'
 
 def non_virtual_ref(x):
@@ -223,19 +204,39 @@
     Used for None or for frames outside JIT scope."""
     return DirectVRef(x)
 
+class InvalidVirtualRef(Exception):
+    """
+    Raised if we try to call a non-forced virtualref after the call to
+    virtual_ref_finish
+    """
+
 # ---------- implementation-specific ----------
 
 class DirectVRef(object):
     def __init__(self, x):
         self._x = x
+        self._state = 'non-forced'
+
     def __call__(self):
+        if self._state == 'non-forced':
+            self._state = 'forced'
+        elif self._state == 'invalid':
+            raise InvalidVirtualRef
         return self._x
 
+    def _finish(self):
+        if self._state == 'non-forced':
+            self._state = 'invalid'
+
 class DirectJitVRef(DirectVRef):
     def __init__(self, x):
         assert x is not None, "virtual_ref(None) is not allowed"
         DirectVRef.__init__(self, x)
 
+def _virtual_ref_finish(vref, x):
+    assert vref._x is x, "Invalid call to virtual_ref_finish"
+    vref._finish()
+
 class Entry(ExtRegistryEntry):
     _about_ = (non_virtual_ref, DirectJitVRef)
 
@@ -255,17 +256,26 @@
         s_obj = self.bookkeeper.immutablevalue(self.instance())
         return _jit_vref.SomeVRef(s_obj)
 
+class Entry(ExtRegistryEntry):
+    _about_ = _virtual_ref_finish
+
+    def compute_result_annotation(self, s_vref, s_obj):
+        pass
+
+    def specialize_call(self, hop):
+        pass
+    
 vref_None = non_virtual_ref(None)
 
 # ____________________________________________________________
-# User interface for the hotpath JIT policy
+# User interface for the warmspot JIT policy
 
 class JitHintError(Exception):
     """Inconsistency in the JIT hints."""
 
 PARAMETERS = {'threshold': 1000,
               'trace_eagerness': 200,
-              'trace_limit': 10000,
+              'trace_limit': 12000,
               'inlining': 0,
               'loop_longevity': 1000,
               'retrace_limit': 5,
@@ -275,7 +285,7 @@
 
 # ____________________________________________________________
 
-class JitDriver(object):    
+class JitDriver(object):
     """Base class to declare fine-grained user control on the JIT.  So
     far, there must be a singleton instance of JitDriver.  This style
     will allow us (later) to support a single RPython program with
@@ -360,6 +370,24 @@
                             raise
     set_user_param._annspecialcase_ = 'specialize:arg(0)'
 
+    
+    def on_compile(self, logger, looptoken, operations, type, *greenargs):
+        """ A hook called when loop is compiled. Overwrite
+        for your own jitdriver if you want to do something special, like
+        call applevel code
+        """
+
+    def on_compile_bridge(self, logger, orig_looptoken, operations, n):
+        """ A hook called when a bridge is compiled. Overwrite
+        for your own jitdriver if you want to do something special
+        """
+
+    # note: if you overwrite this functions with the above signature it'll
+    #       work, but the *greenargs is different for each jitdriver, so we
+    #       can't share the same methods
+    del on_compile
+    del on_compile_bridge
+
     def _make_extregistryentries(self):
         # workaround: we cannot declare ExtRegistryEntries for functions
         # used as methods of a frozen object, but we can attach the
@@ -477,8 +505,6 @@
                 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")
                 objname, fieldname = name.split('.')   # see test_green_field
                 assert objname in driver.reds
                 i = kwds_i['i_' + objname]
@@ -557,7 +583,7 @@
     def specialize_call(self, hop):
         from pypy.rpython.lltypesystem import lltype
         from pypy.rpython.lltypesystem.rstr import string_repr
-        
+
         hop.exception_cannot_occur()
         driver = self.instance.im_self
         name = hop.args_s[0].const
diff --git a/pypy/rlib/nonconst.py b/pypy/rlib/nonconst.py
--- a/pypy/rlib/nonconst.py
+++ b/pypy/rlib/nonconst.py
@@ -18,6 +18,12 @@
     def __nonzero__(self):
         return bool(self.__dict__['constant'])
 
+    def __eq__(self, other):
+        return self.__dict__['constant'] == other
+
+    def __add__(self, other):
+        return self.__dict__['constant'] + other
+
 class EntryNonConstant(ExtRegistryEntry):
     _about_ = NonConstant
 
diff --git a/pypy/rlib/rbigint.py b/pypy/rlib/rbigint.py
--- a/pypy/rlib/rbigint.py
+++ b/pypy/rlib/rbigint.py
@@ -1345,6 +1345,7 @@
 # XXX make sure that we don't ignore this!
 # YYY no, we decided to do ignore this!
 
+ at jit.dont_look_inside
 def _AsDouble(n):
     """ Get a C double from a bigint object. """
     # This is a "correctly-rounded" version from Python 2.7.
diff --git a/pypy/rlib/rcoroutine.py b/pypy/rlib/rcoroutine.py
--- a/pypy/rlib/rcoroutine.py
+++ b/pypy/rlib/rcoroutine.py
@@ -29,7 +29,7 @@
 The type of a switch is determined by the target's costate.
 """
 
-from pypy.rlib.rstack import yield_current_frame_to_caller, resume_point
+from pypy.rlib.rstack import yield_current_frame_to_caller
 from pypy.rlib.objectmodel import we_are_translated
 
 from pypy.interpreter.error import OperationError
@@ -228,7 +228,6 @@
                         self.thunk = None
                         syncstate.switched(incoming_frame)
                         thunk.call()
-                        resume_point("coroutine__bind", state)
                     except Exception, e:
                         exc = e
                         raise
@@ -257,7 +256,6 @@
                 raise CoroutineDamage
             state = self.costate
             incoming_frame = state.update(self).switch()
-            resume_point("coroutine_switch", state, returns=incoming_frame)
             syncstate.switched(incoming_frame)
 
         def kill(self):
diff --git a/pypy/rlib/rsre/rsre_core.py b/pypy/rlib/rsre/rsre_core.py
--- a/pypy/rlib/rsre/rsre_core.py
+++ b/pypy/rlib/rsre/rsre_core.py
@@ -759,17 +759,27 @@
 @specializectx
 def find_repetition_end(ctx, ppos, ptr, maxcount):
     end = ctx.end
-    if maxcount <= 1:
-        if maxcount == 1 and ptr < end:
-            # Relatively common case: maxcount == 1.  If we are not at the
-            # end of the string, it's done by a single direct check.
-            op = ctx.pat(ppos)
-            for op1, checkerfn in unroll_char_checker:
-                if op1 == op:
-                    if checkerfn(ctx, ptr, ppos):
-                        return ptr + 1
+    ptrp1 = ptr + 1
+    # First get rid of the cases where we don't have room for any match.
+    if maxcount <= 0 or ptrp1 > end:
         return ptr
-    elif maxcount != 65535:
+    # Check the first character directly.  If it doesn't match, we are done.
+    # The idea is to be fast for cases like re.search("b+"), where we expect
+    # the common case to be a non-match.  It's much faster with the JIT to
+    # have the non-match inlined here rather than detect it in the fre() call.
+    op = ctx.pat(ppos)
+    for op1, checkerfn in unroll_char_checker:
+        if op1 == op:
+            if checkerfn(ctx, ptr, ppos):
+                break
+    else:
+        return ptr
+    # It matches at least once.  If maxcount == 1 (relatively common),
+    # then we are done.
+    if maxcount == 1:
+        return ptrp1
+    # Else we really need to count how many times it matches.
+    if maxcount != 65535:
         # adjust end
         end1 = ptr + maxcount
         if end1 <= end:
@@ -777,7 +787,7 @@
     op = ctx.pat(ppos)
     for op1, fre in unroll_fre_checker:
         if op1 == op:
-            return fre(ctx, ptr, end, ppos)
+            return fre(ctx, ptrp1, end, ppos)
     raise Error("rsre.find_repetition_end[%d]" % op)
 
 @specializectx
diff --git a/pypy/rlib/rsre/test/test_zjit.py b/pypy/rlib/rsre/test/test_zjit.py
--- a/pypy/rlib/rsre/test/test_zjit.py
+++ b/pypy/rlib/rsre/test/test_zjit.py
@@ -160,3 +160,9 @@
         res = self.meta_interp_match(r"<[\S ]+>", "<..a   .. aa>")
         assert res == 13
         self.check_enter_count(1)
+
+
+    def test_find_repetition_end_fastpath(self):
+        res = self.meta_interp_search(r"b+", "a"*30 + "b")
+        assert res == 30
+        self.check_loops(call=0)
diff --git a/pypy/rlib/rstack.py b/pypy/rlib/rstack.py
--- a/pypy/rlib/rstack.py
+++ b/pypy/rlib/rstack.py
@@ -42,16 +42,26 @@
                            sandboxsafe=True, _nowrapper=True,
                            _callable=_callable)
 
-_stack_get_start = llexternal('LL_stack_get_start', [], lltype.Signed,
-                              lambda: 0)
+_stack_get_end = llexternal('LL_stack_get_end', [], lltype.Signed,
+                            lambda: 0)
 _stack_get_length = llexternal('LL_stack_get_length', [], lltype.Signed,
                                lambda: 1)
+_stack_set_length_fraction = llexternal('LL_stack_set_length_fraction',
+                                        [lltype.Float], lltype.Void,
+                                        lambda frac: None)
 _stack_too_big_slowpath = llexternal('LL_stack_too_big_slowpath',
                                      [lltype.Signed], lltype.Char,
                                      lambda cur: '\x00')
 # the following is used by the JIT
-_stack_get_start_adr = llexternal('LL_stack_get_start_adr', [], lltype.Signed)
+_stack_get_end_adr   = llexternal('LL_stack_get_end_adr',   [], lltype.Signed)
+_stack_get_length_adr= llexternal('LL_stack_get_length_adr',[], lltype.Signed)
 
+# the following is also used by the JIT: "critical code" paths are paths in
+# which we should not raise StackOverflow at all, but just ignore the stack limit
+_stack_criticalcode_start = llexternal('LL_stack_criticalcode_start', [],
+                                       lltype.Void, lambda: None)
+_stack_criticalcode_stop = llexternal('LL_stack_criticalcode_stop', [],
+                                      lltype.Void, lambda: None)
 
 def stack_check():
     if not we_are_translated():
@@ -62,13 +72,13 @@
     current = llop.stack_current(lltype.Signed)
     #
     # Load these variables from C code
-    start = _stack_get_start()
+    end = _stack_get_end()
     length = _stack_get_length()
     #
-    # Common case: if 'current' is within [start:start+length], everything
+    # Common case: if 'current' is within [end-length:end], everything
     # is fine
-    ofs = r_uint(current - start)
-    if ofs < r_uint(length):
+    ofs = r_uint(end - current)
+    if ofs <= r_uint(length):
         return
     #
     # Else call the slow path
@@ -140,111 +150,6 @@
         return var
 
 
-def resume_point(label, *args, **kwds):
-    pass
-
-
-
-class ResumePointFnEntry(ExtRegistryEntry):
-    _about_ = resume_point
-
-    def compute_result_annotation(self, s_label, *args_s, **kwds_s):
-        from pypy.annotation import model as annmodel
-        return annmodel.s_None
-
-    def specialize_call(self, hop, **kwds_i):
-        from pypy.rpython.lltypesystem import lltype
-        from pypy.objspace.flow import model
-
-        assert hop.args_s[0].is_constant()
-        c_label = hop.inputconst(lltype.Void, hop.args_s[0].const)
-        args_v = hop.args_v[1:]
-        if 'i_returns' in kwds_i:
-            assert len(kwds_i) == 1
-            returns_index = kwds_i['i_returns']
-            v_return = args_v.pop(returns_index-1)
-            assert isinstance(v_return, model.Variable), \
-                   "resume_point returns= argument must be a Variable"
-        else:
-            assert not kwds_i
-            v_return = hop.inputconst(lltype.Void, None)
-
-        for v in args_v:
-            assert isinstance(v, model.Variable), "resume_point arguments must be Variables"
-
-        hop.exception_is_here()
-        return hop.genop('resume_point', [c_label, v_return] + args_v,
-                         hop.r_result)
-
-def resume_state_create(prevstate, label, *args):
-    raise RuntimeError("cannot resume states in non-translated versions")
-
-def concretify_argument(hop, index):
-    from pypy.objspace.flow import model
-
-    v_arg = hop.args_v[index]
-    if isinstance(v_arg, model.Variable):
-        return v_arg
-
-    r_arg = hop.rtyper.bindingrepr(v_arg)
-    return hop.inputarg(r_arg, arg=index)
-
-class ResumeStateCreateFnEntry(FrameStackTopReturningFnEntry):
-    _about_ = resume_state_create
-
-    def compute_result_annotation(self, s_prevstate, s_label, *args_s):
-        return FrameStackTopReturningFnEntry.compute_result_annotation(self)
-
-    def specialize_call(self, hop):
-        from pypy.rpython.lltypesystem import lltype
-
-        assert hop.args_s[1].is_constant()
-        c_label = hop.inputconst(lltype.Void, hop.args_s[1].const)
-
-        v_state = hop.inputarg(hop.r_result, arg=0)
-
-        args_v = []
-        for i in range(2, len(hop.args_v)):
-            args_v.append(concretify_argument(hop, i))
-
-        hop.exception_is_here()
-        return hop.genop('resume_state_create', [v_state, c_label] + args_v,
-                         hop.r_result)
-
-def resume_state_invoke(type, state, **kwds):
-    raise NotImplementedError("only works in translated versions")
-
-class ResumeStateInvokeFnEntry(ExtRegistryEntry):
-    _about_ = resume_state_invoke
-
-    def compute_result_annotation(self, s_type, s_state, **kwds):
-        from pypy.annotation.bookkeeper import getbookkeeper
-        assert s_type.is_constant()
-        return getbookkeeper().valueoftype(s_type.const)
-
-    def specialize_call(self, hop, **kwds_i):
-        from pypy.rpython.lltypesystem import lltype
-        v_state = hop.args_v[1]
-        
-        if 'i_returning' in kwds_i:
-            assert len(kwds_i) == 1
-            returning_index = kwds_i['i_returning']
-            v_returning = concretify_argument(hop, returning_index)
-            v_raising = hop.inputconst(lltype.Void, None)
-        elif 'i_raising' in kwds_i:
-            assert len(kwds_i) == 1
-            raising_index = kwds_i['i_raising']
-            v_returning = hop.inputconst(lltype.Void, None)
-            v_raising = concretify_argument(hop, raising_index)
-        else:
-            assert not kwds_i
-            v_returning = hop.inputconst(lltype.Void, None)
-            v_raising = hop.inputconst(lltype.Void, None)
-
-        hop.exception_is_here()
-        return hop.genop('resume_state_invoke', [v_state, v_returning, v_raising],
-                         hop.r_result)
-        
 # ____________________________________________________________
 
 def get_stack_depth_limit():
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
@@ -1,6 +1,6 @@
 import py
 from pypy.rlib.jit import virtual_ref, virtual_ref_finish
-from pypy.rlib.jit import vref_None, non_virtual_ref
+from pypy.rlib.jit import vref_None, non_virtual_ref, InvalidVirtualRef
 from pypy.rlib._jit_vref import SomeVRef
 from pypy.annotation import model as annmodel
 from pypy.annotation.annrpython import RPythonAnnotator
@@ -23,18 +23,23 @@
     pass
 
 
-def test_direct_1():
+def test_direct_forced():
     x1 = X()
     vref = virtual_ref(x1)
+    assert vref._state == 'non-forced'
     assert vref() is x1
-    virtual_ref_finish(x1)
+    assert vref._state == 'forced'
+    virtual_ref_finish(vref, x1)
+    assert vref._state == 'forced'
     assert vref() is x1
 
-def test_direct_2():
+def test_direct_invalid():
     x1 = X()
     vref = virtual_ref(x1)
-    virtual_ref_finish(x1)
-    assert vref() is x1
+    assert vref._state == 'non-forced'
+    virtual_ref_finish(vref, x1)
+    assert vref._state == 'invalid'
+    py.test.raises(InvalidVirtualRef, "vref()")
 
 def test_annotate_1():
     def f():
@@ -50,7 +55,7 @@
         x1 = X()
         vref = virtual_ref(x1)
         x2 = vref()
-        virtual_ref_finish(x1)
+        virtual_ref_finish(vref, x1)
         return x2
     a = RPythonAnnotator()
     s = a.build_types(f, [])
@@ -95,7 +100,7 @@
             x1 = X()
             vref = virtual_ref(x1)
             x2 = vref()
-            virtual_ref_finish(x2)
+            virtual_ref_finish(vref, x2)
             return x2
         x = self.interpret(f, [])
         assert self.castable(self.OBJECTTYPE, x)
@@ -119,6 +124,18 @@
         assert lltype.typeOf(x) == self.OBJECTTYPE
         assert not x
 
+    def test_rtype_5(self):
+        def f():
+            vref = virtual_ref(X())
+            try:
+                vref()
+                return 42
+            except InvalidVirtualRef:
+                return -1
+        x = self.interpret(f, [])
+        assert x == 42
+
+
 class TestLLtype(BaseTestVRef, LLRtypeMixin):
     OBJECTTYPE = OBJECTPTR
     def castable(self, TO, var):
diff --git a/pypy/rlib/test/test_debug.py b/pypy/rlib/test/test_debug.py
--- a/pypy/rlib/test/test_debug.py
+++ b/pypy/rlib/test/test_debug.py
@@ -2,7 +2,7 @@
 import py
 from pypy.rlib.debug import check_annotation, make_sure_not_resized
 from pypy.rlib.debug import debug_print, debug_start, debug_stop
-from pypy.rlib.debug import have_debug_prints
+from pypy.rlib.debug import have_debug_prints, debug_offset, debug_flush
 from pypy.rlib.debug import check_nonneg, IntegerCanBeNegative
 from pypy.rlib import debug
 from pypy.rpython.test.test_llinterp import interpret
@@ -60,6 +60,8 @@
             debug_start("mycat")
             debug_print("foo", 2, "bar", x)
             debug_stop("mycat")
+            debug_flush() # does nothing
+            debug_offset() # should not explode at least
             return have_debug_prints()
 
         try:
diff --git a/pypy/rlib/test/test_jit.py b/pypy/rlib/test/test_jit.py
--- a/pypy/rlib/test/test_jit.py
+++ b/pypy/rlib/test/test_jit.py
@@ -52,9 +52,12 @@
         import sys
         
         s = StringIO()
+        prev = sys.stdout
         sys.stdout = s
-        dis.dis(g)
-        sys.stdout = sys.__stdout__
+        try:
+            dis.dis(g)
+        finally:
+            sys.stdout = prev
         x = s.getvalue().find('CALL_FUNCTION')
         assert x != -1
         x = s.getvalue().find('CALL_FUNCTION', x)
diff --git a/pypy/rpython/llinterp.py b/pypy/rpython/llinterp.py
--- a/pypy/rpython/llinterp.py
+++ b/pypy/rpython/llinterp.py
@@ -513,13 +513,6 @@
         from pypy.translator.tool.lltracker import track
         track(*ll_objects)
 
-    def op_debug_pdb(self, *ll_args):
-        if self.llinterpreter.tracer:
-            self.llinterpreter.tracer.flush()
-        print "entering pdb...", ll_args
-        import pdb
-        pdb.set_trace()
-
     def op_debug_assert(self, x, msg):
         assert x, msg
 
@@ -570,15 +563,6 @@
     def op_hint(self, x, hints):
         return x
 
-    def op_resume_point(self, *args):
-        pass
-
-    def op_resume_state_create(self, *args):
-        raise RuntimeError("resume_state_create can not be called.")
-
-    def op_resume_state_invoke(self, *args):
-        raise RuntimeError("resume_state_invoke can not be called.")
-
     def op_decode_arg(self, fname, i, name, vargs, vkwds):
         raise NotImplementedError("decode_arg")
 
diff --git a/pypy/rpython/lltypesystem/ll2ctypes.py b/pypy/rpython/lltypesystem/ll2ctypes.py
--- a/pypy/rpython/lltypesystem/ll2ctypes.py
+++ b/pypy/rpython/lltypesystem/ll2ctypes.py
@@ -20,7 +20,6 @@
 from pypy.rpython.extfunc import ExtRegistryEntry
 from pypy.rlib.objectmodel import Symbolic, ComputedIntSymbolic
 from pypy.tool.uid import fixid
-from pypy.tool.tls import tlsobject
 from pypy.rlib.rarithmetic import r_uint, r_singlefloat, r_longfloat, intmask
 from pypy.annotation import model as annmodel
 from pypy.rpython.llinterp import LLInterpreter, LLException
@@ -28,6 +27,7 @@
 from pypy.rpython import raddress
 from pypy.translator.platform import platform
 from array import array
+from thread import _local as tlsobject
 
 # ____________________________________________________________
 
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
@@ -521,10 +521,6 @@
                                                     RuntimeError)),
     #                               can always unwind, not just if stackless gc
 
-    'resume_point':         LLOp(canraise=(Exception,)),
-    'resume_state_create':  LLOp(canraise=(MemoryError,), canunwindgc=True),
-    'resume_state_invoke':  LLOp(canraise=(Exception, StackException,
-                                           RuntimeError)),
     'stack_frames_depth':   LLOp(sideeffects=False, canraise=(StackException,
                                                               RuntimeError)),
     'stack_switch':         LLOp(canraise=(StackException, RuntimeError)),
@@ -553,7 +549,8 @@
     'debug_start':          LLOp(canrun=True),
     'debug_stop':           LLOp(canrun=True),
     'have_debug_prints':    LLOp(canrun=True),
-    'debug_pdb':            LLOp(),
+    'debug_offset':         LLOp(canrun=True),
+    'debug_flush':          LLOp(canrun=True),
     'debug_assert':         LLOp(tryfold=True),
     'debug_fatalerror':     LLOp(),
     'debug_llinterpcall':   LLOp(canraise=(Exception,)),
diff --git a/pypy/rpython/lltypesystem/lltype.py b/pypy/rpython/lltypesystem/lltype.py
--- a/pypy/rpython/lltypesystem/lltype.py
+++ b/pypy/rpython/lltypesystem/lltype.py
@@ -4,14 +4,16 @@
                                    base_int, normalizedinttype)
 from pypy.rlib.objectmodel import Symbolic
 from pypy.tool.uid import Hashable
-from pypy.tool.tls import tlsobject
 from pypy.tool.identity_dict import identity_dict
 from pypy.tool import leakfinder
 from types import NoneType
 from sys import maxint
 import weakref
 
-TLS = tlsobject()
+class State(object):
+    pass
+
+TLS = State()
 
 class WeakValueDictionary(weakref.WeakValueDictionary):
     """A subclass of weakref.WeakValueDictionary
diff --git a/pypy/rpython/lltypesystem/opimpl.py b/pypy/rpython/lltypesystem/opimpl.py
--- a/pypy/rpython/lltypesystem/opimpl.py
+++ b/pypy/rpython/lltypesystem/opimpl.py
@@ -513,6 +513,12 @@
 def op_debug_stop(category):
     debug.debug_stop(_normalize(category))
 
+def op_debug_offset():
+    return debug.debug_offset()
+
+def op_debug_flush():
+    pass
+
 def op_have_debug_prints():
     return debug.have_debug_prints()
 
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
@@ -237,6 +237,7 @@
         l.length = newsize
     else:
         _ll_list_resize_really(l, newsize)
+_ll_list_resize_ge.oopspec = 'list._resize_ge(l, newsize)'
 
 def _ll_list_resize_le(l, newsize):
     if newsize >= (len(l.items) >> 1) - 5:
diff --git a/pypy/rpython/lltypesystem/rpbc.py b/pypy/rpython/lltypesystem/rpbc.py
--- a/pypy/rpython/lltypesystem/rpbc.py
+++ b/pypy/rpython/lltypesystem/rpbc.py
@@ -198,7 +198,6 @@
         inputargs = [varoftype(t) for t in [Char] + argtypes]
         startblock = Block(inputargs)
         startblock.exitswitch = inputargs[0]
-        #startblock.operations.append(SpaceOperation('debug_pdb', [], varoftype(Void)))
         graph = FunctionGraph("dispatcher", startblock, varoftype(resulttype))
         row_of_graphs = self.callfamily.calltables[shape][index]
         links = []
diff --git a/pypy/rpython/rlist.py b/pypy/rpython/rlist.py
--- a/pypy/rpython/rlist.py
+++ b/pypy/rpython/rlist.py
@@ -568,7 +568,6 @@
     length = l.ll_length()
     l._ll_resize_ge(length+1)           # see "a note about overflows" above
     l.ll_setitem_fast(length, newitem)
-ll_append.oopspec = 'list.append(l, newitem)'
 
 # this one is for the special case of insert(0, x)
 def ll_prepend(l, newitem):
@@ -793,7 +792,6 @@
         raise MemoryError
     l1._ll_resize_ge(newlength)
     ll_arraycopy(l2, l1, 0, len1, len2)
-ll_extend.oopspec = 'list.extend(l1, l2)'
 
 def ll_extend_with_str(lst, s, getstrlen, getstritem):
     return ll_extend_with_str_slice_startonly(lst, s, getstrlen, getstritem, 0)
diff --git a/pypy/tool/memusage/__init__.py b/pypy/tool/memusage/__init__.py
new file mode 100644
diff --git a/pypy/jit/tool/log-template.gnumeric b/pypy/tool/memusage/log-template.gnumeric
rename from pypy/jit/tool/log-template.gnumeric
rename to pypy/tool/memusage/log-template.gnumeric
diff --git a/pypy/jit/tool/log2gnumeric.py b/pypy/tool/memusage/log2gnumeric.py
old mode 100644
new mode 100755
rename from pypy/jit/tool/log2gnumeric.py
rename to pypy/tool/memusage/log2gnumeric.py
--- a/pypy/jit/tool/log2gnumeric.py
+++ b/pypy/tool/memusage/log2gnumeric.py
@@ -1,12 +1,34 @@
 #! /usr/bin/env python
 """
-Usage: log2gnumeric logfile
-
 Produces a logfile.gnumeric file which contains the data extracted from the
 logfile generated with the PYPYLOG env variable.
 
-Currently, it expects log to contain the translation-task and gc-collect
-categories.
+Run your program like this::
+
+    $ PYPYLOG=gc-collect,jit-mem:logfile pypy your-program.py
+
+This will produce "logfile", containing informations about the memory used by
+the GC and the number of loops created/freed by the JIT.
+
+If you want, you can also measure the amout of used memory as seen by the OS
+(the VmRSS) using memusage.py::
+
+    $ PYPYLOG=gc-collect,jit-mem:logfile ./memusage.py -o logfile.vmrss /path/to/pypy your-program.py
+
+log2gnumeric will automatically pick logfile.vmrss, if present.
+
+If you want to compare PyPy to CPython, you can add its VmRSS to the graph, by
+using the -c option.  To produce the .vmrss file, use again ./memusage.py::
+
+    $ ./memusage.py -o cpython.vmrss python your-program.py
+    $ ./log2gnumeric.py -c cpython.vmrss logfile
+
+Note that on CPython it will take a different amout of time to complete, but
+on the graph the plot will be scaled to match the duration of the PyPy run
+(i.e., the two lines will end "at the same time").
+
+If you are benchmarking translate.py, you can add the "translation-task"
+category to the log, by setting PYPYLOG=gc-collect,jit-mem,translation-task.
 
 You can freely edit the graph in log-template.gnumeric: this script will
 create a new file replacing the 'translation-task' and 'gc-collect' sheets.
@@ -18,7 +40,6 @@
 
 
 def main(logname, options):
-    logname = sys.argv[1]
     outname = logname + '.gnumeric'
     data = open(logname).read()
     data = data.replace('\n', '')
@@ -151,11 +172,11 @@
 
 def vmrss_rows(filename, maxtime):
     lines = []
-    if options.cpython_vmrss:
+    if filename:
         try:
             lines = open(filename).readlines()
         except IOError:
-            print 'Warning: cannot find file %s, skipping this sheet'
+            print 'Warning: cannot find file %s, skipping this sheet' % filename
     for row in vmrss_rows_impl(lines, maxtime):
         yield row
 
@@ -171,8 +192,11 @@
 if __name__ == '__main__':
     CLOCK_FACTOR = 1000000000.0 # report GigaTicks instead of Ticks
     parser = optparse.OptionParser(usage="%prog logfile [options]")
+    parser.format_description = lambda fmt: __doc__
+    parser.description = __doc__
     parser.add_option('-c', '--cpython-vmrss', dest='cpython_vmrss', default=None, metavar='FILE', type=str,
                       help='the .vmrss file produced by CPython')
+
     options, args = parser.parse_args()
     if len(args) != 1:
         parser.print_help()
diff --git a/pypy/tool/memusage/memusage.py b/pypy/tool/memusage/memusage.py
new file mode 100755
--- /dev/null
+++ b/pypy/tool/memusage/memusage.py
@@ -0,0 +1,63 @@
+#! /usr/bin/env python
+"""
+Usage: memusage.py [-o filename] command [args...]
+
+Runs a subprocess, and measure its RSS (resident set size) every second.
+At the end, print the maximum RSS measured, and some statistics.
+
+Also writes "filename", reporting every second the RSS.  If filename is not
+given, the output is written to "memusage.log"
+"""
+
+import sys, os, re, time
+
+def parse_args():
+    args = sys.argv[1:]
+    if args[0] == '-o':
+        args.pop(0)
+        outname = args.pop(0)
+    else:
+        outname = 'memusage.log'
+    args[0] # make sure there is at least one argument left
+    return outname, args
+
+try:
+    outname, args = parse_args()
+except IndexError:
+    print >> sys.stderr, __doc__.strip()
+    sys.exit(2)
+
+childpid = os.fork()
+if childpid == 0:
+    os.execvp(args[0], args)
+    sys.exit(1)
+
+r = re.compile("VmRSS:\s*(\d+)")
+
+filename = '/proc/%d/status' % childpid
+rss_max = 0
+rss_sum = 0
+rss_count = 0
+
+f = open(outname, 'w', 0)
+while os.waitpid(childpid, os.WNOHANG)[0] == 0:
+    g = open(filename)
+    s = g.read()
+    g.close()
+    match = r.search(s)
+    if not match:     # VmRSS is missing if the process just finished
+        break
+    rss = int(match.group(1))
+    print >> f, rss
+    if rss > rss_max: rss_max = rss
+    rss_sum += rss
+    rss_count += 1
+    time.sleep(1)
+f.close()
+
+if rss_count > 0:
+    print
+    print 'Memory usage:'
+    print '\tmaximum RSS: %10d kb' % rss_max
+    print '\tmean RSS:    %10d kb' % (rss_sum / rss_count)
+    print '\trun time:    %10d s' % rss_count
diff --git a/pypy/jit/tool/test/test_log2gnumeric.py b/pypy/tool/memusage/test/test_log2gnumeric.py
rename from pypy/jit/tool/test/test_log2gnumeric.py
rename to pypy/tool/memusage/test/test_log2gnumeric.py
--- a/pypy/jit/tool/test/test_log2gnumeric.py
+++ b/pypy/tool/memusage/test/test_log2gnumeric.py
@@ -1,4 +1,4 @@
-from pypy.jit.tool import log2gnumeric
+from pypy.tool.memusage import log2gnumeric
 
 log = """
 [1000] ...
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
@@ -81,7 +81,7 @@
         self.space = space
         self.operr = operr
         self.typename = operr.w_type.getname(space, "?")
-        self.traceback = AppTraceback(space, self.operr.application_traceback)
+        self.traceback = AppTraceback(space, self.operr.get_traceback())
         debug_excs = getattr(operr, 'debug_excs', [])
         if debug_excs:
             self._excinfo = debug_excs[0]
diff --git a/pypy/tool/release/package.py b/pypy/tool/release/package.py
--- a/pypy/tool/release/package.py
+++ b/pypy/tool/release/package.py
@@ -36,6 +36,10 @@
 class PyPyCNotFound(Exception):
     pass
 
+def fix_permissions(basedir):
+    if sys.platform != 'win32':
+        os.system("chmod -R a+rX %s" % basedir)
+
 def package(basedir, name='pypy-nightly', rename_pypy_c='pypy',
             copy_to_dir = None, override_pypy_c = None):
     basedir = py.path.local(basedir)
@@ -93,6 +97,7 @@
         archive = bindir.join(target)
         shutil.copy(str(source), str(archive))
     old_dir = os.getcwd()
+    fix_permissions(builddir)
     try:
         os.chdir(str(builddir))
         #
@@ -117,7 +122,7 @@
             zf.close()
         else:
             archive = str(builddir.join(name + '.tar.bz2'))
-            e = os.system('tar cvjf ' + archive + " " + name)
+            e = os.system('tar --owner=root --group=root --numeric-owner -cvjf ' + archive + " " + name)
             if e:
                 raise OSError('"tar" returned exit status %r' % e)
     finally:
diff --git a/pypy/tool/release/test/test_package.py b/pypy/tool/release/test/test_package.py
--- a/pypy/tool/release/test/test_package.py
+++ b/pypy/tool/release/test/test_package.py
@@ -10,12 +10,15 @@
     if sys.platform == 'win32':
         basename = 'pypy-c.exe'
         rename_pypy_c = 'pypy-c'
+        exe_name_in_archive = 'pypy-c.exe'
     else:
         basename = 'pypy-c'
         rename_pypy_c = 'pypy'
+        exe_name_in_archive = 'bin/pypy'
     pypy_c = py.path.local(pypydir).join('translator', 'goal', basename)
     if not pypy_c.check():
         os.system("echo faked_pypy_c> %s" % (pypy_c,))
+        pypy_c.chmod(0755)
         fake_pypy_c = True
     else:
         fake_pypy_c = False
@@ -25,10 +28,7 @@
         prefix = builddir.join(test)
         cpyver = '%d.%d' % CPYTHON_VERSION[:2]
         assert prefix.join('lib-python', cpyver, 'test').check()
-        if sys.platform == 'win32':
-            assert prefix.join('pypy-c.exe').check()
-        else:
-            assert prefix.join('bin', 'pypy').check()
+        assert prefix.join(exe_name_in_archive).check()
         assert prefix.join('lib_pypy', 'syslog.py').check()
         assert not prefix.join('lib_pypy', 'py').check()
         assert not prefix.join('lib_pypy', 'ctypes_configure').check()
@@ -39,7 +39,14 @@
             assert zh.open('%s/lib_pypy/syslog.py' % test)
         else:
             th = tarfile.open(str(builddir.join('%s.tar.bz2' % test)))
-            assert th.getmember('%s/lib_pypy/syslog.py' % test)
+            syslog = th.getmember('%s/lib_pypy/syslog.py' % test)
+            exe = th.getmember('%s/%s' % (test, exe_name_in_archive))
+            assert syslog.mode == 0644
+            assert exe.mode == 0755
+            assert exe.uname == ''
+            assert exe.gname == ''
+            assert exe.uid == 0
+            assert exe.gid == 0
 
         # the headers file could be not there, because they are copied into
         # trunk/include only during translation
@@ -66,3 +73,26 @@
         test_dir_structure(test='testzipfile')
     finally:
         package.USE_ZIPFILE_MODULE = prev
+
+def test_fix_permissions(tmpdir):
+    def check(f, mode):
+        assert f.stat().mode & 0777 == mode
+    #
+    mydir = tmpdir.join('mydir').ensure(dir=True)
+    bin   = tmpdir.join('bin')  .ensure(dir=True)
+    file1 = tmpdir.join('file1').ensure(file=True)
+    file2 = mydir .join('file2').ensure(file=True)
+    pypy  = bin   .join('pypy') .ensure(file=True)
+    #
+    mydir.chmod(0700)
+    bin.chmod(0700)
+    file1.chmod(0600)
+    file2.chmod(0640)
+    pypy.chmod(0700)
+    #
+    package.fix_permissions(tmpdir)
+    check(mydir, 0755)
+    check(bin,   0755)
+    check(file1, 0644)
+    check(file2, 0644)
+    check(pypy,  0755)
diff --git a/pypy/tool/tls.py b/pypy/tool/tls.py
deleted file mode 100644
--- a/pypy/tool/tls.py
+++ /dev/null
@@ -1,8 +0,0 @@
-
-"""Thread-local storage."""
-
-try:
-    from thread import _local as tlsobject
-except ImportError:
-    class tlsobject(object):
-        pass
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
@@ -541,7 +541,6 @@
               'cast_pointer': 0,
               'malloc': 2,
               'yield_current_frame_to_caller': sys.maxint, # XXX bit extreme
-              'resume_point': sys.maxint, # XXX bit extreme
               'instrument_count': 0,
               'debug_assert': -1,
               }
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
@@ -81,8 +81,6 @@
                     num_removed += 1
                 else:
                     available[key] = op.result
-            elif op.opname == 'resume_point':
-                available.clear()
     if num_removed:
         remove_same_as(graph)
         # remove casts with unused results
diff --git a/pypy/translator/c/funcgen.py b/pypy/translator/c/funcgen.py
--- a/pypy/translator/c/funcgen.py
+++ b/pypy/translator/c/funcgen.py
@@ -705,7 +705,7 @@
         offset = self.expr(op.args[2])
         value = self.expr(op.args[3])
         typename = cdecl(self.db.gettype(TYPE).replace('@', '*@'), '')
-        return "*(((%(typename)s) %(addr)s ) + %(offset)s) = %(value)s;" % locals()
+        return "((%(typename)s) %(addr)s)[%(offset)s] = %(value)s;" % locals()
 
     def OP_RAW_LOAD(self, op):
         addr = self.expr(op.args[0])
@@ -713,7 +713,7 @@
         offset = self.expr(op.args[2])
         result = self.expr(op.result)
         typename = cdecl(self.db.gettype(TYPE).replace('@', '*@'), '')
-        return "%(result)s = *(((%(typename)s) %(addr)s ) + %(offset)s);" % locals()
+        return "%(result)s = ((%(typename)s) %(addr)s)[%(offset)s];" % locals()
 
     def OP_CAST_PRIMITIVE(self, op):
         TYPE = self.lltypemap(op.result)
diff --git a/pypy/translator/c/src/debug_print.c b/pypy/translator/c/src/debug_print.c
--- a/pypy/translator/c/src/debug_print.c
+++ b/pypy/translator/c/src/debug_print.c
@@ -6,6 +6,8 @@
 #include <stdio.h>
 #ifndef _WIN32
 #include <unistd.h>
+#include <time.h>
+#include <sys/time.h>
 #else
 #define WIN32_LEAN_AND_MEAN
 #include <windows.h>
@@ -65,6 +67,15 @@
   debug_ready = 1;
 }
 
+long pypy_debug_offset(void)
+{
+  if (!debug_ready)
+    return -1;
+  // note that we deliberately ignore errno, since -1 is fine
+  // in case this is not a real file
+  return ftell(pypy_debug_file);
+}
+
 void pypy_debug_ensure_opened(void)
 {
   if (!debug_ready)
diff --git a/pypy/translator/c/src/debug_print.h b/pypy/translator/c/src/debug_print.h
--- a/pypy/translator/c/src/debug_print.h
+++ b/pypy/translator/c/src/debug_print.h
@@ -26,8 +26,9 @@
 #define PYPY_DEBUG_FILE           pypy_debug_file
 #define PYPY_DEBUG_START(cat)     pypy_debug_start(cat)
 #define PYPY_DEBUG_STOP(cat)      pypy_debug_stop(cat)
+#define OP_DEBUG_OFFSET(res)      res = pypy_debug_offset()
 #define OP_HAVE_DEBUG_PRINTS(r)   r = (pypy_have_debug_prints & 1)
-
+#define OP_DEBUG_FLUSH() fflush(pypy_debug_file)
 
 /************************************************************/
 
@@ -35,6 +36,7 @@
 void pypy_debug_ensure_opened(void);
 void pypy_debug_start(const char *category);
 void pypy_debug_stop(const char *category);
+long pypy_debug_offset(void);
 
 extern long pypy_have_debug_prints;
 extern FILE *pypy_debug_file;
@@ -51,8 +53,6 @@
 #  ifdef _WIN32
 #    define READ_TIMESTAMP(val) QueryPerformanceCounter((LARGE_INTEGER*)&(val))
 #  else
-#    include <time.h>
-#    include <sys/time.h>
 
 long long pypy_read_timestamp();
 
diff --git a/pypy/translator/c/src/debug_traceback.h b/pypy/translator/c/src/debug_traceback.h
--- a/pypy/translator/c/src/debug_traceback.h
+++ b/pypy/translator/c/src/debug_traceback.h
@@ -21,7 +21,11 @@
    line to the f:17/KeyError line.
 */
 
-#define PYPY_DEBUG_TRACEBACK_DEPTH        128     /* a power of two */
+#ifdef RPY_LL_ASSERT
+#  define PYPY_DEBUG_TRACEBACK_DEPTH        8192    /* a power of two */
+#else
+#  define PYPY_DEBUG_TRACEBACK_DEPTH        128     /* a power of two */
+#endif
 
 #define PYPYDTPOS_RERAISE                 ((struct pypydtpos_s *) -1)
 #define PYPYDTSTORE(loc, etype)                         \
diff --git a/pypy/translator/c/src/float.h b/pypy/translator/c/src/float.h
--- a/pypy/translator/c/src/float.h
+++ b/pypy/translator/c/src/float.h
@@ -43,3 +43,4 @@
 #define OP_CAST_FLOAT_TO_LONGLONG(x,r) r = (long long)(x)
 #define OP_CAST_FLOAT_TO_ULONGLONG(x,r) r = (unsigned long long)(x)
 #endif
+
diff --git a/pypy/translator/c/src/stack.h b/pypy/translator/c/src/stack.h
--- a/pypy/translator/c/src/stack.h
+++ b/pypy/translator/c/src/stack.h
@@ -11,15 +11,22 @@
  * It is needed to have RPyThreadStaticTLS, too. */
 #include "thread.h"
 
-extern char *_LLstacktoobig_stack_start;
+extern char *_LLstacktoobig_stack_end;
+extern long _LLstacktoobig_stack_length;
+extern char _LLstacktoobig_report_error;
 
 void LL_stack_unwind(void);
 char LL_stack_too_big_slowpath(long);    /* returns 0 (ok) or 1 (too big) */
+void LL_stack_set_length_fraction(double);
 
 /* some macros referenced from pypy.rlib.rstack */
-#define LL_stack_get_start() ((long)_LLstacktoobig_stack_start)
-#define LL_stack_get_length() MAX_STACK_SIZE
-#define LL_stack_get_start_adr() ((long)&_LLstacktoobig_stack_start)  /* JIT */
+#define LL_stack_get_end() ((long)_LLstacktoobig_stack_end)
+#define LL_stack_get_length() _LLstacktoobig_stack_length
+#define LL_stack_get_end_adr()    ((long)&_LLstacktoobig_stack_end)   /* JIT */
+#define LL_stack_get_length_adr() ((long)&_LLstacktoobig_stack_length)/* JIT */
+
+#define LL_stack_criticalcode_start()  (_LLstacktoobig_report_error = 0)
+#define LL_stack_criticalcode_stop()   (_LLstacktoobig_report_error = 1)
 
 
 #ifdef __GNUC__
@@ -32,93 +39,67 @@
 #ifndef PYPY_NOT_MAIN_FILE
 #include <stdio.h>
 
-#ifndef PYPY_NOINLINE
-# if defined __GNUC__
-#  define PYPY_NOINLINE __attribute__((noinline))
-# else
-// add hints for other compilers here ...
-#  define PYPY_NOINLINE
-# endif
-#endif
+/* the current stack is in the interval [end-length:end].  We assume a
+   stack that grows downward here. */
+char *_LLstacktoobig_stack_end = NULL;
+long _LLstacktoobig_stack_length = MAX_STACK_SIZE;
+char _LLstacktoobig_report_error = 1;
+static RPyThreadStaticTLS end_tls_key;
 
-long PYPY_NOINLINE _LL_stack_growing_direction(char *parent)
+void LL_stack_set_length_fraction(double fraction)
 {
-	char local;
-	if (parent == NULL)
-		return _LL_stack_growing_direction(&local);
-	else
-		return &local - parent;
+	_LLstacktoobig_stack_length = (long)(MAX_STACK_SIZE * fraction);
 }
 
-char *_LLstacktoobig_stack_start = NULL;
-int stack_direction = 0;
-RPyThreadStaticTLS start_tls_key;
-
 char LL_stack_too_big_slowpath(long current)
 {
-	long diff;
+	long diff, max_stack_size;
 	char *baseptr, *curptr = (char*)current;
 
-	/* The stack_start variable is updated to match the current value
+	/* The stack_end variable is updated to match the current value
 	   if it is still 0 or if we later find a 'curptr' position
-	   that is below it.  The real stack_start pointer is stored in
+	   that is above it.  The real stack_end pointer is stored in
 	   thread-local storage, but we try to minimize its overhead by
-	   keeping a local copy in _LLstacktoobig_stack_start. */
+	   keeping a local copy in _LLstacktoobig_stack_end. */
 
-	if (stack_direction == 0) {
+	if (_LLstacktoobig_stack_end == NULL) {
 		/* not initialized */
 		/* XXX We assume that initialization is performed early,
 		   when there is still only one thread running.  This
 		   allows us to ignore race conditions here */
-		char *errmsg = RPyThreadStaticTLS_Create(&start_tls_key);
+		char *errmsg = RPyThreadStaticTLS_Create(&end_tls_key);
 		if (errmsg) {
 			/* XXX should we exit the process? */
 			fprintf(stderr, "Internal PyPy error: %s\n", errmsg);
 			return 1;
 		}
-		if (_LL_stack_growing_direction(NULL) > 0)
-			stack_direction = +1;
-		else
-			stack_direction = -1;
 	}
 
-	baseptr = (char *) RPyThreadStaticTLS_Get(start_tls_key);
-	if (baseptr != NULL) {
-		diff = curptr - baseptr;
-		if (((unsigned long)diff) < (unsigned long)MAX_STACK_SIZE) {
+	baseptr = (char *) RPyThreadStaticTLS_Get(end_tls_key);
+	max_stack_size = _LLstacktoobig_stack_length;
+	if (baseptr == NULL) {
+		/* first time we see this thread */
+	}
+	else {
+		diff = baseptr - curptr;
+		if (((unsigned long)diff) <= (unsigned long)max_stack_size) {
 			/* within bounds, probably just had a thread switch */
-			_LLstacktoobig_stack_start = baseptr;
+			_LLstacktoobig_stack_end = baseptr;
 			return 0;
 		}
-
-		if (stack_direction > 0) {
-			if (diff < 0 && diff > -MAX_STACK_SIZE)
-				;           /* stack underflow */
-			else
-				return 1;   /* stack overflow (probably) */
+		if (((unsigned long)-diff) <= (unsigned long)max_stack_size) {
+			/* stack underflowed: the initial estimation of
+			   the stack base must be revised */
 		}
-		else {
-			if (diff >= MAX_STACK_SIZE && diff < 2*MAX_STACK_SIZE)
-				;           /* stack underflow */
-			else
-				return 1;   /* stack overflow (probably) */
+		else {	/* stack overflow (probably) */
+			return _LLstacktoobig_report_error;
 		}
-		/* else we underflowed the stack, which means that
-		   the initial estimation of the stack base must
-		   be revised */
 	}
 
 	/* update the stack base pointer to the current value */
-	if (stack_direction > 0) {
-		/* the valid range is [curptr:curptr+MAX_STACK_SIZE] */
-		baseptr = curptr;
-	}
-	else {
-		/* the valid range is [curptr-MAX_STACK_SIZE+1:curptr+1] */
-		baseptr = curptr - MAX_STACK_SIZE + 1;
-	}
-	RPyThreadStaticTLS_Set(start_tls_key, baseptr);
-	_LLstacktoobig_stack_start = baseptr;
+	baseptr = curptr;
+	RPyThreadStaticTLS_Set(end_tls_key, baseptr);
+	_LLstacktoobig_stack_end = baseptr;
 	return 0;
 }
 
diff --git a/pypy/translator/c/test/test_standalone.py b/pypy/translator/c/test/test_standalone.py
--- a/pypy/translator/c/test/test_standalone.py
+++ b/pypy/translator/c/test/test_standalone.py
@@ -3,8 +3,8 @@
 
 from pypy.rlib.objectmodel import keepalive_until_here
 from pypy.rlib.rarithmetic import r_longlong
-from pypy.rlib.debug import ll_assert, have_debug_prints
-from pypy.rlib.debug import debug_print, debug_start, debug_stop
+from pypy.rlib.debug import ll_assert, have_debug_prints, debug_flush
+from pypy.rlib.debug import debug_print, debug_start, debug_stop, debug_offset
 from pypy.translator.translator import TranslationContext
 from pypy.translator.backendopt import all
 from pypy.translator.c.genc import CStandaloneBuilder, ExternalCompilationInfo
@@ -110,6 +110,7 @@
         assert counters == (0,3,2)
 
     def test_prof_inline(self):
+        py.test.skip("broken by 5b0e029514d4, but we don't use it any more")
         if sys.platform == 'win32':
             py.test.skip("instrumentation support is unix only for now")
         def add(a,b):
@@ -163,13 +164,13 @@
             return 0
         from pypy.translator.interactive import Translation
         # XXX this is mostly a "does not crash option"
-        t = Translation(entry_point, backend='c', standalone=True, profopt="")
+        t = Translation(entry_point, backend='c', standalone=True, profopt="100")
         # no counters
         t.backendopt()
         exe = t.compile()
         out = py.process.cmdexec("%s 500" % exe)
         assert int(out) == 500*501/2
-        t = Translation(entry_point, backend='c', standalone=True, profopt="",
+        t = Translation(entry_point, backend='c', standalone=True, profopt="100",
                         noprofopt=True)
         # no counters
         t.backendopt()
@@ -283,12 +284,13 @@
             debug_stop   ("mycat")
             if have_debug_prints(): x += "a"
             debug_print("toplevel")
-            os.write(1, x + '.\n')
+            debug_flush()
+            os.write(1, x + "." + str(debug_offset()) + '.\n')
             return 0
         t, cbuilder = self.compile(entry_point)
         # check with PYPYLOG undefined
         out, err = cbuilder.cmdexec("", err=True, env={})
-        assert out.strip() == 'got:a.'
+        assert out.strip() == 'got:a.-1.'
         assert 'toplevel' in err
         assert 'mycat' not in err
         assert 'foo 2 bar 3' not in err
@@ -297,7 +299,7 @@
         assert 'bok' not in err
         # check with PYPYLOG defined to an empty string (same as undefined)
         out, err = cbuilder.cmdexec("", err=True, env={'PYPYLOG': ''})
-        assert out.strip() == 'got:a.'
+        assert out.strip() == 'got:a.-1.'
         assert 'toplevel' in err
         assert 'mycat' not in err
         assert 'foo 2 bar 3' not in err
@@ -306,7 +308,7 @@
         assert 'bok' not in err
         # check with PYPYLOG=:- (means print to stderr)
         out, err = cbuilder.cmdexec("", err=True, env={'PYPYLOG': ':-'})
-        assert out.strip() == 'got:bcda.'
+        assert out.strip() == 'got:bcda.-1.'
         assert 'toplevel' in err
         assert '{mycat' in err
         assert 'mycat}' in err
@@ -319,7 +321,8 @@
         path = udir.join('test_debug_xxx.log')
         out, err = cbuilder.cmdexec("", err=True,
                                     env={'PYPYLOG': ':%s' % path})
-        assert out.strip() == 'got:bcda.'
+        size = os.stat(str(path)).st_size
+        assert out.strip() == 'got:bcda.' + str(size) + '.'
         assert not err
         assert path.check(file=1)
         data = path.read()
@@ -334,7 +337,8 @@
         # check with PYPYLOG=somefilename
         path = udir.join('test_debug_xxx_prof.log')
         out, err = cbuilder.cmdexec("", err=True, env={'PYPYLOG': str(path)})
-        assert out.strip() == 'got:a.'
+        size = os.stat(str(path)).st_size
+        assert out.strip() == 'got:a.' + str(size) + '.'
         assert not err
         assert path.check(file=1)
         data = path.read()
@@ -350,7 +354,8 @@
         path = udir.join('test_debug_xxx_myc.log')
         out, err = cbuilder.cmdexec("", err=True,
                                     env={'PYPYLOG': 'myc:%s' % path})
-        assert out.strip() == 'got:bda.'
+        size = os.stat(str(path)).st_size
+        assert out.strip() == 'got:bda.' + str(size) + '.'
         assert not err
         assert path.check(file=1)
         data = path.read()
@@ -365,7 +370,8 @@
         path = udir.join('test_debug_xxx_cat.log')
         out, err = cbuilder.cmdexec("", err=True,
                                     env={'PYPYLOG': 'cat:%s' % path})
-        assert out.strip() == 'got:ca.'
+        size = os.stat(str(path)).st_size
+        assert out.strip() == 'got:ca.' + str(size) + '.'
         assert not err
         assert path.check(file=1)
         data = path.read()
@@ -379,7 +385,8 @@
         path = udir.join('test_debug_xxx_myc_cat2.log')
         out, err = cbuilder.cmdexec("", err=True,
                                     env={'PYPYLOG': 'myc,cat2:%s' % path})
-        assert out.strip() == 'got:bcda.'
+        size = os.stat(str(path)).st_size
+        assert out.strip() == 'got:bcda.' + str(size) + '.'
         assert not err
         assert path.check(file=1)
         data = path.read()
@@ -400,7 +407,7 @@
         path = udir.join('test_debug_does_not_show_up.log')
         out, err = cbuilder.cmdexec("", err=True,
                                     env={'PYPYLOG': ':%s' % path})
-        assert out.strip() == 'got:.'
+        assert out.strip() == 'got:.-1.'
         assert not err
         assert path.check(file=0)
 
@@ -682,6 +689,78 @@
         out = cbuilder.cmdexec("")
         assert out.strip() == "hi!"
 
+    def test_set_length_fraction(self):
+        # check for pypy.rlib.rstack._stack_set_length_fraction()
+        from pypy.rlib.rstack import _stack_set_length_fraction
+        from pypy.rlib.rstackovf import StackOverflow
+        class A:
+            n = 0
+        glob = A()
+        def f(n):
+            glob.n += 1
+            if n <= 0:
+                return 42
+            return f(n+1)
+        def entry_point(argv):
+            _stack_set_length_fraction(0.1)
+            try:
+                return f(1)
+            except StackOverflow:
+                glob.n = 0
+            _stack_set_length_fraction(float(argv[1]))
+            try:
+                return f(1)
+            except StackOverflow:
+                print glob.n
+                return 0
+        t, cbuilder = self.compile(entry_point, stackcheck=True)
+        counts = {}
+        for fraction in [0.1, 0.4, 1.0]:
+            out = cbuilder.cmdexec(str(fraction))
+            print 'counts[%s]: %r' % (fraction, out)
+            counts[fraction] = int(out.strip())
+        #
+        assert counts[1.0] >= 1000
+        # ^^^ should actually be much more than 1000 for this small test
+        assert counts[0.1] < counts[0.4] / 3
+        assert counts[0.4] < counts[1.0] / 2
+        assert counts[0.1] > counts[0.4] / 7
+        assert counts[0.4] > counts[1.0] / 4
+
+    def test_stack_criticalcode(self):
+        # check for pypy.rlib.rstack._stack_criticalcode_start/stop()
+        from pypy.rlib.rstack import _stack_criticalcode_start
+        from pypy.rlib.rstack import _stack_criticalcode_stop
+        from pypy.rlib.rstackovf import StackOverflow
+        class A:
+            pass
+        glob = A()
+        def f(n):
+            if n <= 0:
+                return 42
+            try:
+                return f(n+1)
+            except StackOverflow:
+                if glob.caught:
+                    print 'Oups! already caught!'
+                glob.caught = True
+                _stack_criticalcode_start()
+                critical(100)   # recurse another 100 times here
+                _stack_criticalcode_stop()
+                return 789
+        def critical(n):
+            if n > 0:
+                n = critical(n - 1)
+            return n - 42
+        def entry_point(argv):
+            glob.caught = False
+            print f(1)
+            return 0
+        t, cbuilder = self.compile(entry_point, stackcheck=True)
+        out = cbuilder.cmdexec('')
+        assert out.strip() == '789'
+
+
 class TestMaemo(TestStandalone):
     def setup_class(cls):
         py.test.skip("TestMaemo: tests skipped for now")
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
@@ -77,7 +77,6 @@
     'cast_ptr_to_weakadr':      [PushAllArgs, 'newobj instance void class %s::.ctor(object)' % WEAKREF],
     'gc__collect':              'call void class [mscorlib]System.GC::Collect()',
     'gc_set_max_heap_size':     Ignore,
-    'resume_point':             Ignore,
     'debug_assert':             Ignore,
     'debug_start_traceback':    Ignore,
     'debug_record_traceback':   Ignore,
@@ -85,6 +84,8 @@
     'debug_reraise_traceback':  Ignore,
     'debug_print_traceback':    Ignore,
     'debug_print':              [DebugPrint],
+    'debug_flush':              [PushAllArgs, 'call void [pypylib]pypy.runtime.DebugPrint::DEBUG_FLUSH()'],
+    'debug_offset':             [PushAllArgs, 'call int32 [pypylib]pypy.runtime.DebugPrint::DEBUG_OFFSET()'],
     'debug_start':              [PushAllArgs, 'call void [pypylib]pypy.runtime.DebugPrint::DEBUG_START(string)'],
     'debug_stop':               [PushAllArgs, 'call void [pypylib]pypy.runtime.DebugPrint::DEBUG_STOP(string)'],
     'have_debug_prints':        [PushAllArgs, 'call bool [pypylib]pypy.runtime.DebugPrint::HAVE_DEBUG_PRINTS()'],
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
@@ -38,6 +38,20 @@
             return false;
         }
 
+        public static void DEBUG_FLUSH()
+        {
+            if (debug_file != null)
+                debug_file.Flush();
+        }
+
+        public static int DEBUG_OFFSET()
+        {
+            StreamWriter sw = debug_file as StreamWriter;
+            if (sw == null)
+                return -1;
+            return (int)sw.BaseStream.Position; // XXX: the cast might be incorrect
+        }
+
         public static bool HAVE_DEBUG_PRINTS()
         {
             if ((have_debug_prints & 1) != 0) {
diff --git a/pypy/translator/goal/targetnumpystandalone.py b/pypy/translator/goal/targetnumpystandalone.py
new file mode 100644
--- /dev/null
+++ b/pypy/translator/goal/targetnumpystandalone.py
@@ -0,0 +1,57 @@
+
+""" Usage:
+
+./targetnumpystandalone-c <bytecode> array_size
+
+Will execute a give numpy bytecode. Arrays will be ranges (in float) modulo 10,
+constants would be consecutive starting from one.
+
+Bytecode should contain letters 'a' 'l' and 'f' so far and be correct
+"""
+
+import time
+from pypy.module.micronumpy.numarray import SingleDimArray, Code, compute
+from pypy.jit.codewriter.policy import JitPolicy
+
+def create_array(size):
+    a = SingleDimArray(size)
+    for i in range(size):
+        a.storage[i] = float(i % 10)
+    return a
+
+def entry_point(argv):
+    if len(argv) != 3:
+        print __doc__
+        return 1
+    bytecode = argv[1]
+    for b in bytecode:
+        if b not in 'alf':
+            print "WRONG BYTECODE"
+            print __doc__
+            return 2
+    try:
+        size = int(argv[2])
+    except ValueError:
+        print "INVALID LITERAL FOR INT:", argv[2]
+        print __doc__
+        return 3
+    no_arrays = bytecode.count('l')
+    no_floats = bytecode.count('f')
+    arrays = []
+    floats = []
+    for i in range(no_arrays):
+        arrays.append(create_array(size))
+    for i in range(no_floats):
+        floats.append(float(i + 1))
+    code = Code(bytecode, arrays, floats)
+    t0 = time.time()
+    compute(code)
+    print "bytecode:", bytecode, "size:", size
+    print "took:", time.time() - t0
+    return 0
+
+def target(*args):
+    return entry_point, None
+
+def jitpolicy(driver):
+    return JitPolicy()
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,7 +105,8 @@
         return parser
 
     def handle_config(self, config, translateconfig):
-        if translateconfig._cfgimpl_value_owners['opt'] == 'default':
+        if (not translateconfig.help and
+            translateconfig._cfgimpl_value_owners['opt'] == 'default'):
             raise Exception("You have to specify the --opt level.\n"
                     "Try --opt=2 or --opt=jit, or equivalently -O2 or -Ojit .")
         self.translateconfig = translateconfig
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
@@ -95,7 +95,6 @@
 
     'gc__collect':              jvm.SYSTEMGC,
     'gc_set_max_heap_size':     Ignore,
-    'resume_point':             Ignore,
     'jit_marker':               Ignore,
     'jit_force_virtualizable':  Ignore,
     'jit_force_virtual':        DoNothing,
diff --git a/pypy/translator/oosupport/test_template/operations.py b/pypy/translator/oosupport/test_template/operations.py
--- a/pypy/translator/oosupport/test_template/operations.py
+++ b/pypy/translator/oosupport/test_template/operations.py
@@ -107,12 +107,6 @@
             return res
         assert self.interpret(fn, [sys.maxint, 2]) == 1
 
-    def test_ignore_resume_point(self):
-        def fn(x):
-            rstack.resume_point('hello world', x)
-            return x
-        assert self.interpret(fn, [42]) == 42
-
     def test_rshift(self):
         def fn(x, y):
             return x >> y
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
@@ -129,7 +129,9 @@
         m.cfiles = rel_cfiles
 
         rel_includedirs = [pypyrel(incldir) for incldir in
-                           self._preprocess_include_dirs(eci.include_dirs)]
+                           self.preprocess_include_dirs(eci.include_dirs)]
+        rel_libdirs = [pypyrel(libdir) for libdir in
+                       self.preprocess_library_dirs(eci.library_dirs)]
 
         m.comment('automatically generated makefile')
         definitions = [
@@ -139,7 +141,7 @@
             ('SOURCES', rel_cfiles),
             ('OBJECTS', rel_ofiles),
             ('LIBS', self._libs(eci.libraries)),
-            ('LIBDIRS', self._libdirs(eci.library_dirs)),
+            ('LIBDIRS', self._libdirs(rel_libdirs)),
             ('INCLUDEDIRS', self._includedirs(rel_includedirs)),
             ('CFLAGS', cflags),
             ('CFLAGSEXTRA', list(eci.compile_extra)),
diff --git a/pypy/translator/platform/test/test_posix.py b/pypy/translator/platform/test/test_posix.py
--- a/pypy/translator/platform/test/test_posix.py
+++ b/pypy/translator/platform/test/test_posix.py
@@ -3,7 +3,7 @@
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
 from pypy.tool.udir import udir
 from StringIO import StringIO
-import sys
+import sys, os
 
 def test_echo():
     res = host.execute('echo', '42 24')
@@ -49,6 +49,19 @@
         mk.write()
         assert 'LINKFILES = /foo/bar.a' in tmpdir.join('Makefile').read()
 
+    def test_preprocess_localbase(self):
+        tmpdir = udir.join('test_preprocess_localbase').ensure(dir=1)
+        eci = ExternalCompilationInfo()
+        os.environ['PYPY_LOCALBASE'] = '/foo/baz'
+        try:
+            mk = self.platform.gen_makefile(['blip.c'], eci, path=tmpdir)
+            mk.write()
+        finally:
+            del os.environ['PYPY_LOCALBASE']
+        Makefile = tmpdir.join('Makefile').read()
+        assert 'INCLUDEDIRS = -I/foo/baz/include' in Makefile
+        assert 'LIBDIRS = -L/foo/baz/lib' in Makefile
+
 class TestMaemo(TestMakefile):
     strict_on_stderr = False
     
diff --git a/pypy/translator/stackless/frame.py b/pypy/translator/stackless/frame.py
--- a/pypy/translator/stackless/frame.py
+++ b/pypy/translator/stackless/frame.py
@@ -104,10 +104,8 @@
 
 class RestartInfo(object):
 
-    """A RestartInfo is created (briefly) for each graph that contains
-    a resume point.
-
-    In addition, a RestartInfo is created for each function that needs
+    """
+    A RestartInfo is created for each function that needs
     to do explicit stackless manipulations
     (e.g. code.yield_current_frame_to_caller)."""
 
diff --git a/pypy/translator/stackless/test/test_coroutine_reconstruction.py b/pypy/translator/stackless/test/test_coroutine_reconstruction.py
deleted file mode 100644
--- a/pypy/translator/stackless/test/test_coroutine_reconstruction.py
+++ /dev/null
@@ -1,68 +0,0 @@
-from pypy.rlib import rcoroutine
-from pypy.rlib import rstack
-from pypy.rlib.rstack import resume_state_create
-from pypy.translator.stackless.test.test_transform import llinterp_stackless_function
-from pypy.rpython.lltypesystem.lloperation import llop
-from pypy.rpython.lltypesystem import lltype
-
-namespace = rcoroutine.make_coroutine_classes(object)
-syncstate = namespace['syncstate']
-AbstractThunk = namespace['AbstractThunk']
-Coroutine = namespace['Coroutine']
-
-class TestCoroutineReconstruction:
-
-    def setup_meth(self):
-        syncstate.reset()
-
-    def test_simple_ish(self):
-
-        output = []
-        def f(coro, n, x):
-            if n == 0:
-                coro.switch()
-                rstack.resume_point("f_0")
-                assert rstack.stack_frames_depth() == 9
-                return
-            f(coro, n-1, 2*x)
-            rstack.resume_point("f_1", coro, n, x)
-            output.append(x)
-
-        class T(AbstractThunk):
-            def __init__(self, arg_coro, arg_n, arg_x):
-                self.arg_coro = arg_coro
-                self.arg_n = arg_n
-                self.arg_x = arg_x
-            def call(self):
-                f(self.arg_coro, self.arg_n, self.arg_x)
-
-        def example():
-            main_coro = Coroutine.getcurrent()
-            sub_coro = Coroutine()
-            thunk_f = T(main_coro, 5, 1)
-            sub_coro.bind(thunk_f)
-            sub_coro.switch()
-
-            new_coro = Coroutine()
-            new_thunk_f = T(main_coro, 5, 1)
-            new_coro.bind(new_thunk_f)
-
-            costate = Coroutine._get_default_costate()
-            bottom = resume_state_create(None, "yield_current_frame_to_caller_1")
-            _bind_frame = resume_state_create(bottom, "coroutine__bind", costate)
-            f_frame_1 = resume_state_create(_bind_frame, "f_1", main_coro, 5, 1)
-            f_frame_2 = resume_state_create(f_frame_1, "f_1", main_coro, 4, 2)
-            f_frame_3 = resume_state_create(f_frame_2, "f_1", main_coro, 3, 4)
-            f_frame_4 = resume_state_create(f_frame_3, "f_1", main_coro, 2, 8)
-            f_frame_5 = resume_state_create(f_frame_4, "f_1", main_coro, 1, 16)
-            f_frame_0 = resume_state_create(f_frame_5, "f_0")
-            switch_frame = resume_state_create(f_frame_0, "coroutine_switch", costate)
-
-            new_coro.frame = switch_frame
-
-            new_coro.switch()
-            return output == [16, 8, 4, 2, 1]
-
-        res = llinterp_stackless_function(example)
-        assert res == 1
-
diff --git a/pypy/translator/stackless/test/test_resume_point.py b/pypy/translator/stackless/test/test_resume_point.py
deleted file mode 100644
--- a/pypy/translator/stackless/test/test_resume_point.py
+++ /dev/null
@@ -1,457 +0,0 @@
-from pypy.translator.stackless.transform import StacklessTransformer
-from pypy.translator.stackless.test.test_transform import llinterp_stackless_function, rtype_stackless_function, one, run_stackless_function
-from pypy import conftest
-import py
-from pypy.rlib import rstack
-
-def do_backendopt(t):
-    from pypy.translator.backendopt import all
-    all.backend_optimizations(t)
-
-def transform_stackless_function(fn, callback_for_transform=None):
-    def wrapper(argv):
-        return fn()
-    t = rtype_stackless_function(wrapper)
-    if callback_for_transform:
-        callback_for_transform(t)
-    if conftest.option.view:
-        t.view()
-    st = StacklessTransformer(t, wrapper, False)
-    st.transform_all()
-
-def test_no_call():
-    def f(x, y):
-        x = x-1
-        rstack.resume_point("rp0", x, y) 
-        r = x+y
-        rstack.stack_unwind()
-        return r
-    def example():
-        v1 = f(one(),one()+one())
-        state = rstack.resume_state_create(None, "rp0", one(), one()+one()+one())
-        v2 = rstack.resume_state_invoke(int, state)
-        return v1*10 + v2
-##     transform_stackless_function(example)
-    res = llinterp_stackless_function(example, assert_unwind=False)
-    assert res == 24
-
-def test_bogus_restart_state_create():
-    def f(x, y):
-        x = x-1
-        rstack.resume_point("rp0", x, y) 
-        return x+y
-    def example():
-        v1 = f(one(),one()+one())
-        state = rstack.resume_state_create(None, "rp0", one())
-        return v1
-    info = py.test.raises(AssertionError, "transform_stackless_function(example)")
-    assert 'rp0' in str(info.value)
-    
-
-def test_call():
-    def g(x,y):
-        return x*y
-    def f(x, y):
-        z = g(x,y)
-        rstack.resume_point("rp1", y, returns=z) 
-        return z+y
-    def example():
-        v1 = f(one(),one()+one())
-        s = rstack.resume_state_create(None, "rp1", 5*one())
-        v2 = rstack.resume_state_invoke(int, s, returning=one()*7)
-        return v1*100 + v2
-    res = llinterp_stackless_function(example)
-    assert res == 412
-    res = run_stackless_function(example)
-    assert res == 412
-
-def test_returns_with_instance():
-    class C:
-        def __init__(self, x):
-            self.x = x
-    def g(x):
-        return C(x+1)
-    def f(x, y):
-        r = g(x)
-        rstack.resume_point("rp1", y, returns=r)
-        return r.x + y
-    def example():
-        v1 = f(one(),one()+one())
-        s = rstack.resume_state_create(None, "rp1", 5*one())
-        v2 = rstack.resume_state_invoke(int, s, returning=C(one()*3))
-        return v1*100 + v2
-    res = llinterp_stackless_function(example, assert_unwind=False)
-    assert res == 408
-    res = run_stackless_function(example)
-    assert res == 408
-
-def test_call_uncovered():
-    def g(x,y):
-        return x*y
-    def f(x, y):
-        z = g(x,y)
-        rstack.resume_point("rp1", y, returns=z)
-        return z+y+x
-    def example():
-        f(one(),one()+one())
-        return 0
-    e = py.test.raises(Exception, transform_stackless_function, example)
-    msg, = e.value.args
-    assert msg.startswith('not covered needed value at resume_point') and 'rp1' in msg
-
-def test_chained_states():
-    def g(x, y):
-        x += 1
-        rstack.resume_point("rp1", x, y)
-        return x + y
-    def f(x, y, z):
-        y += 1
-        r = g(x, y)
-        rstack.resume_point("rp2", z, returns=r)
-        return r + z
-    def example():
-        v1 = f(one(), 2*one(), 3*one())
-        s2 = rstack.resume_state_create(None, "rp2", 2*one())
-        s1 = rstack.resume_state_create(s2, "rp1", 4*one(), 5*one())
-        return 100*v1 + rstack.resume_state_invoke(int, s1)
-    res = llinterp_stackless_function(example)
-    assert res == 811
-    res = run_stackless_function(example)
-    assert res == 811
-
-def test_return_instance():
-    class C:
-        pass
-    def g(x):
-        c = C()
-        c.x = x + 1
-        rstack.resume_point("rp1", c)
-        return c
-    def f(x, y):
-        r = g(x)
-        rstack.resume_point("rp2", y, returns=r)
-        return r.x + y
-    def example():
-        v1 = f(one(), 2*one())
-        s2 = rstack.resume_state_create(None, "rp2", 2*one())
-        c = C()
-        c.x = 4*one()
-        s1 = rstack.resume_state_create(s2, "rp1", c)
-        return v1*100 + rstack.resume_state_invoke(int, s1)
-    res = llinterp_stackless_function(example)
-    assert res == 406
-    res = run_stackless_function(example)
-    assert res == 406
-
-def test_really_return_instance():
-    class C:
-        pass
-    def g(x):
-        c = C()
-        c.x = x + 1
-        rstack.resume_point("rp1", c)
-        return c
-    def example():
-        v1 = g(one()).x
-        c = C()
-        c.x = 4*one()
-        s1 = rstack.resume_state_create(None, "rp1", c)
-        return v1*100 + rstack.resume_state_invoke(C, s1).x
-    res = llinterp_stackless_function(example)
-    assert res == 204
-    res = run_stackless_function(example)
-    assert res == 204
-
-def test_resume_and_raise():
-    def g(x):
-        rstack.resume_point("rp0", x)
-        if x == 0:
-            raise KeyError
-        return x + 1
-    def example():
-        v1 = g(one())
-        s = rstack.resume_state_create(None, "rp0", one()-1)
-        try:
-            v2 = rstack.resume_state_invoke(int, s)
-        except KeyError:
-            v2 = 42
-        return v1*100 + v2
-    res = llinterp_stackless_function(example)
-    assert res == 242
-    res = run_stackless_function(example)
-    assert res == 242
-    
-def test_resume_and_raise_and_catch():
-    def g(x):
-        rstack.resume_point("rp0", x)
-        if x == 0:
-            raise KeyError
-        return x + 1
-    def f(x):
-        x = x - 1
-        try:
-            r = g(x)
-            rstack.resume_point("rp1", returns=r)
-        except KeyError:
-            r = 42
-        return r - 1
-    def example():
-        v1 = f(one()+one())
-        s1 = rstack.resume_state_create(None, "rp1")
-        s0 = rstack.resume_state_create(s1, "rp0", one()-1)
-        v2 = rstack.resume_state_invoke(int, s0)
-        return v1*100 + v2
-    res = llinterp_stackless_function(example)
-    assert res == 141
-    res = run_stackless_function(example)
-    assert res == 141
-
-def test_invoke_raising():
-    def g(x):
-        rstack.resume_point("rp0", x)
-        return x + 1
-    def f(x):
-        x = x - 1
-        try:
-            r = g(x)
-            rstack.resume_point("rp1", returns=r)
-        except KeyError:
-            r = 42
-        return r - 1
-    def example():
-        v1 = f(one()+one())
-        s1 = rstack.resume_state_create(None, "rp1")
-        s0 = rstack.resume_state_create(s1, "rp0", 0)
-        v2 = rstack.resume_state_invoke(int, s0, raising=KeyError())
-        return v1*100 + v2
-    res = llinterp_stackless_function(example)
-    assert res == 141
-    res = run_stackless_function(example)
-    assert res == 141
-    
-
-def test_finally():
-    def f(x):
-        rstack.resume_point("rp1", x)        
-        return 1/x
-    def in_finally(x): 
-        rstack.resume_point("rp1.5", x)
-        return 2/x
-    def g(x):
-        r = y = 0
-        r += f(x)
-        try:
-            y = f(x)
-            rstack.resume_point("rp0", x, r, returns=y)
-        finally:
-            r += in_finally(x)
-        return r + y
-    def example():
-        return g(one())
-    transform_stackless_function(example)
-
-def test_except():
-    py.test.skip("please don't write code like this")
-    def f(x):
-        rstack.resume_point("rp1", x)        
-        return 1/x
-    def g(x):
-        r = y = 0
-        r += f(x)
-        try:
-            y = f(x)
-            rstack.resume_point("rp0", x, r, y, returns=y)
-        except ZeroDivisionError:
-            r += f(x)
-        return r + y
-    def example():
-        return g(one())
-    transform_stackless_function(example)
-
-def test_using_pointers():
-    from pypy.interpreter.miscutils import FixedStack
-    class Arguments:
-        def __init__(self, a, b, c, d, e):
-            pass
-    class W_Root:
-        pass
-    class FakeFrame:
-        def __init__(self, space):
-            self.space = space
-            self.valuestack = FixedStack()
-            self.valuestack.setup(10)
-            self.valuestack.push(W_Root())
-    class FakeSpace:
-        def call_args(self, args, kw):
-            return W_Root()
-        def str_w(self, ob):
-            return 'a string'
-    def call_function(f, oparg, w_star=None, w_starstar=None):
-        n_arguments = oparg & 0xff
-        n_keywords = (oparg>>8) & 0xff
-        keywords = None
-        if n_keywords:
-            keywords = {}
-            for i in range(n_keywords):
-                w_value = f.valuestack.pop()
-                w_key   = f.valuestack.pop()
-                key = f.space.str_w(w_key)
-                keywords[key] = w_value
-        arguments = [None] * n_arguments
-        for i in range(n_arguments - 1, -1, -1):
-            arguments[i] = f.valuestack.pop()
-        args = Arguments(f.space, arguments, keywords, w_star, w_starstar)
-        w_function  = f.valuestack.pop()
-        w_result = f.space.call_args(w_function, args)
-        rstack.resume_point("call_function", f, returns=w_result)
-        f.valuestack.push(w_result)
-    def example():
-        s = FakeSpace()
-        f = FakeFrame(s)
-        call_function(f, 100, W_Root(), W_Root())
-        return one()
-    transform_stackless_function(example, do_backendopt)
-
-def test_always_raising():
-    def g(out):
-        out.append(3)
-        rstack.resume_point('g')
-        raise KeyError
-
-    def h(out):
-        try:
-            # g is always raising, good enough to put the resume point
-            # before, instead of after!
-            rstack.resume_point('h', out)
-            g(out)
-        except KeyError:
-            return 0
-        return -1
-
-    def example():
-        out = []
-        x = h(out)
-        l  = len(out)
-        chain = rstack.resume_state_create(None, 'h', out)
-        chain = rstack.resume_state_create(chain, 'g')
-        x += rstack.resume_state_invoke(int, chain)
-        l += len(out)
-        return l*100+x
-
-    res = llinterp_stackless_function(example)
-    assert res == 200
-    res = run_stackless_function(example)
-    assert res == 200
-
-def test_more_mess():
-    from pypy.interpreter.miscutils import Stack
-
-    def new_framestack():
-        return Stack()
-
-    class FakeFrame:
-        pass
-    class FakeSlpFrame:
-        def switch(self):
-            rstack.stack_unwind()
-            return FakeSlpFrame()
-
-    class FakeCoState:
-        def update(self, new):
-            self.last, self.current = self.current, new
-            frame, new.frame = new.frame, None
-            return frame
-        def do_things_to_do(self):
-            self.do_things_to_do()
-
-    costate = FakeCoState()
-    costate.current = None
-
-    class FakeExecutionContext:
-        def __init__(self):
-            self.space = space
-            self.framestack = new_framestack()
-
-        def subcontext_new(coobj):
-            coobj.framestack = new_framestack()
-        subcontext_new = staticmethod(subcontext_new)
-
-        def subcontext_enter(self, next):
-            self.framestack = next.framestack
-
-        def subcontext_leave(self, current):
-            current.framestack = self.framestack
-
-    class FakeSpace:
-        def __init__(self):
-            self.ec = None
-        def getexecutioncontext(self):
-            if self.ec is None:
-                self.ec = FakeExecutionContext()
-            return self.ec
-
-    space = FakeSpace()
-
-    class MainCoroutineGetter(object):
-        def __init__(self):
-            self.costate = None
-        def _get_default_costate(self):
-            if self.costate is None:
-                costate = FakeCoState()
-                self.costate = costate
-                return costate
-            return self.costate
-
-    main_coroutine_getter = MainCoroutineGetter()
-    
-    class FakeCoroutine:
-        def __init__(self):
-            self.frame = None
-            self.costate = costate
-            space.getexecutioncontext().subcontext_new(self)
-            
-        def switch(self):
-            if self.frame is None:
-                raise RuntimeError
-            state = self.costate
-            incoming_frame = state.update(self).switch()
-            rstack.resume_point("coroutine_switch", self, state, returns=incoming_frame)
-            left = state.last
-            left.frame = incoming_frame
-            left.goodbye()
-            self.hello()
-            #main_coroutine_getter._get_default_costate().do_things_to_do()
-
-        def hello(self):
-            pass
-
-        def goodbye(self):
-            pass
-
-    class FakeAppCoroutine(FakeCoroutine):
-        def __init__(self):
-            FakeCoroutine.__init__(self)
-            self.space = space
-            
-        def hello(self):
-            ec = self.space.getexecutioncontext()
-            ec.subcontext_enter(self)
-
-        def goodbye(self):
-            ec = self.space.getexecutioncontext()
-            ec.subcontext_leave(self)
-
-    def example():
-        coro = FakeAppCoroutine()
-        othercoro = FakeCoroutine()
-        othercoro.frame = FakeSlpFrame()
-        if one():
-            coro.frame = FakeSlpFrame()
-        if one() - one():
-            coro.costate = FakeCoState()
-            coro.costate.last = coro.costate.current = othercoro
-        space.getexecutioncontext().framestack.push(FakeFrame())
-        coro.switch()
-        return one()
-
-    transform_stackless_function(example, do_backendopt)
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
@@ -112,19 +112,6 @@
 #         abort()
 #     return retval + x + 1
 
-class SymbolicRestartNumber(ComputedIntSymbolic):
-    def __init__(self, label, value=None):
-        ComputedIntSymbolic.__init__(self, self._getvalue)
-        self.label = label
-        self.value = value
-
-    def _getvalue(self):
-        # argh, we'd like to assert-fail if value is None here, but we
-        # get called too early (during databasing) for this to be
-        # valid.  so we might return None and rely on the database
-        # checking that this only happens before the database is
-        # complete.
-        return self.value
 
 # the strategy for sharing parts of the resume code:
 #
@@ -248,8 +235,7 @@
         self.stackless_gc = stackless_gc
 
     def analyze_simple_operation(self, op, graphinfo):
-        if op.opname in ('yield_current_frame_to_caller', 'resume_point',
-                'resume_state_invoke', 'resume_state_create', 'stack_frames_depth',
+        if op.opname in ('yield_current_frame_to_caller', 'stack_frames_depth',
                 'stack_switch', 'stack_unwind', 'stack_capture',
                 'get_stack_depth_limit', 'set_stack_depth_limit'):
             return True
@@ -458,24 +444,11 @@
 
         self.is_finished = False
 
-        # only for sanity checking, but still very very important
-        self.explicit_resume_point_data = {}
-        
-        self.symbolic_restart_numbers = {}
-
-        # register the prebuilt restartinfos & give them names for use
-        # with resume_state_create
         # the mauling of frame_typer internals should be a method on FrameTyper.
         for restartinfo in frame.RestartInfo.prebuilt:
             name = restartinfo.func_or_graph.__name__
             for i in range(len(restartinfo.frame_types)):
-                label = name + '_' + str(i)
-                assert label not in self.symbolic_restart_numbers
-                # XXX we think this is right:
-                self.symbolic_restart_numbers[label] = SymbolicRestartNumber(
-                    label, len(self.masterarray1) + i)
                 frame_type = restartinfo.frame_types[i]
-                self.explicit_resume_point_data[label] = frame_type
                 self.frametyper.ensure_frame_type_for_types(frame_type)
             self.register_restart_info(restartinfo)
 
@@ -589,156 +562,6 @@
                 # yes
                 convertblock.exits[0].args[index] = newvar
         # end ouch!
-        
-    def handle_resume_point(self, block, i):
-        # in some circumstances we might be able to reuse
-        # an already inserted resume point
-        op = block.operations[i]
-        if i == len(block.operations) - 1:
-            link = block.exits[0]
-            nextblock = None
-        else:
-            link = split_block(None, block, i+1)
-            i = 0
-            nextblock = link.target
-
-        label = op.args[0].value
-
-        parms = op.args[1:]
-        if not isinstance(parms[0], model.Variable):
-            assert parms[0].value is None
-            parms[0] = None
-        args = vars_to_save(block)
-        for a in args:
-            if a not in parms:
-                raise Exception, "not covered needed value at resume_point %r"%(label,)
-        if parms[0] is not None: # returns= case
-            res = parms[0]
-            args = [arg for arg in args if arg is not res]
-        else:
-            args = args
-            res = op.result
-
-        (FRAME_TYPE, varsforcall, saver) = self.frametyper.frame_type_for_vars(parms[1:])
-
-        if label in self.explicit_resume_point_data:
-            OTHER_TYPE = self.explicit_resume_point_data[label]
-            assert FRAME_TYPE == OTHER_TYPE, "inconsistent types for label %r"%(label,)
-        else:
-            self.explicit_resume_point_data[label] = FRAME_TYPE
-
-        self._make_resume_handling(FRAME_TYPE, varsforcall, res, block.exits)
-
-        restart_number = len(self.masterarray1) + len(self.resume_blocks) - 1
-
-        if label in self.symbolic_restart_numbers:
-            symb = self.symbolic_restart_numbers[label]
-            assert symb.value is None
-            symb.value = restart_number
-        else:
-            symb = SymbolicRestartNumber(label, restart_number)
-            self.symbolic_restart_numbers[label] = symb
-
-        return nextblock
-
-    def handle_resume_state_create(self, block, i):
-        op = block.operations[i]
-        llops = LowLevelOpList()
-        label = op.args[1].value
-        parms = op.args[2:]
-        FRAME_TYPE, varsforcall, saver = self.frametyper.frame_type_for_vars(parms)
-
-        if label in self.explicit_resume_point_data:
-            OTHER_TYPE = self.explicit_resume_point_data[label]
-            assert FRAME_TYPE == OTHER_TYPE, "inconsistent types for label %r"%(label,)
-        else:
-            self.explicit_resume_point_data[label] = FRAME_TYPE
-
-        if label in self.symbolic_restart_numbers:
-            symb = self.symbolic_restart_numbers[label]
-        else:
-            symb = SymbolicRestartNumber(label)
-            self.symbolic_restart_numbers[label] = symb
-
-        # this is rather insane: we create an exception object, pass
-        # it to the saving function, then read the thus created state
-        # out of and then clear global_state.top
-        c_EXC = model.Constant(self.unwind_exception_type.TO, lltype.Void)
-        c_flags = model.Constant({'flavor': 'gc'}, lltype.Void)
-        v_exc = llops.genop('malloc', [c_EXC, c_flags],
-                            resulttype = self.unwind_exception_type)
-        llops.genop('setfield', [v_exc,
-                                 model.Constant('inst_depth', lltype.Void),
-                                 model.Constant(0, lltype.Signed)])
-
-        realvarsforcall = []
-        for v in varsforcall:
-            if v.concretetype != lltype.Void:
-                realvarsforcall.append(gen_cast(llops, storage_type(v.concretetype), v))
-        
-        llops.genop('direct_call',
-                    [model.Constant(saver, lltype.typeOf(saver)), v_exc,
-                     model.Constant(symb, lltype.Signed)] + realvarsforcall,
-                    resulttype = lltype.Void)
-        v_state = varoftype(lltype.Ptr(frame.STATE_HEADER))
-        v_state_hdr = llops.genop("getfield",
-                                  [self.ll_global_state, self.c_inst_top_name],
-                                  resulttype=lltype.Ptr(STATE_HEADER))
-        v_state = gen_cast(llops, lltype.Ptr(FRAME_TYPE), v_state_hdr)
-        llops.genop("setfield",
-                    [self.ll_global_state, self.c_inst_top_name, self.c_null_state])
-
-        v_prevstate = gen_cast(llops, lltype.Ptr(frame.STATE_HEADER), op.args[0])
-        llops.genop('direct_call', [self.set_back_pointer_ptr,
-                                    v_state_hdr, v_prevstate])
-        llops.append(model.SpaceOperation('cast_opaque_ptr', [v_state_hdr], op.result))
-        block.operations[i:i+1] = llops
-
-    def handle_resume_state_invoke(self, block):
-        op = block.operations[-1]
-        assert op.opname == 'resume_state_invoke'
-        # some commentary.
-        #
-        # we don't want to write 155 or so different versions of
-        # resume_after_foo that appear to the annotator to return
-        # different types.  we take advantage of the fact that this
-        # function always raises UnwindException and have it (appear
-        # to) return Void.  then to placate all the other machinery,
-        # we pass a constant zero-of-the-appropriate-type along the
-        # non-exceptional link (which we know will never be taken).
-        # Nota Bene: only mutate a COPY of the non-exceptional link
-        # because the non-exceptional link has been stored in
-        # self.resume_blocks and we don't want a constant "zero" in
-        # there.
-        v_state = op.args[0]
-        v_returning = op.args[1]
-        v_raising = op.args[2]
-        llops = LowLevelOpList()
-
-        if v_raising.concretetype == lltype.Void:
-            erased_type = storage_type(v_returning.concretetype)
-            resume_after_ptr = self.resume_afters[erased_type]
-            v_param = v_returning
-        else:
-            assert v_returning.concretetype == lltype.Void
-            erased_type = self.exception_type
-            resume_after_ptr = self.resume_after_raising_ptr
-            v_param = v_raising
-
-        if erased_type != v_param.concretetype:
-            v_param = gen_cast(llops, erased_type, v_param)
-        llops.genop('direct_call', [resume_after_ptr, v_state, v_param],
-                    resulttype=lltype.Void)
-
-        del block.operations[-1]
-        block.operations.extend(llops)
-
-        noexclink = block.exits[0].copy()
-        realrettype = op.result.concretetype
-        for i, a in enumerate(noexclink.args):
-            if a is op.result:
-                noexclink.args[i] = model.Constant(realrettype._defl(), realrettype)
-        block.recloseblock(*((noexclink,) + block.exits[1:]))        
 
     def insert_unwind_handling(self, block, i):
         # for the case where we are resuming to an except:
@@ -821,19 +644,8 @@
                 op = replace_with_call(self.operation_replacement[op.opname])
                 stackless_op = True
 
-            if op.opname == 'resume_state_create':
-                self.handle_resume_state_create(block, i)
-                continue # go back and look at that malloc
-                        
             if (op.opname in ('direct_call', 'indirect_call')
                 or self.analyzer.analyze(op)):
-                if op.opname == 'resume_point':
-                    block = self.handle_resume_point(block, i)
-                    if block is None:
-                        return
-                    else:
-                        i = 0
-                        continue
 
                 if not stackless_op and not self.analyzer.analyze(op):
                     i += 1
@@ -849,9 +661,7 @@
                     continue
 
                 nextblock = self.insert_unwind_handling(block, i)
-                if op.opname == 'resume_state_invoke':
-                    self.handle_resume_state_invoke(block)
-                
+
                 if nextblock is None:
                     return
 
diff --git a/pypy/translator/transform.py b/pypy/translator/transform.py
--- a/pypy/translator/transform.py
+++ b/pypy/translator/transform.py
@@ -175,41 +175,6 @@
     # make sure the bookkeeper knows about AssertionError
     self.bookkeeper.getuniqueclassdef(AssertionError)
 
-def insert_stackcheck(ann):
-    from pypy.tool.algo.graphlib import Edge, make_edge_dict, break_cycles
-    edges = []
-    graphs_to_patch = {}
-    for callposition, (caller, callee) in ann.translator.callgraph.items():
-        if getattr(getattr(callee, 'func', None), 'insert_stack_check_here', False):
-            graphs_to_patch[callee] = True
-            continue
-        edge = Edge(caller, callee)
-        edge.callposition = callposition
-        edges.append(edge)
-
-    for graph in graphs_to_patch:
-        v = Variable()
-        ann.setbinding(v, annmodel.SomeImpossibleValue())
-        unwind_op = SpaceOperation('simple_call', [Constant(stack_check)], v)
-        graph.startblock.operations.insert(0, unwind_op)
-
-    edgedict = make_edge_dict(edges)
-    for edge in break_cycles(edgedict, edgedict):
-        caller = edge.source
-        _, _, call_tag = edge.callposition
-        if call_tag:
-            caller_block, _ = call_tag
-        else:
-            ann.warning("cycle detected but no information on where to insert "
-                        "stack_check()")
-            continue
-        # caller block found, insert stack_check()
-        v = Variable()
-        # push annotation on v
-        ann.setbinding(v, annmodel.SomeImpossibleValue())
-        unwind_op = SpaceOperation('simple_call', [Constant(stack_check)], v)
-        caller_block.operations.insert(0, unwind_op)
-
 def insert_ll_stackcheck(translator):
     from pypy.translator.backendopt.support import find_calls_from
     from pypy.rlib.rstack import stack_check


More information about the pypy-commit mailing list