[pypy-commit] pypy py3k: merge default

pjenvey noreply at buildbot.pypy.org
Mon Mar 18 23:08:39 CET 2013


Author: Philip Jenvey <pjenvey at underboss.org>
Branch: py3k
Changeset: r62411:7d3b2666f8b2
Date: 2013-03-18 15:08 -0700
http://bitbucket.org/pypy/pypy/changeset/7d3b2666f8b2/

Log:	merge default

diff too long, truncating to 2000 out of 23512 lines

diff --git a/lib-python/2/distutils/sysconfig_pypy.py b/lib-python/2/distutils/sysconfig_pypy.py
--- a/lib-python/2/distutils/sysconfig_pypy.py
+++ b/lib-python/2/distutils/sysconfig_pypy.py
@@ -43,7 +43,7 @@
     if prefix is None:
         prefix = PREFIX
     if standard_lib:
-        return os.path.join(prefix, "lib-python", get_python_version())
+        return os.path.join(prefix, "lib-python", sys.version[0])
     return os.path.join(prefix, 'site-packages')
 
 
@@ -61,6 +61,7 @@
     g['SO'] = _get_so_extension() or ".so"
     g['SOABI'] = g['SO'].rsplit('.')[0]
     g['LIBDIR'] = os.path.join(sys.prefix, 'lib')
+    g['CC'] = "gcc -pthread" # -pthread might not be valid on OS/X, check
 
     global _config_vars
     _config_vars = g
diff --git a/lib-python/2/pickle.py b/lib-python/2/pickle.py
--- a/lib-python/2/pickle.py
+++ b/lib-python/2/pickle.py
@@ -34,6 +34,8 @@
 import struct
 import re
 
+from __pypy__.builders import StringBuilder
+
 __all__ = ["PickleError", "PicklingError", "UnpicklingError", "Pickler",
            "Unpickler", "dump", "dumps", "load", "loads"]
 
@@ -1409,11 +1411,24 @@
 except ImportError:
     from StringIO import StringIO
 
+
+class StringBuilderFile(object):
+    ''' pickle uses only file.write - provide this method, 
+    use StringBuilder for speed
+    '''
+    def __init__(self):
+        self.builder = StringBuilder()
+        self.write = self.builder.append
+
+    def getvalue(self):
+        return self.builder.build()
+
+
 def dump(obj, file, protocol=None):
     Pickler(file, protocol).dump(obj)
 
 def dumps(obj, protocol=None):
-    file = StringIO()
+    file = StringBuilderFile()
     Pickler(file, protocol).dump(obj)
     return file.getvalue()
 
diff --git a/lib-python/2/sysconfig.py b/lib-python/2/sysconfig.py
--- a/lib-python/2/sysconfig.py
+++ b/lib-python/2/sysconfig.py
@@ -27,10 +27,10 @@
         'data'   : '{base}',
         },
     'pypy': {
-        'stdlib': '{base}/lib-python/{py_version_short}',
-        'platstdlib': '{base}/lib-python/{py_version_short}',
-        'purelib': '{base}/lib-python/{py_version_short}',
-        'platlib': '{base}/lib-python/{py_version_short}',
+        'stdlib': '{base}/lib-python/{py_version}',
+        'platstdlib': '{base}/lib-python/{py_version}',
+        'purelib': '{base}/lib-python/{py_version}',
+        'platlib': '{base}/lib-python/{py_version}',
         'include': '{base}/include',
         'platinclude': '{base}/include',
         'scripts': '{base}/bin',
diff --git a/lib_pypy/_marshal.py b/lib_pypy/_marshal.py
--- a/lib_pypy/_marshal.py
+++ b/lib_pypy/_marshal.py
@@ -7,7 +7,6 @@
 # the "sandboxed" process.  It must work for Python2 as well.
 
 import types
-from _codecs import utf_8_decode, utf_8_encode
 
 try:
     intern
@@ -166,9 +165,8 @@
 
     def dump_unicode(self, x):
         self._write(TYPE_UNICODE)
-        #s = x.encode('utf8')
-        s, len_s = utf_8_encode(x)
-        self.w_long(len_s)
+        s = x.encode('utf8')
+        self.w_long(len(s))
         self._write(s)
     try:
         unicode
@@ -386,8 +384,7 @@
     def load_unicode(self):
         n = self.r_long()
         s = self._read(n)
-        #ret = s.decode('utf8')
-        ret, len_ret = utf_8_decode(s)
+        ret = s.decode('utf8')
         return ret
     dispatch[TYPE_UNICODE] = load_unicode
 
diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py
--- a/lib_pypy/_sqlite3.py
+++ b/lib_pypy/_sqlite3.py
@@ -364,9 +364,10 @@
         self._in_transaction = False
         self.isolation_level = isolation_level
 
-        self._cursors = []
+        self.__cursors = []
+        self.__cursors_counter = 0
         self.__statements = []
-        self.__statement_counter = 0
+        self.__statements_counter = 0
         self._statement_cache = _StatementCache(self, cached_statements)
 
         self.__func_cache = {}
@@ -394,10 +395,7 @@
     def close(self):
         self._check_thread()
 
-        for statement in self.__statements:
-            obj = statement()
-            if obj is not None:
-                obj._finalize()
+        self.__do_all_statements(Statement._finalize, True)
 
         if self._db:
             ret = _lib.sqlite3_close(self._db)
@@ -469,13 +467,33 @@
         exc.error_code = error_code
         return exc
 
+    def _remember_cursor(self, cursor):
+        self.__cursors.append(weakref.ref(cursor))
+        self.__cursors_counter += 1
+        if self.__cursors_counter < 200:
+            return
+        self.__cursors_counter = 0
+        self.__cursors = [r for r in self.__cursors if r() is not None]
+
     def _remember_statement(self, statement):
         self.__statements.append(weakref.ref(statement))
-        self.__statement_counter += 1
+        self.__statements_counter += 1
+        if self.__statements_counter < 200:
+            return
+        self.__statements_counter = 0
+        self.__statements = [r for r in self.__statements if r() is not None]
 
-        if self.__statement_counter % 100 == 0:
-            self.__statements = [ref for ref in self.__statements
-                                 if ref() is not None]
+    def __do_all_statements(self, action, reset_cursors):
+        for weakref in self.__statements:
+            statement = weakref()
+            if statement is not None:
+                action(statement)
+
+        if reset_cursors:
+            for weakref in self.__cursors:
+                cursor = weakref()
+                if cursor is not None:
+                    cursor._reset = True
 
     @_check_thread_wrap
     @_check_closed_wrap
@@ -528,10 +546,7 @@
         if not self._in_transaction:
             return
 
-        for statement in self.__statements:
-            obj = statement()
-            if obj is not None:
-                obj._reset()
+        self.__do_all_statements(Statement._reset, False)
 
         statement = c_void_p()
         ret = _lib.sqlite3_prepare_v2(self._db, b"COMMIT", -1,
@@ -552,15 +567,7 @@
         if not self._in_transaction:
             return
 
-        for statement in self.__statements:
-            obj = statement()
-            if obj is not None:
-                obj._reset()
-
-        for cursor_ref in self._cursors:
-            cursor = cursor_ref()
-            if cursor:
-                cursor._reset = True
+        self.__do_all_statements(Statement._reset, True)
 
         statement = c_void_p()
         ret = _lib.sqlite3_prepare_v2(self._db, b"ROLLBACK", -1,
@@ -787,14 +794,9 @@
     __statement = None
 
     def __init__(self, con):
-        self.__initialized = True
-        self.__connection = con
-
         if not isinstance(con, Connection):
             raise TypeError
-        con._check_thread()
-        con._check_closed()
-        con._cursors.append(weakref.ref(self))
+        self.__connection = con
 
         self.arraysize = 1
         self.row_factory = None
@@ -804,11 +806,12 @@
         self.__description = None
         self.__rowcount = -1
 
+        con._check_thread()
+        con._remember_cursor(self)
+
+        self.__initialized = True
+
     def __del__(self):
-        try:
-            self.__connection._cursors.remove(weakref.ref(self))
-        except (AttributeError, ValueError):
-            pass
         if self.__statement:
             self.__statement._reset()
 
@@ -876,9 +879,6 @@
                 if self.__statement._kind == Statement._DQL and ret == _lib.SQLITE_ROW:
                     self.__statement._build_row_cast_map()
                     self.__statement._readahead(self)
-                else:
-                    self.__statement._item = None
-                    self.__statement._exhausted = True
 
                 if self.__statement._kind == Statement._DML:
                     if self.__rowcount == -1:
@@ -886,7 +886,6 @@
                     self.__rowcount += _lib.sqlite3_changes(self.__connection._db)
         finally:
             self.__locked = False
-
         return self
 
     @__check_cursor_wrap
@@ -924,9 +923,10 @@
             if rc != _lib.SQLITE_DONE:
                 _lib.sqlite3_finalize(statement)
                 if rc == _lib.SQLITE_OK:
-                    return self
+                    break
                 else:
                     raise self.__connection._get_exception(rc)
+
             rc = _lib.sqlite3_finalize(statement)
             if rc != _lib.SQLITE_OK:
                 raise self.__connection._get_exception(rc)
@@ -1003,6 +1003,7 @@
 
     def __init__(self, connection, sql):
         self.__con = connection
+        self.__con._remember_statement(self)
 
         if not isinstance(sql, basestring):
             raise Warning("SQL is of wrong type. Must be string or unicode.")
@@ -1015,7 +1016,6 @@
             self._kind = Statement._DDL
 
         self._in_use = False
-        self._exhausted = False
         self._row_factory = None
 
         if isinstance(sql, unicode):
@@ -1031,10 +1031,9 @@
             ret = _lib.sqlite3_prepare_v2(self.__con._db, sql, -1,
                                           byref(self._statement), byref(sql))
             self._kind = Statement._DQL
-
         if ret != _lib.SQLITE_OK:
             raise self.__con._get_exception(ret)
-        self.__con._remember_statement(self)
+
         sql = sql.value.decode('utf-8')
         if _check_remaining_sql(sql):
             raise Warning("You can only execute one statement at a time.")
@@ -1053,7 +1052,6 @@
         if self._in_use and self._statement:
             _lib.sqlite3_reset(self._statement)
             self._in_use = False
-        self._exhausted = False
 
     if sys.version_info[0] < 3:
         def __check_decodable(self, param):
@@ -1218,20 +1216,19 @@
         self._item = row
 
     def _next(self, cursor):
-        if self._exhausted:
+        try:
+            item = self._item
+        except AttributeError:
             raise StopIteration
-        item = self._item
+        del self._item
 
         ret = _lib.sqlite3_step(self._statement)
-        if ret == _lib.SQLITE_DONE:
-            self._exhausted = True
-            self._item = None
-        elif ret != _lib.SQLITE_ROW:
-            exc = self.__con._get_exception(ret)
+        if ret not in (_lib.SQLITE_DONE, _lib.SQLITE_ROW):
             _lib.sqlite3_reset(self._statement)
-            raise exc
+            raise self.__con._get_exception(ret)
+        elif ret == _lib.SQLITE_ROW:
+            self._readahead(cursor)
 
-        self._readahead(cursor)
         return item
 
     def _get_description(self):
diff --git a/lib_pypy/numpypy/core/numeric.py b/lib_pypy/numpypy/core/numeric.py
--- a/lib_pypy/numpypy/core/numeric.py
+++ b/lib_pypy/numpypy/core/numeric.py
@@ -4,6 +4,7 @@
            'array_repr', 'array_str', 'set_string_function',
            'array_equal', 'outer', 'vdot', 'identity', 'little_endian',
            'Inf', 'inf', 'infty', 'Infinity', 'nan', 'NaN', 'False_', 'True_',
+           'seterr',
           ]
 
 import sys
diff --git a/pypy/TODO b/pypy/TODO
new file mode 100644
--- /dev/null
+++ b/pypy/TODO
@@ -0,0 +1,2 @@
+
+* ARM
diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
--- a/pypy/doc/whatsnew-head.rst
+++ b/pypy/doc/whatsnew-head.rst
@@ -42,6 +42,7 @@
 .. branch: numpy-unify-methods
 .. branch: fix-version-tool
 .. branch: popen2-removal
+.. branch: pickle-dumps
 
 .. branch: release-2.0-beta1
 
@@ -85,3 +86,8 @@
 
 .. branch: vendor-rename
 Remove minor verison number from lib-python dirs to simplify stdlib upgrades.
+
+.. branch: jitframe-on-heap
+Moves optimized JIT frames from stack to heap. As a side effect it enables
+stackless to work well with the JIT on PyPy. Also removes a bunch of code from
+the GC which fixes cannot find gc roots.
diff --git a/pypy/goal/getnightly.py b/pypy/goal/getnightly.py
new file mode 100755
--- /dev/null
+++ b/pypy/goal/getnightly.py
@@ -0,0 +1,27 @@
+#!/usr/bin/env python
+
+import sys
+import os
+import py
+
+if sys.platform.startswith('linux'):
+    arch = 'linux'
+else:
+    print 'Cannot determine the platform, please update this scrip'
+    sys.exit(1)
+
+if sys.maxint == 2**63 - 1:
+    arch += '64'
+
+filename = 'pypy-c-jit-latest-%s.tar.bz2' % arch
+url = 'http://buildbot.pypy.org/nightly/trunk/%s' % filename
+tmp = py.path.local.mkdtemp()
+mydir = tmp.chdir()
+print 'Downloading pypy to', tmp
+if os.system('wget "%s"' % url) != 0:
+    sys.exit(1)
+
+print 'Extracting pypy binary'
+mydir.chdir()
+os.system("tar -x -v --wildcards --strip-components=2 -f %s '*/bin/pypy'" % tmp.join(filename))
+
diff --git a/pypy/interpreter/error.py b/pypy/interpreter/error.py
--- a/pypy/interpreter/error.py
+++ b/pypy/interpreter/error.py
@@ -1,8 +1,15 @@
-import os, sys
+import cStringIO
 import itertools
+import os
+import sys
+import traceback
+from errno import EINTR
+
 from rpython.rlib import jit
 from rpython.rlib.objectmodel import we_are_translated
-from errno import EINTR
+
+from pypy.interpreter import debug
+
 
 AUTO_DEBUG = os.getenv('PYPY_DEBUG')
 RECORD_INTERPLEVEL_TRACEBACK = True
@@ -94,7 +101,7 @@
         if space is None:
             # this part NOT_RPYTHON
             exc_typename = str(self.w_type)
-            exc_value    = str(w_value)
+            exc_value = str(w_value)
         else:
             w = space.wrap
             if space.is_w(space.type(self.w_type), space.w_text):
@@ -128,7 +135,8 @@
 
     def print_application_traceback(self, space, file=None):
         "NOT_RPYTHON: Dump a standard application-level traceback."
-        if file is None: file = sys.stderr
+        if file is None:
+            file = sys.stderr
         self.print_app_tb_only(file)
         print >> file, self.errorstr(space)
 
@@ -163,8 +171,8 @@
     def print_detailed_traceback(self, space=None, file=None):
         """NOT_RPYTHON: Dump a nice detailed interpreter- and
         application-level traceback, useful to debug the interpreter."""
-        import traceback, cStringIO
-        if file is None: file = sys.stderr
+        if file is None:
+            file = sys.stderr
         f = cStringIO.StringIO()
         for i in range(len(self.debug_excs)-1, -1, -1):
             print >> f, "Traceback (interpreter-level):"
@@ -177,7 +185,6 @@
         self.print_app_tb_only(file)
         print >> file, '(application-level)', self.errorstr(space)
         if AUTO_DEBUG:
-            import debug
             debug.fire(self)
 
     @jit.unroll_safe
@@ -202,7 +209,7 @@
         #  (Class, x)                 (Class, Class(x))               no
         #  (inst, None)               (inst.__class__, inst)          no
         #
-        w_type  = self.w_type
+        w_type = self.w_type
         w_value = self.get_w_value(space)
 
         if space.exception_is_valid_obj_as_class_w(w_type):
@@ -252,7 +259,7 @@
             w_value = w_inst
             w_type = w_instclass
 
-        self.w_type   = w_type
+        self.w_type = w_type
         self._w_value = w_value
 
     def _exception_getclass(self, space, w_inst, what="exceptions"):
@@ -372,7 +379,7 @@
         from rpython.rlib.unroll import unrolling_iterable
         attrs = ['x%d' % i for i in range(len(formats))]
         entries = unrolling_iterable(zip(itertools.count(), formats, attrs))
-        #
+
         class OpErrFmt(OperationError):
             def __init__(self, w_type, strings, *args):
                 assert len(args) == len(strings) - 1
@@ -381,6 +388,7 @@
                     setattr(self, attr, args[i])
                 assert w_type is not None
                 self.setup(w_type)
+
             def _compute_value(self):
                 lst = [None] * (len(formats) + len(formats) + 1)
                 for i, fmt, attr in entries:
diff --git a/pypy/interpreter/nestedscope.py b/pypy/interpreter/nestedscope.py
--- a/pypy/interpreter/nestedscope.py
+++ b/pypy/interpreter/nestedscope.py
@@ -1,11 +1,13 @@
-from pypy.interpreter.error import OperationError
-from pypy.interpreter import function, pycode, pyframe
-from pypy.interpreter.baseobjspace import Wrappable
-from pypy.interpreter.mixedmodule import MixedModule
-from pypy.interpreter.astcompiler import consts
 from rpython.rlib import jit
 from rpython.tool.uid import uid
 
+from pypy.interpreter import function, pycode, pyframe
+from pypy.interpreter.astcompiler import consts
+from pypy.interpreter.baseobjspace import Wrappable
+from pypy.interpreter.error import OperationError
+from pypy.interpreter.mixedmodule import MixedModule
+
+
 class Cell(Wrappable):
     "A simple container for a wrapped value."
 
@@ -20,7 +22,7 @@
 
     def get(self):
         if self.w_value is None:
-            raise ValueError, "get() from an empty cell"
+            raise ValueError("get() from an empty cell")
         return self.w_value
 
     def set(self, w_value):
@@ -28,7 +30,7 @@
 
     def delete(self):
         if self.w_value is None:
-            raise ValueError, "delete() on an empty cell"
+            raise ValueError("delete() on an empty cell")
         self.w_value = None
 
     def descr__lt__(self, space, w_other):
@@ -53,10 +55,10 @@
         return space.eq(self.w_value, other.w_value)
 
     def descr__reduce__(self, space):
-        w_mod    = space.getbuiltinmodule('_pickle_support')
-        mod      = space.interp_w(MixedModule, w_mod)
+        w_mod = space.getbuiltinmodule('_pickle_support')
+        mod = space.interp_w(MixedModule, w_mod)
         new_inst = mod.get('cell_new')
-        if self.w_value is None:    #when would this happen?
+        if self.w_value is None:    # when would this happen?
             return space.newtuple([new_inst, space.newtuple([])])
         tup = [self.w_value]
         return space.newtuple([new_inst, space.newtuple([]),
@@ -64,7 +66,7 @@
 
     def descr__setstate__(self, space, w_state):
         self.w_value = space.getitem(w_state, space.wrap(0))
-        
+
     def __repr__(self):
         """ representation for debugging purposes """
         if self.w_value is None:
@@ -81,10 +83,9 @@
             raise OperationError(space.w_ValueError, space.wrap("Cell is empty"))
 
 
-
 super_initialize_frame_scopes = pyframe.PyFrame.initialize_frame_scopes
-super_fast2locals             = pyframe.PyFrame.fast2locals
-super_locals2fast             = pyframe.PyFrame.locals2fast
+super_fast2locals = pyframe.PyFrame.fast2locals
+super_locals2fast = pyframe.PyFrame.locals2fast
 
 
 class __extend__(pyframe.PyFrame):
@@ -139,7 +140,7 @@
     def fast2locals(self):
         super_fast2locals(self)
         # cellvars are values exported to inner scopes
-        # freevars are values coming from outer scopes 
+        # freevars are values coming from outer scopes
         freevarnames = list(self.pycode.co_cellvars)
         if self.pycode.co_flags & consts.CO_OPTIMIZED:
             freevarnames.extend(self.pycode.co_freevars)
diff --git a/pypy/module/_continuation/interp_continuation.py b/pypy/module/_continuation/interp_continuation.py
--- a/pypy/module/_continuation/interp_continuation.py
+++ b/pypy/module/_continuation/interp_continuation.py
@@ -19,11 +19,6 @@
         #  - normal:      self.sthread != None, not is_empty_handle(self.h)
         #  - finished:    self.sthread != None, is_empty_handle(self.h)
 
-    def __del__(self):
-        sthread = self.sthread
-        if sthread is not None and not sthread.is_empty_handle(self.h):
-            sthread.destroy(self.h)
-
     def check_sthread(self):
         ec = self.space.getexecutioncontext()
         if ec.stacklet_thread is not self.sthread:
@@ -34,7 +29,6 @@
         if self.sthread is not None:
             raise geterror(self.space, "continulet already __init__ialized")
         sthread = build_sthread(self.space)
-        workaround_disable_jit(sthread)
         #
         # hackish: build the frame "by hand", passing it the correct arguments
         space = self.space
@@ -77,8 +71,7 @@
                 global_state.clear()
                 raise geterror(self.space, "continulet already finished")
         self.check_sthread()
-        workaround_disable_jit(self.sthread)
-        #
+
         global_state.origin = self
         if to is None:
             # simple switch: going to self.h
@@ -271,16 +264,6 @@
         sthread = ec.stacklet_thread = SThread(space, ec)
     return sthread
 
-def workaround_disable_jit(sthread):
-    # A bad workaround to kill the JIT anywhere in this thread.
-    # This forces all the frames.  It's a bad workaround because
-    # it takes O(depth) time, and it will cause some "abort:
-    # vable escape" in the JIT.  The goal is to prevent any frame
-    # from being still virtuals, because the JIT generates code
-    # to un-virtualizable them "on demand" by loading values based
-    # on FORCE_TOKEN, which is an address in the stack.
-    sthread.ec.force_all_frames()
-
 # ____________________________________________________________
 
 def permute(space, args_w):
diff --git a/pypy/module/_io/interp_iobase.py b/pypy/module/_io/interp_iobase.py
--- a/pypy/module/_io/interp_iobase.py
+++ b/pypy/module/_io/interp_iobase.py
@@ -391,7 +391,11 @@
     def remove(self, w_iobase):
         holder = w_iobase.streamholder
         if holder is not None:
-            del self.streams[holder]
+            try:
+                del self.streams[holder]
+            except KeyError:
+                # this can happen in daemon threads
+                pass
 
     def flush_all(self, space):
         while self.streams:
diff --git a/pypy/module/cppyy/capi/reflex_capi.py b/pypy/module/cppyy/capi/reflex_capi.py
--- a/pypy/module/cppyy/capi/reflex_capi.py
+++ b/pypy/module/cppyy/capi/reflex_capi.py
@@ -9,18 +9,23 @@
 srcpath = pkgpath.join("src")
 incpath = pkgpath.join("include")
 
+import commands
+(config_stat, incdir) = commands.getstatusoutput("root-config --incdir")
+
 if os.environ.get("ROOTSYS"):
-    import commands
-    (stat, incdir) = commands.getstatusoutput("root-config --incdir")
-    if stat != 0:        # presumably Reflex-only
+    if config_stat != 0:     # presumably Reflex-only
         rootincpath = [os.path.join(os.environ["ROOTSYS"], "include")]
         rootlibpath = [os.path.join(os.environ["ROOTSYS"], "lib64"), os.path.join(os.environ["ROOTSYS"], "lib")]
     else:
         rootincpath = [incdir]
         rootlibpath = commands.getoutput("root-config --libdir").split()
 else:
-    rootincpath = []
-    rootlibpath = []
+    if config_stat == 0:
+        rootincpath = [incdir]
+        rootlibpath = commands.getoutput("root-config --libdir").split()
+    else:
+        rootincpath = []
+        rootlibpath = []
 
 def identify():
     return 'Reflex'
diff --git a/pypy/module/cppyy/test/Makefile b/pypy/module/cppyy/test/Makefile
--- a/pypy/module/cppyy/test/Makefile
+++ b/pypy/module/cppyy/test/Makefile
@@ -7,7 +7,7 @@
 
 ifeq ($(ROOTSYS),)
   genreflex=genreflex
-  cppflags=
+  cppflags=-I$(shell root-config --incdir) -L$(shell root-config --libdir)
 else
   genreflex=$(ROOTSYS)/bin/genreflex
   ifeq ($(wildcard $(ROOTSYS)/include),)     # standard locations used?
diff --git a/pypy/module/cppyy/test/test_crossing.py b/pypy/module/cppyy/test/test_crossing.py
--- a/pypy/module/cppyy/test/test_crossing.py
+++ b/pypy/module/cppyy/test/test_crossing.py
@@ -1,6 +1,16 @@
 import py, os, sys
+from pypy.interpreter.gateway import interp2app, unwrap_spec
+from rpython.translator.tool.cbuild import ExternalCompilationInfo
+from rpython.translator import platform
+from rpython.translator.gensupp import uniquemodulename
+from rpython.tool.udir import udir
+
+from pypy.module.cpyext import api
+from pypy.module.cpyext.state import State
+
 from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
 
+
 currpath = py.path.local(__file__).dirpath()
 test_dct = str(currpath.join("crossingDict.so"))
 
@@ -11,27 +21,90 @@
     if err:
         raise OSError("'make' failed (see stderr)")
 
+# from pypy/module/cpyext/test/test_cpyext.py; modified to accept more external
+# symbols and called directly instead of import_module
+def compile_extension_module(space, modname, symbols, **kwds):
+    """
+    Build an extension module and return the filename of the resulting native
+    code file.
+
+    modname is the name of the module, possibly including dots if it is a module
+    inside a package.
+
+    Any extra keyword arguments are passed on to ExternalCompilationInfo to
+    build the module (so specify your source with one of those).
+    """
+    state = space.fromcache(State)
+    api_library = state.api_lib
+    if sys.platform == 'win32':
+        kwds["libraries"] = [api_library]
+        # '%s' undefined; assuming extern returning int
+        kwds["compile_extra"] = ["/we4013"]
+    elif sys.platform == 'darwin':
+        kwds["link_files"] = [str(api_library + '.dylib')]
+    else:
+        kwds["link_files"] = [str(api_library + '.so')]
+        if sys.platform.startswith('linux'):
+            kwds["compile_extra"]=["-Werror=implicit-function-declaration"]
+
+    modname = modname.split('.')[-1]
+    eci = ExternalCompilationInfo(
+        export_symbols=['init%s' % (modname,)]+symbols,
+        include_dirs=api.include_dirs,
+        **kwds
+        )
+    eci = eci.convert_sources_to_files()
+    dirname = (udir/uniquemodulename('module')).ensure(dir=1)
+    soname = platform.platform.compile(
+        [], eci,
+        outputfilename=str(dirname/modname),
+        standalone=False)
+    from pypy.module.imp.importing import get_so_extension
+    pydname = soname.new(purebasename=modname, ext=get_so_extension(space))
+    soname.rename(pydname)
+    return str(pydname)
 
 class AppTestCrossing(AppTestCpythonExtensionBase):
     spaceconfig = dict(usemodules=['cpyext', 'cppyy', 'thread', '_rawffi', '_ffi',
                                    'array', 'itertools', 'rctime', 'binascii'])
 
     def setup_class(cls):
-        # following from AppTestCpythonExtensionBase, with cppyy added
-        cls.space.getbuiltinmodule("cpyext")
-        from pypy.module.imp.importing import importhook
-        importhook(cls.space, "os") # warm up reference counts
-        from pypy.module.cpyext.pyobject import RefcountState
-        state = cls.space.fromcache(RefcountState)
-        state.non_heaptypes_w[:] = []
-
-        # cppyy specific additions (not that the test_dct is loaded late
+        AppTestCpythonExtensionBase.setup_class.im_func(cls)
+        # cppyy specific additions (note that test_dct is loaded late
         # to allow the generated extension module be loaded first)
         cls.w_test_dct    = cls.space.wrap(test_dct)
         cls.w_pre_imports = cls.space.appexec([], """():
             import cppyy, ctypes""")    # prevents leak-checking complaints on ctypes
-        from pypy.module.imp.importing import get_so_extension
-        cls.w_soext = cls.space.wrap(get_so_extension(cls.space))
+
+    def setup_method(self, func):
+        AppTestCpythonExtensionBase.setup_method.im_func(self, func)
+
+        @unwrap_spec(name=str, init=str, body=str)
+        def load_cdll(space, name, init, body, w_symbols):
+            # the following is loosely from test_cpyext.py import_module; it
+            # is copied here to be able to tweak the call to
+            # compile_extension_module and to get a different return result
+            # than in that function
+            code = """
+            #include <Python.h>
+            %(body)s
+
+            void init%(name)s(void) {
+            %(init)s
+            }
+            """ % dict(name=name, init=init, body=body)
+            kwds = dict(separate_module_sources=[code])
+            symbols = [space.str_w(w_item) for w_item in space.fixedview(w_symbols)]
+            mod = compile_extension_module(space, name, symbols, **kwds)
+
+            # explicitly load the module as a CDLL rather than as a module
+            import ctypes
+            from pypy.module.imp.importing import get_so_extension
+            fullmodname = os.path.join(
+                os.path.dirname(mod), name + get_so_extension(space))
+            return ctypes.CDLL(fullmodname, ctypes.RTLD_GLOBAL)
+
+        self.w_load_cdll = self.space.wrap(interp2app(load_cdll))
 
     def test00_base_class(self):
         """Test from cpyext; only here to see whether the imported class works"""
@@ -49,10 +122,13 @@
 
         import os, ctypes
 
+        name = 'bar'
+
         init = """
         if (Py_IsInitialized())
             Py_InitModule("bar", methods);
         """
+
         # note: only the symbols are needed for C, none for python
         body = """
         long bar_unwrap(PyObject* arg)
@@ -67,10 +143,12 @@
             { NULL }
         };
         """
+        # explicitly load the module as a CDLL rather than as a module
+#        dirname = space.wrap(os.path.dirname(mod))
 
-        dirname = self.import_module(name='bar', init=init, body=body, load_it=False)
-        fullmodname = os.path.join(dirname, 'bar' + self.soext)
-        self.cmodule = ctypes.CDLL(fullmodname, ctypes.RTLD_GLOBAL)
+#        dirname = self.import_module(name='bar', init=init, body=body, load_it=False)
+#        fullmodname = os.path.join(dirname, name + self.soext)
+        self.cmodule = self.load_cdll(name, init, body, ['bar_unwrap', 'bar_wrap'])#ctypes.CDLL(fullmodname, ctypes.RTLD_GLOBAL)
 
     def test02_crossing_dict(self):
         """Test availability of all needed classes in the dict"""
diff --git a/pypy/module/cppyy/test/test_pythonify.py b/pypy/module/cppyy/test/test_pythonify.py
--- a/pypy/module/cppyy/test/test_pythonify.py
+++ b/pypy/module/cppyy/test/test_pythonify.py
@@ -6,6 +6,9 @@
 test_dct = str(currpath.join("example01Dict.so"))
 
 def setup_module(mod):
+    # force removal of ROOTSYS for this one test, which serves as a test itself
+    if os.getenv("ROOTSYS"):
+        os.unsetenv("ROOTSYS")
     if sys.platform == 'win32':
         py.test.skip("win32 not supported so far")
     err = os.system("cd '%s' && make example01Dict.so" % currpath)
diff --git a/pypy/module/micronumpy/interp_arrayops.py b/pypy/module/micronumpy/interp_arrayops.py
--- a/pypy/module/micronumpy/interp_arrayops.py
+++ b/pypy/module/micronumpy/interp_arrayops.py
@@ -109,19 +109,19 @@
     _axis = axis
     if axis < 0:
         _axis = len(shape) + axis
-    if _axis < 0 or len(shape) <= _axis:
-        raise operationerrfmt(space.w_IndexError, "axis %d out of bounds [0, %d)", axis, len(shape))
     for arr in args_w[1:]:
-        dtype = interp_ufuncs.find_binop_result_dtype(space, dtype,
-                                                      arr.get_dtype())
-        if _axis < 0 or len(arr.get_shape()) <= _axis:
-            raise operationerrfmt(space.w_IndexError, "axis %d out of bounds [0, %d)", axis, len(shape))
         for i, axis_size in enumerate(arr.get_shape()):
             if len(arr.get_shape()) != len(shape) or (i != _axis and axis_size != shape[i]):
                 raise OperationError(space.w_ValueError, space.wrap(
                     "all the input arrays must have same number of dimensions"))
             elif i == _axis:
                 shape[i] += axis_size
+        dtype = interp_ufuncs.find_binop_result_dtype(space, dtype,
+                                                      arr.get_dtype())
+        if _axis < 0 or len(arr.get_shape()) <= _axis:
+            raise operationerrfmt(space.w_IndexError, "axis %d out of bounds [0, %d)", axis, len(shape))
+    if _axis < 0 or len(shape) <= _axis:
+        raise operationerrfmt(space.w_IndexError, "axis %d out of bounds [0, %d)", axis, len(shape))
     res = W_NDimArray.from_shape(shape, dtype, 'C')
     chunks = [Chunk(0, i, 1, i) for i in shape]
     axis_start = 0
diff --git a/pypy/module/micronumpy/interp_numarray.py b/pypy/module/micronumpy/interp_numarray.py
--- a/pypy/module/micronumpy/interp_numarray.py
+++ b/pypy/module/micronumpy/interp_numarray.py
@@ -136,6 +136,10 @@
     def getitem_array_int(self, space, w_index):
         prefix, res_shape, iter_shape, indexes = \
                 self._prepare_array_index(space, w_index)
+        if iter_shape is None:
+            # w_index is a list of slices, return a view
+            chunks = self.implementation._prepare_slice_args(space, w_index)
+            return chunks.apply(self)
         shape = res_shape + self.get_shape()[len(indexes):]
         res = W_NDimArray.from_shape(shape, self.get_dtype(), self.get_order())
         if not res.get_size():
@@ -147,8 +151,15 @@
         val_arr = convert_to_array(space, w_value)
         prefix, _, iter_shape, indexes = \
                 self._prepare_array_index(space, w_index)
-        return loop.setitem_array_int(space, self, iter_shape, indexes, val_arr,
-                                      prefix)
+        if iter_shape is None:
+            # w_index is a list of slices
+            w_value = convert_to_array(space, w_value)
+            chunks = self.implementation._prepare_slice_args(space, w_index)
+            view = chunks.apply(self)
+            view.implementation.setslice(space, w_value)
+            return
+        loop.setitem_array_int(space, self, iter_shape, indexes, val_arr,
+                               prefix)
 
     def descr_getitem(self, space, w_idx):
         if (isinstance(w_idx, W_NDimArray) and
@@ -169,9 +180,9 @@
 
     def descr_setitem(self, space, w_idx, w_value):
         if (isinstance(w_idx, W_NDimArray) and
-            w_idx.get_dtype().is_bool_type()):
-            return self.setitem_filter(space, w_idx,
-                                       convert_to_array(space, w_value))
+                w_idx.get_dtype().is_bool_type()):
+            self.setitem_filter(space, w_idx, convert_to_array(space, w_value))
+            return
         try:
             self.implementation.descr_setitem(space, self, w_idx, w_value)
         except ArrayArgumentException:
diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py
--- a/pypy/module/micronumpy/test/test_numarray.py
+++ b/pypy/module/micronumpy/test/test_numarray.py
@@ -1470,12 +1470,11 @@
         assert str(exc.value) == \
                 "all the input arrays must have same number of dimensions"
 
-        if 0: # XXX too pedantic
-            g1 = array([0,1,2])
-            g2 = array([[3,4,5]])
-            exc = raises(ValueError, concatenate, (g1, g2), axis=2)
-            assert str(exc.value) == \
-                    "all the input arrays must have same number of dimensions"
+        g1 = array([0,1,2])
+        g2 = array([[3,4,5]])
+        exc = raises(ValueError, concatenate, (g1, g2), axis=2)
+        assert str(exc.value) == \
+                "all the input arrays must have same number of dimensions"
 
         a = array([1, 2, 3, 4, 5, 6])
         a = (a + a)[::2]
@@ -2204,6 +2203,20 @@
         a[array([0, 2]), slice(0, 2)] = [[10, 11], [12, 13]]
         assert (a == [[10, 11], [3, 4], [12, 13]]).all()
 
+    def test_slice_vector_index(self):
+        from numpypy import arange
+        b = arange(145)
+        a = b[slice(25, 125, None)]
+        assert (a == range(25, 125)).all()
+        a = b[[slice(25, 125, None)]]
+        assert a.shape == (100,)
+        # a is a view into b
+        a[10] = 200
+        assert b[35] == 200
+        b[[slice(25, 30)]] = range(5)
+        assert all(a[:5] == range(5))
+        raises(TypeError, 'b[[[slice(25, 125)]]]')
+
     def test_cumsum(self):
         from numpypy import arange
         a = arange(6).reshape(3, 2)
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
@@ -22,6 +22,7 @@
                             'lastblock',
                             'is_being_profiled',
                             'w_globals',
+                            'w_f_trace',
                             ]
 
 JUMP_ABSOLUTE = opmap['JUMP_ABSOLUTE']
@@ -39,9 +40,6 @@
 def set_jitcell_at(newcell, next_instr, is_being_profiled, bytecode):
     bytecode.jit_cells[next_instr, is_being_profiled] = newcell
 
-def confirm_enter_jit(next_instr, is_being_profiled, bytecode, frame, ec):
-    return (frame.w_f_trace is None and
-            ec.w_tracefunc is None)
 
 def can_never_inline(next_instr, is_being_profiled, bytecode):
     return False
@@ -57,7 +55,6 @@
 pypyjitdriver = PyPyJitDriver(get_printable_location = get_printable_location,
                               get_jitcell_at = get_jitcell_at,
                               set_jitcell_at = set_jitcell_at,
-                              confirm_enter_jit = confirm_enter_jit,
                               can_never_inline = can_never_inline,
                               should_unroll_one_iteration =
                               should_unroll_one_iteration,
diff --git a/pypy/module/pypyjit/interp_resop.py b/pypy/module/pypyjit/interp_resop.py
--- a/pypy/module/pypyjit/interp_resop.py
+++ b/pypy/module/pypyjit/interp_resop.py
@@ -5,14 +5,14 @@
 from pypy.interpreter.gateway import unwrap_spec, interp2app
 from pypy.interpreter.pycode import PyCode
 from pypy.interpreter.error import OperationError
-from rpython.rtyper.lltypesystem import lltype, llmemory
+from rpython.rtyper.lltypesystem import lltype
 from rpython.rtyper.annlowlevel import cast_base_ptr_to_instance, hlstr
 from rpython.rtyper.lltypesystem.rclass import OBJECT
-from rpython.jit.metainterp.resoperation import rop, AbstractResOp
+from rpython.jit.metainterp.resoperation import rop
 from rpython.rlib.nonconst import NonConstant
 from rpython.rlib import jit_hooks
 from rpython.rlib.jit import Counters
-from rpython.rlib.rarithmetic import r_uint
+from rpython.rlib.objectmodel import compute_unique_id
 from pypy.module.pypyjit.interp_jit import pypyjitdriver
 
 class Cache(object):
@@ -270,7 +270,8 @@
         self.jd_name = debug_info.get_jitdriver().name
         self.type = debug_info.type
         if is_bridge:
-            self.bridge_no = debug_info.fail_descr_no
+            self.bridge_no = compute_unique_id(debug_info.fail_descr)
+            #self.bridge_no = debug_info.fail_descr_no
             self.w_green_key = space.w_None
         else:
             self.w_green_key = wrap_greenkey(space,
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
@@ -106,7 +106,7 @@
                        'posix', '_socket', '_sre', '_lsprof', '_weakref',
                        '__pypy__', 'cStringIO', '_collections', 'struct',
                        'mmap', 'marshal', '_codecs', 'rctime', 'cppyy',
-                       '_cffi_backend', 'pyexpat']:
+                       '_cffi_backend', 'pyexpat', '_continuation']:
             if modname == 'pypyjit' and 'interp_resop' in rest:
                 return False
             return True
diff --git a/pypy/module/pypyjit/test/test_jit_hook.py b/pypy/module/pypyjit/test/test_jit_hook.py
--- a/pypy/module/pypyjit/test/test_jit_hook.py
+++ b/pypy/module/pypyjit/test/test_jit_hook.py
@@ -2,7 +2,8 @@
 import py
 from pypy.interpreter.gateway import interp2app
 from pypy.interpreter.pycode import PyCode
-from rpython.jit.metainterp.history import JitCellToken, ConstInt, ConstPtr
+from rpython.jit.metainterp.history import JitCellToken, ConstInt, ConstPtr,\
+     BasicFailDescr
 from rpython.jit.metainterp.resoperation import rop
 from rpython.jit.metainterp.logger import Logger
 from rpython.rtyper.annlowlevel import (cast_instance_to_base_ptr,
@@ -69,7 +70,7 @@
                                         oplist, 'loop', greenkey)
         di_loop.asminfo = AsmInfo(offset, 0, 0)
         di_bridge = JitDebugInfo(MockJitDriverSD, logger, JitCellToken(),
-                                 oplist, 'bridge', fail_descr_no=0)
+                                 oplist, 'bridge', fail_descr=BasicFailDescr())
         di_bridge.asminfo = AsmInfo(offset, 0, 0)
 
         def interp_on_compile():
diff --git a/pypy/module/test_lib_pypy/test_marshal_extra.py b/pypy/module/test_lib_pypy/test_marshal_extra.py
--- a/pypy/module/test_lib_pypy/test_marshal_extra.py
+++ b/pypy/module/test_lib_pypy/test_marshal_extra.py
@@ -144,3 +144,8 @@
 def test_load_truncated_string():
     s = '(\x02\x00\x00\x00i\x03\x00\x00\x00sB\xf9\x00\x00\nabcd'
     py.test.raises(EOFError, marshal.loads, s)
+
+def test_dump_unicode_length():
+    s = b'123\xe9'.decode('latin-1')
+    r = marshal.dumps(s)
+    assert r == b'u\x05\x00\x00\x00123\xc3\xa9'
diff --git a/pypy/module/test_lib_pypy/test_sqlite3.py b/pypy/module/test_lib_pypy/test_sqlite3.py
--- a/pypy/module/test_lib_pypy/test_sqlite3.py
+++ b/pypy/module/test_lib_pypy/test_sqlite3.py
@@ -57,11 +57,34 @@
     cur = con.cursor()
     with pytest.raises(StopIteration):
         next(cur)
-    cur = con.execute('select 1')
+
+    cur.execute('select 1')
     next(cur)
     with pytest.raises(StopIteration):
         next(cur)
 
+    cur.execute('select 1')
+    con.commit()
+    next(cur)
+    with pytest.raises(StopIteration):
+        next(cur)
+
+    with pytest.raises(_sqlite3.ProgrammingError):
+        cur.executemany('select 1', [])
+    with pytest.raises(StopIteration):
+        next(cur)
+
+    cur.execute('select 1')
+    cur.execute('create table test(ing)')
+    with pytest.raises(StopIteration):
+        next(cur)
+
+    cur.execute('select 1')
+    cur.execute('insert into test values(1)')
+    con.commit()
+    with pytest.raises(StopIteration):
+        next(cur)
+
 def test_cursor_after_close():
      con = _sqlite3.connect(':memory:')
      cur = con.execute('select 1')
@@ -136,6 +159,7 @@
         con.commit()
     except _sqlite3.OperationalError:
         pytest.fail("_sqlite3 knew nothing about the implicit ROLLBACK")
+    con.close()
 
 def test_statement_arg_checking():
     con = _sqlite3.connect(':memory:')
@@ -171,3 +195,4 @@
     with pytest.raises(ValueError) as e:
         con.execute('insert into foo(x) values (?)', 2)
     assert str(e.value) == 'parameters are of unsupported type'
+    con.close()
diff --git a/pypy/objspace/std/dictmultiobject.py b/pypy/objspace/std/dictmultiobject.py
--- a/pypy/objspace/std/dictmultiobject.py
+++ b/pypy/objspace/std/dictmultiobject.py
@@ -107,15 +107,13 @@
         for w_k, w_v in list_pairs_w:
             w_self.setitem(w_k, w_v)
 
-    def view_as_kwargs(self):
-        return self.strategy.view_as_kwargs(self)
-
 def _add_indirections():
     dict_methods = "setitem setitem_str getitem \
                     getitem_str delitem length \
                     clear w_keys values \
                     items iterkeys itervalues iteritems setdefault \
-                    popitem listview_str listview_unicode listview_int".split()
+                    popitem listview_str listview_unicode listview_int \
+                    view_as_kwargs".split()
 
     def make_method(method):
         def f(self, *args):
@@ -123,9 +121,6 @@
         f.func_name = method
         return f
 
-    def view_as_kwargs(self):
-        return self.strategy.view_as_kwargs(self)
-
     for method in dict_methods:
         setattr(W_DictMultiObject, method, make_method(method))
 
@@ -573,6 +568,12 @@
     def w_keys(self, w_dict):
         return self.space.newlist(self.unerase(w_dict.dstorage).keys())
 
+    def setitem_str(self, w_dict, s, w_value):
+        self.setitem(w_dict, self.space.wrap(s), w_value)
+
+    def switch_to_object_strategy(self, w_dict):
+        assert 0, "should be unreachable"
+
 create_iterator_classes(ObjectDictStrategy)
 
 class StringDictStrategy(AbstractTypedStrategy, DictStrategy):
diff --git a/pypy/tool/jitlogparser/parser.py b/pypy/tool/jitlogparser/parser.py
--- a/pypy/tool/jitlogparser/parser.py
+++ b/pypy/tool/jitlogparser/parser.py
@@ -34,7 +34,7 @@
         self.descr = descr
         self._is_guard = name.startswith('guard_')
         if self._is_guard:
-            self.guard_no = int(self.descr[len('<Guard'):-1])
+            self.guard_no = int(self.descr[len('<Guard'):-1], 16)
 
     def setfailargs(self, failargs):
         self.failargs = failargs
@@ -350,7 +350,7 @@
     i = 0
     while i < len(ops):
         op = ops[i]
-        if op.is_guard() and bridges.get('loop-' + str(op.guard_no), None):
+        if op.is_guard() and bridges.get('loop-' + hex(op.guard_no)[2:], None):
             res.append(op)
             i = 0
             if hasattr(op.bridge, 'force_asm'):
@@ -372,7 +372,7 @@
             m = re.search('has address ([-\da-f]+)', entry)
             addr = int(m.group(1), 16)
             entry = entry.lower()
-            m = re.search('guard \d+', entry)
+            m = re.search('guard [\da-f]+', entry)
             name = m.group(0)
         else:
             name = entry[:entry.find('(') - 1].lower()
@@ -395,8 +395,8 @@
         comm = loop.comment
         comm = comm.lower()
         if comm.startswith('# bridge'):
-            m = re.search('guard \d+', comm)
-            name = m.group(0)
+            m = re.search('guard (\d+)', comm)
+            name = 'guard ' + hex(int(m.group(1)))[2:]
         elif "(" in comm:
             name = comm[2:comm.find('(')-1]
         else:
@@ -414,7 +414,7 @@
 def split_trace(trace):
     labels = [0]
     if trace.comment and 'Guard' in trace.comment:
-        descrs = ['bridge ' + re.search('Guard (\d+)', trace.comment).group(1)]
+        descrs = ['bridge ' + re.search('Guard ([\da-f]+)', trace.comment).group(1)]
     else:
         descrs = ['entry ' + re.search('Loop (\d+)', trace.comment).group(1)]
     for i, op in enumerate(trace.operations):
@@ -444,3 +444,7 @@
         if line:
             num, count = line.split(':', 2)
             mapping[num].count = int(count)
+
+if __name__ == '__main__':
+    import_log(sys.argv[1])
+    
diff --git a/pypy/tool/jitlogparser/storage.py b/pypy/tool/jitlogparser/storage.py
--- a/pypy/tool/jitlogparser/storage.py
+++ b/pypy/tool/jitlogparser/storage.py
@@ -63,14 +63,14 @@
         for loop_no, loop in enumerate(loops):
             for op in loop.operations:
                 if op.name.startswith('guard_'):
-                    guard_dict[int(op.descr[len('<Guard'):-1])] = (op, loop)
+                    guard_dict[int(op.descr[len('<Guard'):-1], 16)] = (op, loop)
         for loop in loops:
             if loop.comment:
                 comment = loop.comment.strip()
                 if 'entry bridge' in comment:
                     pass
                 elif comment.startswith('# bridge out of'):
-                    no = int(comment[len('# bridge out of Guard '):].split(' ', 1)[0])
+                    no = int(comment[len('# bridge out of Guard '):].split(' ', 1)[0], 16)
                     op, parent = guard_dict[no]
                     op.bridge = loop
                     op.percentage = ((getattr(loop, 'count', 1) * 100) /
diff --git a/pypy/tool/jitlogparser/test/test_parser.py b/pypy/tool/jitlogparser/test/test_parser.py
--- a/pypy/tool/jitlogparser/test/test_parser.py
+++ b/pypy/tool/jitlogparser/test/test_parser.py
@@ -162,23 +162,23 @@
     loops = LoopStorage().reconnect_loops([main, bridge, entry_bridge])
     assert len(loops) == 2
     assert len(loops[0].operations[0].bridge.operations) == 1
-    assert loops[0].operations[0].bridge.no == 18
+    assert loops[0].operations[0].bridge.no == 0x18
     assert loops[0].operations[0].percentage == 30
 
 def test_adjust_bridges():
     main = parse('''
     [v0]
-    guard_false(v0, descr=<Guard13>)
+    guard_false(v0, descr=<Guard1a>)
     guard_true(v0, descr=<Guard5>)
     ''')
     bridge = parse('''
-    # bridge out of Guard 13
+    # bridge out of Guard 1a
     []
     int_add(0, 1)
     ''')
     LoopStorage().reconnect_loops([main, bridge])
     assert adjust_bridges(main, {})[1].name == 'guard_true'
-    assert adjust_bridges(main, {'loop-13': True})[1].name == 'int_add'
+    assert adjust_bridges(main, {'loop-1a': True})[1].name == 'int_add'
 
 def test_parsing_strliteral():
     loop = parse("""
@@ -259,7 +259,7 @@
 +348: i32 = int_is_true(i31)
 +360: i33 = int_or(i27, i32)
 +364: i34 = int_is_true(i33)
-guard_false(i34, descr=<Guard89>) [i1, i22, p2]
+guard_false(i34, descr=<Guard8a>) [i1, i22, p2]
 +372: i35 = int_add(i22, 1)
 debug_merge_point(0, 're StrMatchIn at 92 [17. 4. 0. 20. 393237. 21. 0. 29. 9. 1. 65535. 15. 4. 9. 3. 0. 1. 21. 1. 29. 9. 1. 65535. 15. 4. 9. 2. 0. 1. 1...')
 +376: jump(i35, i1, p2, p4, descr=TargetToken(1081858656))
@@ -323,7 +323,7 @@
     [i7]
     i9 = int_lt(i7, 1003)
     label(i9, descr=grrr)
-    guard_true(i9, descr=<Guard2>) []
+    guard_true(i9, descr=<Guardaf>) []
     i13 = getfield_raw(151937600, descr=<SignedFieldDescr pypysig_long_struct.c_value 0>)
     label(i13, descr=asb)
     i19 = int_lt(i13, 1003)
@@ -336,10 +336,10 @@
     i0 = int_lt(1, 2)
     finish(i0)
     ''')
-    bridge.comment = 'bridge out of Guard 2 with 1 ops'
+    bridge.comment = 'bridge out of Guard af with 1 ops'
     loop.comment = 'Loop 0'
     loops = split_trace(loop) + split_trace(bridge)
-    input = ['grrr:123\nasb:12\nbridge 2:1234']
+    input = ['grrr:123\nasb:12\nbridge af:1234']
     parse_log_counts(input, loops)
     assert loops[-1].count == 1234
     assert loops[1].count == 123
diff --git a/rpython/annotator/binaryop.py b/rpython/annotator/binaryop.py
--- a/rpython/annotator/binaryop.py
+++ b/rpython/annotator/binaryop.py
@@ -143,13 +143,9 @@
         # XXX HACK HACK HACK
         bk = getbookkeeper()
         if bk is not None: # for testing
+            op = bk._find_current_op("is_", 2)
             knowntypedata = {}
-            fn, block, i = bk.position_key
-
             annotator = bk.annotator
-            op = block.operations[i]
-            assert op.opname == "is_" 
-            assert len(op.args) == 2                
 
             def bind(src_obj, tgt_obj, tgt_arg):
                 if hasattr(tgt_obj, 'is_type_of') and src_obj.is_constant():
@@ -319,11 +315,7 @@
                 rarithmetic.signedtype(int2.knowntype)):
             return r
         knowntypedata = {}
-        # XXX HACK HACK HACK
-        fn, block, i = getbookkeeper().position_key
-        op = block.operations[i]
-        assert op.opname == opname
-        assert len(op.args) == 2
+        op = getbookkeeper()._find_current_op(opname=opname, arity=2)
         def tointtype(int0):
             if int0.knowntype is bool:
                 return int
diff --git a/rpython/annotator/bookkeeper.py b/rpython/annotator/bookkeeper.py
--- a/rpython/annotator/bookkeeper.py
+++ b/rpython/annotator/bookkeeper.py
@@ -693,6 +693,20 @@
             if emulate_enter:
                 self.leave()
 
+    def _find_current_op(self, opname=None, arity=None, pos=None, s_type=None):
+        """ Find operation that is currently being annotated. Do some
+        sanity checks to see whether the correct op was found."""
+        # XXX XXX HACK HACK HACK
+        fn, block, i = self.position_key
+        op = block.operations[i]
+        if opname is not None:
+            assert op.opname == opname or op.opname in opname
+        if arity is not None:
+            assert len(op.args) == arity
+        if pos is not None:
+            assert self.annotator.binding(op.args[pos]) == s_type
+        return op
+
     def build_args(self, op, args_s):
         space = RPythonCallsSpace()
         if op == "simple_call":
diff --git a/rpython/annotator/builtin.py b/rpython/annotator/builtin.py
--- a/rpython/annotator/builtin.py
+++ b/rpython/annotator/builtin.py
@@ -178,15 +178,9 @@
                                                    # from bool to int, notice that isinstance( , bool|int)
                                                    # is quite border case for RPython
                 r.const = False
-        # XXX HACK HACK HACK
-        # XXX HACK HACK HACK
-        # XXX HACK HACK HACK
         bk = getbookkeeper()
         if variables is None:
-            fn, block, i = bk.position_key
-            op = block.operations[i]
-            assert op.opname == "simple_call" 
-            assert len(op.args) == 3
+            op = bk._find_current_op("simple_call", 3)
             assert op.args[0] == Constant(isinstance)
             variables = [op.args[1]]
         for variable in variables:
diff --git a/rpython/annotator/description.py b/rpython/annotator/description.py
--- a/rpython/annotator/description.py
+++ b/rpython/annotator/description.py
@@ -306,8 +306,10 @@
             result = schedule(graph, inputcells)
             signature = getattr(self.pyobj, '_signature_', None)
             if signature:
-                result = enforce_signature_return(self, signature[1], result)
-                self.bookkeeper.annotator.addpendingblock(graph, graph.returnblock, [result])
+                sigresult = enforce_signature_return(self, signature[1], result)
+                if sigresult is not None:
+                    self.bookkeeper.annotator.addpendingblock(graph, graph.returnblock, [sigresult])
+                    result = sigresult
         # Some specializations may break the invariant of returning
         # annotations that are always more general than the previous time.
         # We restore it here:
diff --git a/rpython/annotator/model.py b/rpython/annotator/model.py
--- a/rpython/annotator/model.py
+++ b/rpython/annotator/model.py
@@ -233,6 +233,9 @@
     def nonnoneify(self):
         return self.__class__(can_be_None=False, no_nul=self.no_nul)
 
+    def nonnulify(self):
+        return self.__class__(can_be_None=self.can_be_None, no_nul=True)
+
 class SomeString(SomeStringOrUnicode):
     "Stands for an object which is known to be a string."
     knowntype = str
diff --git a/rpython/annotator/signature.py b/rpython/annotator/signature.py
--- a/rpython/annotator/signature.py
+++ b/rpython/annotator/signature.py
@@ -132,11 +132,13 @@
         inputcells[:] = args_s
 
 def finish_type(paramtype, bookkeeper, func):
-    from rpython.rlib.types import SelfTypeMarker
+    from rpython.rlib.types import SelfTypeMarker, AnyTypeMarker
     if isinstance(paramtype, SomeObject):
         return paramtype
     elif isinstance(paramtype, SelfTypeMarker):
         raise Exception("%r argument declared as annotation.types.self(); class needs decorator rlib.signature.finishsigs()" % (func,))
+    elif isinstance(paramtype, AnyTypeMarker):
+        return None
     else:
         return paramtype(bookkeeper)
 
@@ -144,15 +146,20 @@
     assert len(paramtypes) == len(actualtypes)
     params_s = [finish_type(paramtype, funcdesc.bookkeeper, funcdesc.pyobj) for paramtype in paramtypes]
     for i, (s_param, s_actual) in enumerate(zip(params_s, actualtypes)):
+        if s_param is None: # can be anything
+            continue
         if not s_param.contains(s_actual):
             raise Exception("%r argument %d:\n"
                             "expected %s,\n"
                             "     got %s" % (funcdesc, i+1, s_param, s_actual))
-    actualtypes[:] = params_s
+    for i, s_param in enumerate(params_s):
+        if s_param is None:
+            continue
+        actualtypes[i] = s_param
 
 def enforce_signature_return(funcdesc, sigtype, inferredtype):
     s_sigret = finish_type(sigtype, funcdesc.bookkeeper, funcdesc.pyobj)
-    if not s_sigret.contains(inferredtype):
+    if s_sigret is not None and not s_sigret.contains(inferredtype):
         raise Exception("%r return value:\n"
                         "expected %s,\n"
                         "     got %s" % (funcdesc, s_sigret, inferredtype))
diff --git a/rpython/annotator/test/test_annrpython.py b/rpython/annotator/test/test_annrpython.py
--- a/rpython/annotator/test/test_annrpython.py
+++ b/rpython/annotator/test/test_annrpython.py
@@ -446,6 +446,25 @@
         s_item = s.listdef.listitem.s_value
         assert s_item.no_nul
 
+    def test_str_split_nul(self):
+        def f(n):
+            return n.split('\0')[0]
+        a = self.RPythonAnnotator()
+        a.translator.config.translation.check_str_without_nul = True
+        s = a.build_types(f, [annmodel.SomeString(no_nul=False, can_be_None=False)])
+        assert isinstance(s, annmodel.SomeString)
+        assert not s.can_be_None
+        assert s.no_nul
+
+        def g(n):
+            return n.split('\0', 1)[0]
+        a = self.RPythonAnnotator()
+        a.translator.config.translation.check_str_without_nul = True
+        s = a.build_types(g, [annmodel.SomeString(no_nul=False, can_be_None=False)])
+        assert isinstance(s, annmodel.SomeString)
+        assert not s.can_be_None
+        assert not s.no_nul
+
     def test_str_splitlines(self):
         a = self.RPythonAnnotator()
         def f(a_str):
@@ -3762,6 +3781,19 @@
         assert isinstance(s, annmodel.SomeString)
         assert not s.can_be_None
 
+    def test_contains_no_nul(self):
+        def f(i):
+            if "\0" in i:
+                return None
+            else:
+                return i
+        a = self.RPythonAnnotator()
+        a.translator.config.translation.check_str_without_nul = True
+        s = a.build_types(f, [annmodel.SomeString(no_nul=False)])
+        assert isinstance(s, annmodel.SomeString)
+        assert s.can_be_None
+        assert s.no_nul
+
     def test_no___call__(self):
         class X(object):
             def __call__(self):
diff --git a/rpython/annotator/unaryop.py b/rpython/annotator/unaryop.py
--- a/rpython/annotator/unaryop.py
+++ b/rpython/annotator/unaryop.py
@@ -43,12 +43,7 @@
             raise Exception, 'type() called with more than one argument'
         r = SomeType()
         bk = getbookkeeper()
-        fn, block, i = bk.position_key
-        annotator = bk.annotator
-        op = block.operations[i]
-        assert op.opname == "type"
-        assert len(op.args) == 1
-        assert annotator.binding(op.args[0]) == obj
+        op = bk._find_current_op(opname="type", arity=1, pos=0, s_type=obj)
         r.is_type_of = [op.args[0]]
         return r
 
@@ -79,10 +74,7 @@
 
         bk = getbookkeeper()
         knowntypedata = {}
-        fn, block, i = bk.position_key
-        op = block.operations[i]
-        assert op.opname == "is_true" or op.opname == "nonzero"
-        assert len(op.args) == 1
+        op = bk._find_current_op(opname=("is_true", "nonzero"), arity=1)
         arg = op.args[0]
         s_nonnone_obj = s_obj
         if s_obj.can_be_none():
@@ -504,7 +496,11 @@
 
     def method_split(str, patt, max=-1):
         getbookkeeper().count("str_split", str, patt)
-        s_item = str.basestringclass(no_nul=str.no_nul)
+        if max == -1 and patt.is_constant() and patt.const == "\0":
+            no_nul = True
+        else:
+            no_nul = str.no_nul
+        s_item = str.basestringclass(no_nul=no_nul)
         return getbookkeeper().newlist(s_item)
 
     def method_rsplit(str, patt, max=-1):
@@ -520,6 +516,20 @@
         result = str.basestringclass(no_nul=str.no_nul)
         return result
 
+    def op_contains(str, s_element):
+        if s_element.is_constant() and s_element.const == "\0":
+            r = SomeBool()
+            bk = getbookkeeper()
+            op = bk._find_current_op(opname="contains", arity=2, pos=0, s_type=str)
+            knowntypedata = {}
+            add_knowntypedata(knowntypedata, False, [op.args[0]], str.nonnulify())
+            r.set_knowntypedata(knowntypedata)
+            return r
+        else:
+            return SomeObject.op_contains(str, s_element)
+    op_contains.can_only_throw = []
+
+
 class __extend__(SomeUnicodeString):
     def method_encode(uni, s_enc):
         if not s_enc.is_constant():
diff --git a/rpython/jit/backend/arm/arch.py b/rpython/jit/backend/arm/arch.py
--- a/rpython/jit/backend/arm/arch.py
+++ b/rpython/jit/backend/arm/arch.py
@@ -1,7 +1,3 @@
-from rpython.rtyper.lltypesystem import lltype, rffi
-from rpython.rlib.rarithmetic import r_uint
-
-
 FUNC_ALIGN = 8
 WORD = 4
 DOUBLE_WORD = 8
@@ -14,54 +10,12 @@
 PC_OFFSET = 8
 FORCE_INDEX_OFS = 0
 
-from rpython.translator.tool.cbuild import ExternalCompilationInfo
-eci = ExternalCompilationInfo(post_include_bits=["""
-static int pypy__arm_int_div(int a, int b) {
-    return a/b;
-}
-static unsigned int pypy__arm_uint_div(unsigned int a, unsigned int b) {
-    return a/b;
-}
-static int pypy__arm_int_mod(int a, int b) {
-    return a % b;
-}
-"""])
-
-
-def arm_int_div_emulator(a, b):
-    return int(a / float(b))
-arm_int_div_sign = lltype.Ptr(
-        lltype.FuncType([lltype.Signed, lltype.Signed], lltype.Signed))
-arm_int_div = rffi.llexternal(
-    "pypy__arm_int_div", [lltype.Signed, lltype.Signed], lltype.Signed,
-                        _callable=arm_int_div_emulator,
-                        compilation_info=eci,
-                        _nowrapper=True, elidable_function=True)
-
-
-def arm_uint_div_emulator(a, b):
-    return r_uint(a) / r_uint(b)
-arm_uint_div_sign = lltype.Ptr(
-        lltype.FuncType([lltype.Unsigned, lltype.Unsigned], lltype.Unsigned))
-arm_uint_div = rffi.llexternal(
-    "pypy__arm_uint_div", [lltype.Unsigned, lltype.Unsigned], lltype.Unsigned,
-                        _callable=arm_uint_div_emulator,
-                        compilation_info=eci,
-                        _nowrapper=True, elidable_function=True)
-
-
-def arm_int_mod_emulator(a, b):
-    sign = 1
-    if a < 0:
-        a = -1 * a
-        sign = -1
-    if b < 0:
-        b = -1 * b
-    res = a % b
-    return sign * res
-arm_int_mod_sign = arm_int_div_sign
-arm_int_mod = rffi.llexternal(
-    "pypy__arm_int_mod", [lltype.Signed, lltype.Signed], lltype.Signed,
-                        _callable=arm_int_mod_emulator,
-                        compilation_info=eci,
-                        _nowrapper=True, elidable_function=True)
+# The stack contains the force_index and the, callee saved registers and
+# ABI required information
+# All the rest of the data is in a GC-managed variable-size "frame".
+# This jitframe object's address is always stored in the register FP
+# A jitframe is a jit.backend.llsupport.llmodel.jitframe.JITFRAME
+# Stack frame fixed area
+# Currently only the force_index
+JITFRAME_FIXED_SIZE = 11 + 16 * 2 + 1
+# 11 GPR + 16 VFP Regs (64bit) + 1 word for alignment
diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py
--- a/rpython/jit/backend/arm/assembler.py
+++ b/rpython/jit/backend/arm/assembler.py
@@ -1,91 +1,64 @@
 from __future__ import with_statement
+
 import os
+
+from rpython.jit.backend.arm import conditions as c, registers as r
+from rpython.jit.backend.arm.arch import (WORD, DOUBLE_WORD, FUNC_ALIGN,
+    JITFRAME_FIXED_SIZE)
+from rpython.jit.backend.arm.codebuilder import ARMv7Builder, OverwritingBuilder
+from rpython.jit.backend.arm.locations import imm, StackLocation
+from rpython.jit.backend.arm.opassembler import ResOpAssembler
+from rpython.jit.backend.arm.regalloc import (Regalloc,
+    CoreRegisterManager, check_imm_arg, VFPRegisterManager,
+    operations as regalloc_operations,
+    operations_with_guard as regalloc_operations_with_guard)
 from rpython.jit.backend.llsupport import jitframe
-from rpython.jit.backend.arm.helper.assembler import saved_registers
-from rpython.jit.backend.arm import conditions as c
-from rpython.jit.backend.arm import registers as r
-from rpython.jit.backend.arm.arch import WORD, DOUBLE_WORD, FUNC_ALIGN, \
-                                    N_REGISTERS_SAVED_BY_MALLOC
-from rpython.jit.backend.arm.codebuilder import ARMv7Builder, OverwritingBuilder
-from rpython.jit.backend.arm.locations import get_fp_offset
-from rpython.jit.backend.arm.regalloc import (Regalloc, ARMFrameManager,
-                    CoreRegisterManager, check_imm_arg,
-                    operations as regalloc_operations,
-                    operations_with_guard as regalloc_operations_with_guard)
+from rpython.jit.backend.llsupport.assembler import DEBUG_COUNTER
 from rpython.jit.backend.llsupport.asmmemmgr import MachineDataBlockWrapper
 from rpython.jit.backend.model import CompiledLoopToken
-from rpython.jit.codewriter import longlong
 from rpython.jit.codewriter.effectinfo import EffectInfo
-from rpython.jit.metainterp.history import AbstractFailDescr, INT, REF, FLOAT
-from rpython.jit.metainterp.history import BoxInt, ConstInt
-from rpython.jit.metainterp.resoperation import rop, ResOperation
-from rpython.rlib import rgc
-from rpython.rlib.objectmodel import we_are_translated, specialize
-from rpython.rtyper.annlowlevel import llhelper
-from rpython.rtyper.lltypesystem import lltype, rffi, llmemory
-from rpython.rtyper.lltypesystem.lloperation import llop
-from rpython.jit.backend.arm.opassembler import ResOpAssembler
-from rpython.rlib.debug import (debug_print, debug_start, debug_stop,
-                             have_debug_prints, fatalerror)
+from rpython.jit.metainterp.history import AbstractFailDescr, FLOAT
+from rpython.jit.metainterp.resoperation import rop
+from rpython.rlib.debug import debug_print, debug_start, debug_stop
 from rpython.rlib.jit import AsmInfo
-from rpython.rlib.objectmodel import compute_unique_id
-
-# XXX Move to llsupport
-from rpython.jit.backend.x86.support import memcpy_fn
-
-DEBUG_COUNTER = lltype.Struct('DEBUG_COUNTER', ('i', lltype.Signed),
-                              ('type', lltype.Char),  # 'b'ridge, 'l'abel or
-                                                      # 'e'ntry point
-                              ('number', lltype.Signed))
+from rpython.rlib.objectmodel import we_are_translated, specialize, compute_unique_id
+from rpython.rlib.rarithmetic import r_uint
+from rpython.rtyper.annlowlevel import llhelper, cast_instance_to_gcref
+from rpython.rtyper.lltypesystem import lltype, rffi
 
 
 class AssemblerARM(ResOpAssembler):
 
-    STACK_FIXED_AREA = -1
-
-    debug = True
+    debug = False
 
     def __init__(self, cpu, translate_support_code=False):
-        self.cpu = cpu
+        ResOpAssembler.__init__(self, cpu, translate_support_code)
         self.setup_failure_recovery()
         self.mc = None
-        self.memcpy_addr = 0
         self.pending_guards = None
         self._exit_code_addr = 0
         self.current_clt = None
         self.malloc_slowpath = 0
-        self.wb_slowpath = [0, 0, 0, 0]
+        self.wb_slowpath = [0, 0, 0, 0, 0]
         self._regalloc = None
         self.datablockwrapper = None
         self.propagate_exception_path = 0
         self.stack_check_slowpath = 0
-        self._compute_stack_size()
         self._debug = False
         self.loop_run_counters = []
         self.debug_counter_descr = cpu.fielddescrof(DEBUG_COUNTER, 'i')
-        self.force_token_to_dead_frame = {}    # XXX temporary hack
+        self.gcrootmap_retaddr_forced = 0
 
     def set_debug(self, v):
         r = self._debug
         self._debug = v
         return r
 
-    def _compute_stack_size(self):
-        self.STACK_FIXED_AREA = len(r.callee_saved_registers) * WORD
-        self.STACK_FIXED_AREA += WORD  # FORCE_TOKEN
-        self.STACK_FIXED_AREA += N_REGISTERS_SAVED_BY_MALLOC * WORD
-        if self.cpu.supports_floats:
-            self.STACK_FIXED_AREA += (len(r.callee_saved_vfp_registers)
-                                        * DOUBLE_WORD)
-        if self.STACK_FIXED_AREA % 8 != 0:
-            self.STACK_FIXED_AREA += WORD  # Stack alignment
-        assert self.STACK_FIXED_AREA % 8 == 0
-
-    def setup(self, looptoken, operations):
+    def setup(self, looptoken):
+        assert self.memcpy_addr != 0, 'setup_once() not called?'
+        if we_are_translated():
+            self.debug = False
         self.current_clt = looptoken.compiled_loop_token
-        operations = self.cpu.gc_ll_descr.rewrite_assembler(self.cpu,
-                        operations, self.current_clt.allgcrefs)
-        assert self.memcpy_addr != 0, 'setup_once() not called?'
         self.mc = ARMv7Builder()
         self.pending_guards = []
         assert self.datablockwrapper is None
@@ -93,7 +66,6 @@
         self.datablockwrapper = MachineDataBlockWrapper(self.cpu.asmmemmgr,
                                                         allblocks)
         self.target_tokens_currently_compiling = {}
-        return operations
 
     def teardown(self):
         self.current_clt = None
@@ -102,34 +74,8 @@
         self.pending_guards = None
         assert self.datablockwrapper is None
 
-    def setup_once(self):
-        # Addresses of functions called by new_xxx operations
-        gc_ll_descr = self.cpu.gc_ll_descr
-        gc_ll_descr.initialize()
-        self._build_wb_slowpath(False)
-        self._build_wb_slowpath(True)
-        self._build_failure_recovery(exc=True, withfloats=False)
-        self._build_failure_recovery(exc=False, withfloats=False)
-        if self.cpu.supports_floats:
-            self._build_wb_slowpath(False, withfloats=True)
-            self._build_wb_slowpath(True, withfloats=True)
-            self._build_failure_recovery(exc=True, withfloats=True)
-            self._build_failure_recovery(exc=False, withfloats=True)
-        self._build_propagate_exception_path()
-        if gc_ll_descr.get_malloc_slowpath_addr is not None:
-            self._build_malloc_slowpath()
-        self._build_stack_check_slowpath()
-        if gc_ll_descr.gcrootmap and gc_ll_descr.gcrootmap.is_shadow_stack:
-            self._build_release_gil(gc_ll_descr.gcrootmap)
-        self.memcpy_addr = self.cpu.cast_ptr_to_int(memcpy_fn)
-
-        if not self._debug:
-            # if self._debug is already set it means that someone called
-            # set_debug by hand before initializing the assembler. Leave it
-            # as it is
-            debug_start('jit-backend-counts')
-            self.set_debug(have_debug_prints())
-            debug_stop('jit-backend-counts')
+    def setup_failure_recovery(self):
+        self.failure_recovery_code = [0, 0, 0, 0]
 
     def finish_once(self):
         if self._debug:
@@ -162,18 +108,6 @@
         self.loop_run_counters.append(struct)
         return struct
 
-    def _append_debugging_code(self, operations, tp, number, token):
-        counter = self._register_counter(tp, number, token)
-        c_adr = ConstInt(rffi.cast(lltype.Signed, counter))
-        box = BoxInt()
-        box2 = BoxInt()
-        ops = [ResOperation(rop.GETFIELD_RAW, [c_adr],
-                            box, descr=self.debug_counter_descr),
-               ResOperation(rop.INT_ADD, [box, ConstInt(1)], box2),
-               ResOperation(rop.SETFIELD_RAW, [c_adr, box2],
-                            None, descr=self.debug_counter_descr)]
-        operations.extend(ops)
-
     @specialize.argtype(1)
     def _inject_debugging_code(self, looptoken, operations, tp, number):
         if self._debug:
@@ -218,22 +152,84 @@
         self.reacqgil_addr = rffi.cast(lltype.Signed, reacqgil_func)
 
     def _build_propagate_exception_path(self):
-        if self.cpu.propagate_exception_v < 0:
+        if not self.cpu.propagate_exception_descr:
             return      # not supported (for tests, or non-translated)
         #
         mc = ARMv7Builder()
-        #
-        # Call the helper, which will return a dead frame object with
-        # the correct exception set, or MemoryError by default
-        # XXX make sure we return the correct value here
-        addr = rffi.cast(lltype.Signed, self.cpu.get_propagate_exception())
-        mc.BL(addr)
-        self.gen_func_epilog(mc=mc)
-        self.propagate_exception_path = mc.materialize(self.cpu.asmmemmgr, [])
+        self._store_and_reset_exception(mc, r.r0)
+        ofs = self.cpu.get_ofs_of_frame_field('jf_guard_exc')
+        # make sure ofs fits into a register
+        assert check_imm_arg(ofs)
+        mc.LDR_ri(r.r0.value, r.fp.value, imm=ofs)
+        propagate_exception_descr = rffi.cast(lltype.Signed,
+                  cast_instance_to_gcref(self.cpu.propagate_exception_descr))
+        # put propagate_exception_descr into frame
+        ofs = self.cpu.get_ofs_of_frame_field('jf_descr')
+        # make sure ofs fits into a register
+        assert check_imm_arg(ofs)
+        mc.gen_load_int(r.r0.value, propagate_exception_descr)
+        mc.STR_ri(r.r0.value, r.fp.value, imm=ofs)
+        mc.MOV_rr(r.r0.value, r.fp.value)
+        self.gen_func_epilog(mc)
+        rawstart = mc.materialize(self.cpu.asmmemmgr, [])
+        self.propagate_exception_path = rawstart
+
+    def _store_and_reset_exception(self, mc, excvalloc=None, exctploc=None,
+                                                                on_frame=False):
+        """ Resest the exception. If excvalloc is None, then store it on the
+        frame in jf_guard_exc
+        """
+        assert excvalloc is not r.ip
+        assert exctploc is not r.ip
+        tmpreg = r.lr
+        mc.gen_load_int(r.ip.value, self.cpu.pos_exc_value())
+        if excvalloc is not None: # store
+            assert excvalloc.is_reg()
+            self.load_reg(mc, excvalloc, r.ip)
+        if on_frame:
+            # store exc_value in JITFRAME
+            ofs = self.cpu.get_ofs_of_frame_field('jf_guard_exc')
+            assert check_imm_arg(ofs)
+            self.store_reg(mc, r.ip, r.fp, ofs)
+        if exctploc is not None:
+            # store pos_exception in exctploc
+            assert exctploc.is_reg()
+            mc.gen_load_int(r.ip.value, self.cpu.pos_exception())
+            self.load_reg(mc, exctploc, r.ip)
+
+        # reset exception
+        mc.gen_load_int(tmpreg.value, 0)
+
+        self.store_reg(mc, tmpreg, r.ip, 0)
+
+        mc.gen_load_int(r.ip.value, self.cpu.pos_exception())
+        self.store_reg(mc, tmpreg, r.ip, 0)
+
+    def _restore_exception(self, mc, excvalloc, exctploc):
+        assert excvalloc is not r.ip
+        assert exctploc is not r.ip
+        tmpreg = r.lr # use lr as a second temporary reg
+        mc.gen_load_int(r.ip.value, self.cpu.pos_exc_value())
+        if excvalloc is not None:
+            assert excvalloc.is_reg()
+            self.store_reg(mc, excvalloc, r.ip)
+        else:
+            assert exctploc is not r.fp
+            # load exc_value from JITFRAME and put it in pos_exc_value
+            ofs = self.cpu.get_ofs_of_frame_field('jf_guard_exc')
+            self.load_reg(mc, tmpreg, r.fp, ofs)
+            self.store_reg(mc, tmpreg, r.ip)
+            # reset exc_value in the JITFRAME
+            mc.gen_load_int(tmpreg.value, 0)
+            self.store_reg(mc, tmpreg, r.fp, ofs)
+
+        # restore pos_exception from exctploc register
+        mc.gen_load_int(r.ip.value, self.cpu.pos_exception())
+        self.store_reg(mc, exctploc, r.ip)
 
     def _build_stack_check_slowpath(self):
         _, _, slowpathaddr = self.cpu.insert_stack_check()
-        if slowpathaddr == 0 or self.cpu.propagate_exception_v < 0:
+        if slowpathaddr == 0 or not self.cpu.propagate_exception_descr:
             return      # no stack check (for tests, or non-translated)
         #
         # make a "function" that is called immediately at the start of
@@ -257,7 +253,7 @@
         mc.gen_load_int(r.r0.value, self.cpu.pos_exception())
         mc.LDR_ri(r.r0.value, r.r0.value)
         mc.TST_rr(r.r0.value, r.r0.value)
-        # restore registers and return 
+        # restore registers and return
         # We check for c.EQ here, meaning all bits zero in this case
         mc.POP([reg.value for reg in r.argument_regs] + [r.pc.value], cond=c.EQ)
         #
@@ -276,7 +272,7 @@
         rawstart = mc.materialize(self.cpu.asmmemmgr, [])
         self.stack_check_slowpath = rawstart
 
-    def _build_wb_slowpath(self, withcards, withfloats=False):
+    def _build_wb_slowpath(self, withcards, withfloats=False, for_frame=False):
         descr = self.cpu.gc_ll_descr.write_barrier_descr
         if descr is None:
             return
@@ -295,12 +291,28 @@
         # It must keep stack alignment accordingly.
         mc = ARMv7Builder()
         #
-        if withfloats:
-            floats = r.caller_vfp_resp
+        exc0 = exc1 = None
+        mc.PUSH([r.ip.value, r.lr.value]) # push two words to keep alignment
+        if not for_frame:
+            self._push_all_regs_to_jitframe(mc, [], withfloats, callee_only=True)
         else:
-            floats = []
-        with saved_registers(mc, r.caller_resp + [r.ip, r.lr], floats):
-            mc.BL(func)
+            # we're possibly called from the slowpath of malloc
+            # save the caller saved registers
+            # assuming we do not collect here
+            exc0, exc1 = r.r4, r.r5
+            mc.PUSH([gpr.value for gpr in r.caller_resp] + [exc0.value, exc1.value])
+            mc.VPUSH([vfpr.value for vfpr in r.caller_vfp_resp])
+
+            self._store_and_reset_exception(mc, exc0, exc1)
+        mc.BL(func)
+        #
+        if not for_frame:
+            self._pop_all_regs_from_jitframe(mc, [], withfloats, callee_only=True)
+        else:
+            self._restore_exception(mc, exc0, exc1)
+            mc.VPOP([vfpr.value for vfpr in r.caller_vfp_resp])
+            mc.POP([gpr.value for gpr in r.caller_resp] +
+                            [exc0.value, exc1.value])
         #
         if withcards:
             # A final TEST8 before the RET, for the caller.  Careful to
@@ -310,350 +322,174 @@
                                     imm=descr.jit_wb_if_flag_byteofs)
             mc.TST_ri(r.ip.value, imm=0x80)
         #
-        mc.MOV_rr(r.pc.value, r.lr.value)
+        mc.POP([r.ip.value, r.pc.value])
         #
         rawstart = mc.materialize(self.cpu.asmmemmgr, [])
-        self.wb_slowpath[withcards + 2 * withfloats] = rawstart
-
-    def setup_failure_recovery(self):
-
-        #@rgc.no_collect -- XXX still true, but hacked gc_set_extra_threshold
-        def failure_recovery_func(mem_loc, frame_pointer, stack_pointer):
-            """mem_loc is a structure in memory describing where the values for
-            the failargs are stored.  frame loc is the address of the frame
-            pointer for the frame to be decoded frame """
-            vfp_registers = rffi.cast(rffi.LONGP, stack_pointer)
-            registers = rffi.ptradd(vfp_registers, 2*len(r.all_vfp_regs))
-            registers = rffi.cast(rffi.LONGP, registers)


More information about the pypy-commit mailing list