[pypy-commit] pypy py3k: hg merge default

amauryfa noreply at buildbot.pypy.org
Tue Nov 22 22:18:43 CET 2011


Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: py3k
Changeset: r49674:4a4118ac402e
Date: 2011-11-22 22:17 +0100
http://bitbucket.org/pypy/pypy/changeset/4a4118ac402e/

Log:	hg merge default

diff --git a/.hgtags b/.hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -1,3 +1,4 @@
 b590cf6de4190623aad9aa698694c22e614d67b9 release-1.5
 b48df0bf4e75b81d98f19ce89d4a7dc3e1dab5e5 benchmarked
 d8ac7d23d3ec5f9a0fa1264972f74a010dbfd07f release-1.6
+ff4af8f318821f7f5ca998613a60fca09aa137da release-1.7
diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py
--- a/lib_pypy/_sqlite3.py
+++ b/lib_pypy/_sqlite3.py
@@ -231,6 +231,9 @@
 sqlite.sqlite3_result_text.argtypes = [c_void_p, c_char_p, c_int, c_void_p]
 sqlite.sqlite3_result_text.restype = None
 
+sqlite.sqlite3_enable_load_extension.argtypes = [c_void_p, c_int]
+sqlite.sqlite3_enable_load_extension.restype = c_int
+
 ##########################################
 # END Wrapped SQLite C API and constants
 ##########################################
@@ -705,6 +708,14 @@
         from sqlite3.dump import _iterdump
         return _iterdump(self)
 
+    def enable_load_extension(self, enabled):
+        self._check_thread()
+        self._check_closed()
+
+        rc = sqlite.sqlite3_enable_load_extension(self.db, int(enabled))
+        if rc != SQLITE_OK:
+            raise OperationalError("Error enabling load extension")
+
 DML, DQL, DDL = range(3)
 
 class Cursor(object):
diff --git a/lib_pypy/pyrepl/unix_console.py b/lib_pypy/pyrepl/unix_console.py
--- a/lib_pypy/pyrepl/unix_console.py
+++ b/lib_pypy/pyrepl/unix_console.py
@@ -412,7 +412,12 @@
                    e.args[4] == 'unexpected end of data':
                 pass
             else:
-                raise
+                # was: "raise".  But it crashes pyrepl, and by extension the
+                # pypy currently running, in which we are e.g. in the middle
+                # of some debugging session.  Argh.  Instead just print an
+                # error message to stderr and continue running, for now.
+                self.partial_char = ''
+                sys.stderr.write('\n%s: %s\n' % (e.__class__.__name__, e))
         else:
             self.partial_char = ''
             self.event_queue.push(c)
diff --git a/lib_pypy/syslog.py b/lib_pypy/syslog.py
--- a/lib_pypy/syslog.py
+++ b/lib_pypy/syslog.py
@@ -38,9 +38,27 @@
 _setlogmask.argtypes = (c_int,)
 _setlogmask.restype = c_int
 
+_S_log_open = False
+_S_ident_o = None
+
+def _get_argv():
+    try:
+        import sys
+        script = sys.argv[0]
+        if isinstance(script, str):
+            return script[script.rfind('/')+1:] or None
+    except Exception:
+        pass
+    return None
+
 @builtinify
-def openlog(ident, option, facility):
-    _openlog(ident, option, facility)
+def openlog(ident=None, logoption=0, facility=LOG_USER):
+    global _S_ident_o, _S_log_open
+    if ident is None:
+        ident = _get_argv()
+    _S_ident_o = c_char_p(ident)    # keepalive
+    _openlog(_S_ident_o, logoption, facility)
+    _S_log_open = True
 
 @builtinify
 def syslog(arg1, arg2=None):
@@ -48,11 +66,18 @@
         priority, message = arg1, arg2
     else:
         priority, message = LOG_INFO, arg1
+    # if log is not opened, open it now
+    if not _S_log_open:
+        openlog()
     _syslog(priority, "%s", message)
 
 @builtinify
 def closelog():
-    _closelog()
+    global _S_log_open, S_ident_o
+    if _S_log_open:
+        _closelog()
+        _S_log_open = False
+        _S_ident_o = None
 
 @builtinify
 def setlogmask(mask):
diff --git a/pypy/doc/coding-guide.rst b/pypy/doc/coding-guide.rst
--- a/pypy/doc/coding-guide.rst
+++ b/pypy/doc/coding-guide.rst
@@ -270,7 +270,12 @@
   - *slicing*:
     the slice start must be within bounds. The stop doesn't need to, but it must
     not be smaller than the start.  All negative indexes are disallowed, except for
-    the [:-1] special case.  No step.
+    the [:-1] special case.  No step.  Slice deletion follows the same rules.
+    
+  - *slice assignment*:
+    only supports ``lst[x:y] = sublist``, if ``len(sublist) == y - x``.
+    In other words, slice assignment cannot change the total length of the list,
+    but just replace items.
 
   - *other operators*:
     ``+``, ``+=``, ``in``, ``*``, ``*=``, ``==``, ``!=`` work as expected.
diff --git a/pypy/doc/how-to-release.rst b/pypy/doc/how-to-release.rst
--- a/pypy/doc/how-to-release.rst
+++ b/pypy/doc/how-to-release.rst
@@ -1,6 +1,3 @@
-.. include:: needswork.txt
-
-.. needs work, it talks about svn. also, it is not really user documentation
 
 Making a PyPy Release
 =======================
@@ -12,11 +9,8 @@
 forgetting things. A set of todo files may also work.
 
 Check and prioritize all issues for the release, postpone some if necessary,
-create new  issues also as necessary. A meeting (or meetings) should be
-organized to decide what things are priorities, should go in and work for
-the release. 
-
-An important thing is to get the documentation into an up-to-date state!
+create new  issues also as necessary. An important thing is to get
+the documentation into an up-to-date state!
 
 Release Steps
 ----------------
diff --git a/pypy/doc/project-ideas.rst b/pypy/doc/project-ideas.rst
--- a/pypy/doc/project-ideas.rst
+++ b/pypy/doc/project-ideas.rst
@@ -23,17 +23,20 @@
 PyPy's implementation of the Python ``long`` type is slower than CPython's.
 Find out why and optimize them.
 
+Make bytearray type fast
+------------------------
+
+PyPy's bytearray type is very inefficient. It would be an interesting
+task to look into possible optimizations on this.
+
 Numpy improvements
 ------------------
 
-This is more of a project-container than a single project. Possible ideas:
+The numpy is rapidly progressing in pypy, so feel free to come to IRC and
+ask for proposed topic. A not necesarilly up-to-date `list of topics`_
+is also available.
 
-* 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.
+.. _`list of topics`: https://bitbucket.org/pypy/extradoc/src/extradoc/planning/micronumpy.txt
 
 Improving the jitviewer
 ------------------------
diff --git a/pypy/doc/release-1.7.0.rst b/pypy/doc/release-1.7.0.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/release-1.7.0.rst
@@ -0,0 +1,94 @@
+==================================
+PyPy 1.7 - widening the sweet spot
+==================================
+
+We're pleased to announce the 1.7 release of PyPy. As became a habit, this
+release brings a lot of bugfixes and performance improvements over the 1.6
+release. However, unlike the previous releases, the focus has been on widening
+the "sweet spot" of PyPy. That is, classes of Python code that PyPy can greatly
+speed up should be vastly improved with this release. You can download the 1.7
+release here:
+
+    http://pypy.org/download.html
+
+What is PyPy?
+=============
+
+PyPy is a very compliant Python interpreter, almost a drop-in replacement for
+CPython 2.7. It's fast (`pypy 1.7 and cpython 2.7.1`_ performance comparison)
+due to its integrated tracing JIT compiler.
+
+This release supports x86 machines running Linux 32/64, Mac OS X 32/64 or
+Windows 32. Windows 64 work is ongoing, but not yet natively supported.
+
+The main topic of this release is widening the range of code which PyPy
+can greatly speed up. On average on
+our benchmark suite, PyPy 1.7 is around **30%** faster than PyPy 1.6 and up
+to **20 times** faster on some benchmarks.
+
+.. _`pypy 1.7 and cpython 2.7.1`: http://speed.pypy.org
+
+
+Highlights
+==========
+
+* Numerous performance improvements. There are too many examples which python
+  constructs now should behave faster to list them.
+
+* Bugfixes and compatibility fixes with CPython.
+
+* Windows fixes.
+
+* PyPy now comes with stackless features enabled by default. However,
+  any loop using stackless features will interrupt the JIT for now, so no real
+  performance improvement for stackless-based programs. Contact pypy-dev for
+  info how to help on removing this restriction.
+
+* NumPy effort in PyPy was renamed numpypy. In order to try using it, simply
+  write::
+
+    import numpypy as numpy
+
+  at the beginning of your program. There is a huge progress on numpy in PyPy
+  since 1.6, the main feature being implementation of dtypes.
+
+* JSON encoder (but not decoder) has been replaced with a new one. This one
+  is written in pure Python, but is known to outperform CPython's C extension
+  up to **2 times** in some cases. It's about **20 times** faster than
+  the one that we had in 1.6.
+
+* The memory footprint of some of our RPython modules has been drastically
+  improved. This should impact any applications using for example cryptography,
+  like tornado.
+
+* There was some progress in exposing even more CPython C API via cpyext.
+
+Things that didn't make it, expect in 1.8 soon
+==============================================
+
+There is an ongoing work, which while didn't make it to the release, is
+probably worth mentioning here. This is what you should probably expect in
+1.8 some time soon:
+
+* Specialized list implementation. There is a branch that implements lists of
+  integers/floats/strings as compactly as array.array. This should drastically
+  improve performance/memory impact of some applications
+
+* NumPy effort is progressing forward, with multi-dimensional arrays coming
+  soon.
+
+* There are two brand new JIT assembler backends, notably for the PowerPC and
+  ARM processors.
+
+Fundraising
+===========
+
+It's maybe worth mentioning that we're running fundraising campaigns for
+NumPy effort in PyPy and for Python 3 in PyPy. In case you want to see any
+of those happen faster, we urge you to donate to `numpy proposal`_ or
+`py3k proposal`_. In case you want PyPy to progress, but you trust us with
+the general direction, you can always donate to the `general pot`_.
+
+.. _`numpy proposal`: http://pypy.org/numpydonate.html
+.. _`py3k proposal`: http://pypy.org/py3donate.html
+.. _`general pot`: http://pypy.org
diff --git a/pypy/interpreter/test/test_executioncontext.py b/pypy/interpreter/test/test_executioncontext.py
--- a/pypy/interpreter/test/test_executioncontext.py
+++ b/pypy/interpreter/test/test_executioncontext.py
@@ -292,7 +292,7 @@
         import os, sys
         print sys.executable, self.tmpfile
         if sys.platform == "win32":
-            cmdformat = '""%s" "%s""'    # excellent! tons of "!
+            cmdformat = '"%s" "%s"'
         else:
             cmdformat = "'%s' '%s'"
         g = os.popen(cmdformat % (sys.executable, self.tmpfile), 'r')
diff --git a/pypy/jit/backend/conftest.py b/pypy/jit/backend/conftest.py
--- a/pypy/jit/backend/conftest.py
+++ b/pypy/jit/backend/conftest.py
@@ -12,7 +12,7 @@
                     help="choose a fixed random seed")
     group.addoption('--backend', action="store",
                     default='llgraph',
-                    choices=['llgraph', 'x86'],
+                    choices=['llgraph', 'cpu'],
                     dest="backend",
                     help="select the backend to run the functions with")
     group.addoption('--block-length', action="store", type="int",
diff --git a/pypy/jit/backend/llgraph/llimpl.py b/pypy/jit/backend/llgraph/llimpl.py
--- a/pypy/jit/backend/llgraph/llimpl.py
+++ b/pypy/jit/backend/llgraph/llimpl.py
@@ -20,6 +20,7 @@
 from pypy.jit.backend.llgraph import symbolic
 from pypy.jit.codewriter import longlong
 
+from pypy.rlib import libffi
 from pypy.rlib.objectmodel import ComputedIntSymbolic, we_are_translated
 from pypy.rlib.rarithmetic import ovfcheck
 from pypy.rlib.rarithmetic import r_longlong, r_ulonglong, r_uint
@@ -325,12 +326,12 @@
     loop = _from_opaque(loop)
     loop.operations.append(Operation(opnum))
 
-def compile_add_descr(loop, ofs, type, arg_types):
+def compile_add_descr(loop, ofs, type, arg_types, extrainfo, width):
     from pypy.jit.backend.llgraph.runner import Descr
     loop = _from_opaque(loop)
     op = loop.operations[-1]
     assert isinstance(type, str) and len(type) == 1
-    op.descr = Descr(ofs, type, arg_types=arg_types)
+    op.descr = Descr(ofs, type, arg_types=arg_types, extrainfo=extrainfo, width=width)
 
 def compile_add_descr_arg(loop, ofs, type, arg_types):
     from pypy.jit.backend.llgraph.runner import Descr
@@ -825,6 +826,16 @@
         else:
             raise NotImplementedError
 
+    def op_getinteriorfield_raw(self, descr, array, index):
+        if descr.typeinfo == REF:
+            return do_getinteriorfield_raw_ptr(array, index, descr.width, descr.ofs)
+        elif descr.typeinfo == INT:
+            return do_getinteriorfield_raw_int(array, index, descr.width, descr.ofs)
+        elif descr.typeinfo == FLOAT:
+            return do_getinteriorfield_raw_float(array, index, descr.width, descr.ofs)
+        else:
+            raise NotImplementedError
+
     def op_setinteriorfield_gc(self, descr, array, index, newvalue):
         if descr.typeinfo == REF:
             return do_setinteriorfield_gc_ptr(array, index, descr.ofs,
@@ -838,6 +849,16 @@
         else:
             raise NotImplementedError
 
+    def op_setinteriorfield_raw(self, descr, array, index, newvalue):
+        if descr.typeinfo == REF:
+            return do_setinteriorfield_raw_ptr(array, index, newvalue, descr.width, descr.ofs)
+        elif descr.typeinfo == INT:
+            return do_setinteriorfield_raw_int(array, index, newvalue, descr.width, descr.ofs)
+        elif descr.typeinfo == FLOAT:
+            return do_setinteriorfield_raw_float(array, index, newvalue, descr.width, descr.ofs)
+        else:
+            raise NotImplementedError
+
     def op_setfield_gc(self, fielddescr, struct, newvalue):
         if fielddescr.typeinfo == REF:
             do_setfield_gc_ptr(struct, fielddescr.ofs, newvalue)
@@ -1403,6 +1424,14 @@
     struct = array._obj.container.getitem(index)
     return cast_to_ptr(_getinteriorfield_gc(struct, fieldnum))
 
+def _getinteriorfield_raw(ffitype, array, index, width, ofs):
+    addr = rffi.cast(rffi.VOIDP, array)
+    return libffi.array_getitem(ffitype, width, addr, index, ofs)
+
+def do_getinteriorfield_raw_int(array, index, width, ofs):
+    res = _getinteriorfield_raw(libffi.types.slong, array, index, width, ofs)
+    return res
+
 def _getfield_raw(struct, fieldnum):
     STRUCT, fieldname = symbolic.TokenToField[fieldnum]
     ptr = cast_from_int(lltype.Ptr(STRUCT), struct)
@@ -1479,7 +1508,14 @@
     return do_setinteriorfield_gc
 do_setinteriorfield_gc_int = new_setinteriorfield_gc(cast_from_int)
 do_setinteriorfield_gc_float = new_setinteriorfield_gc(cast_from_floatstorage)
-do_setinteriorfield_gc_ptr = new_setinteriorfield_gc(cast_from_ptr)        
+do_setinteriorfield_gc_ptr = new_setinteriorfield_gc(cast_from_ptr)
+
+def new_setinteriorfield_raw(ffitype):
+    def do_setinteriorfield_raw(array, index, newvalue, width, ofs):
+        addr = rffi.cast(rffi.VOIDP, array)
+        return libffi.array_setitem(ffitype, width, addr, index, ofs, newvalue)
+    return do_setinteriorfield_raw
+do_setinteriorfield_raw_int = new_setinteriorfield_raw(libffi.types.slong)
 
 def do_setfield_raw_int(struct, fieldnum, newvalue):
     STRUCT, fieldname = symbolic.TokenToField[fieldnum]
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
@@ -23,8 +23,10 @@
 class Descr(history.AbstractDescr):
 
     def __init__(self, ofs, typeinfo, extrainfo=None, name=None,
-                 arg_types=None, count_fields_if_immut=-1, ffi_flags=0):
+                 arg_types=None, count_fields_if_immut=-1, ffi_flags=0, width=-1):
+
         self.ofs = ofs
+        self.width = width
         self.typeinfo = typeinfo
         self.extrainfo = extrainfo
         self.name = name
@@ -119,14 +121,14 @@
         return False
 
     def getdescr(self, ofs, typeinfo='?', extrainfo=None, name=None,
-                 arg_types=None, count_fields_if_immut=-1, ffi_flags=0):
+                 arg_types=None, count_fields_if_immut=-1, ffi_flags=0, width=-1):
         key = (ofs, typeinfo, extrainfo, name, arg_types,
-               count_fields_if_immut, ffi_flags)
+               count_fields_if_immut, ffi_flags, width)
         try:
             return self._descrs[key]
         except KeyError:
             descr = Descr(ofs, typeinfo, extrainfo, name, arg_types,
-                          count_fields_if_immut, ffi_flags)
+                          count_fields_if_immut, ffi_flags, width)
             self._descrs[key] = descr
             return descr
 
@@ -179,7 +181,8 @@
             descr = op.getdescr()
             if isinstance(descr, Descr):
                 llimpl.compile_add_descr(c, descr.ofs, descr.typeinfo,
-                                         descr.arg_types)
+                                         descr.arg_types, descr.extrainfo,
+                                         descr.width)
             if (isinstance(descr, history.LoopToken) and
                 op.getopnum() != rop.JUMP):
                 llimpl.compile_add_loop_token(c, descr)
@@ -324,10 +327,22 @@
 
     def interiorfielddescrof(self, A, fieldname):
         S = A.OF
-        ofs2 = symbolic.get_size(A)
+        width = symbolic.get_size(A)
         ofs, size = symbolic.get_field_token(S, fieldname)
         token = history.getkind(getattr(S, fieldname))
-        return self.getdescr(ofs, token[0], name=fieldname, extrainfo=ofs2)
+        return self.getdescr(ofs, token[0], name=fieldname, width=width)
+
+    def interiorfielddescrof_dynamic(self, offset, width, fieldsize,
+        is_pointer, is_float, is_signed):
+
+        if is_pointer:
+            typeinfo = REF
+        elif is_float:
+            typeinfo = FLOAT
+        else:
+            typeinfo = INT
+        # we abuse the arg_types field to distinguish dynamic and static descrs
+        return Descr(offset, typeinfo, arg_types='dynamic', name='<dynamic interior field>', width=width)
 
     def calldescrof(self, FUNC, ARGS, RESULT, extrainfo):
         arg_types = []
diff --git a/pypy/jit/backend/llsupport/descr.py b/pypy/jit/backend/llsupport/descr.py
--- a/pypy/jit/backend/llsupport/descr.py
+++ b/pypy/jit/backend/llsupport/descr.py
@@ -111,6 +111,16 @@
     def repr_of_descr(self):
         return '<%s %s %s>' % (self._clsname, self.name, self.offset)
 
+class DynamicFieldDescr(BaseFieldDescr):
+    def __init__(self, offset, fieldsize, is_pointer, is_float, is_signed):
+        self.offset = offset
+        self._fieldsize = fieldsize
+        self._is_pointer_field = is_pointer
+        self._is_float_field = is_float
+        self._is_field_signed = is_signed
+
+    def get_field_size(self, translate_support_code):
+        return self._fieldsize
 
 class NonGcPtrFieldDescr(BaseFieldDescr):
     _clsname = 'NonGcPtrFieldDescr'
@@ -182,6 +192,7 @@
     def repr_of_descr(self):
         return '<%s>' % self._clsname
 
+
 class NonGcPtrArrayDescr(BaseArrayDescr):
     _clsname = 'NonGcPtrArrayDescr'
     def get_item_size(self, translate_support_code):
@@ -211,6 +222,13 @@
     def get_ofs_length(self, translate_support_code):
         return -1
 
+class DynamicArrayNoLengthDescr(BaseArrayNoLengthDescr):
+    def __init__(self, itemsize):
+        self.itemsize = itemsize
+
+    def get_item_size(self, translate_support_code):
+        return self.itemsize
+
 class NonGcPtrArrayNoLengthDescr(BaseArrayNoLengthDescr):
     _clsname = 'NonGcPtrArrayNoLengthDescr'
     def get_item_size(self, translate_support_code):
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
@@ -9,9 +9,10 @@
 from pypy.jit.backend.llsupport import symbolic
 from pypy.jit.backend.llsupport.symbolic import WORD, unroll_basic_sizes
 from pypy.jit.backend.llsupport.descr import (get_size_descr,
-     get_field_descr, BaseFieldDescr, get_array_descr, BaseArrayDescr,
-     get_call_descr, BaseIntCallDescr, GcPtrCallDescr, FloatCallDescr,
-     VoidCallDescr, InteriorFieldDescr, get_interiorfield_descr)
+     get_field_descr, BaseFieldDescr, DynamicFieldDescr, get_array_descr,
+     BaseArrayDescr, DynamicArrayNoLengthDescr, get_call_descr,
+     BaseIntCallDescr, GcPtrCallDescr, FloatCallDescr, VoidCallDescr,
+     InteriorFieldDescr, get_interiorfield_descr)
 from pypy.jit.backend.llsupport.asmmemmgr import AsmMemoryManager
 
 
@@ -238,6 +239,12 @@
     def interiorfielddescrof(self, A, fieldname):
         return get_interiorfield_descr(self.gc_ll_descr, A, A.OF, fieldname)
 
+    def interiorfielddescrof_dynamic(self, offset, width, fieldsize,
+        is_pointer, is_float, is_signed):
+        arraydescr = DynamicArrayNoLengthDescr(width)
+        fielddescr = DynamicFieldDescr(offset, fieldsize, is_pointer, is_float, is_signed)
+        return InteriorFieldDescr(arraydescr, fielddescr)
+
     def unpack_arraydescr(self, arraydescr):
         assert isinstance(arraydescr, BaseArrayDescr)
         return arraydescr.get_base_size(self.translate_support_code)
diff --git a/pypy/jit/backend/model.py b/pypy/jit/backend/model.py
--- a/pypy/jit/backend/model.py
+++ b/pypy/jit/backend/model.py
@@ -183,38 +183,35 @@
             lst[n] = None
         self.fail_descr_free_list.extend(faildescr_indices)
 
-    @staticmethod
-    def sizeof(S):
+    def sizeof(self, S):
         raise NotImplementedError
 
-    @staticmethod
-    def fielddescrof(S, fieldname):
+    def fielddescrof(self, S, fieldname):
         """Return the Descr corresponding to field 'fieldname' on the
         structure 'S'.  It is important that this function (at least)
         caches the results."""
         raise NotImplementedError
 
-    @staticmethod
-    def arraydescrof(A):
+    def interiorfielddescrof(self, A, fieldname):
         raise NotImplementedError
 
-    @staticmethod
-    def calldescrof(FUNC, ARGS, RESULT):
+    def interiorfielddescrof_dynamic(self, offset, width, fieldsize, is_pointer,
+        is_float, is_signed):
+        raise NotImplementedError
+
+    def arraydescrof(self, A):
+        raise NotImplementedError
+
+    def calldescrof(self, FUNC, ARGS, RESULT):
         # FUNC is the original function type, but ARGS is a list of types
         # with Voids removed
         raise NotImplementedError
 
-    @staticmethod
-    def methdescrof(SELFTYPE, methname):
+    def methdescrof(self, SELFTYPE, methname):
         # must return a subclass of history.AbstractMethDescr
         raise NotImplementedError
 
-    @staticmethod
-    def typedescrof(TYPE):
-        raise NotImplementedError
-
-    @staticmethod
-    def interiorfielddescrof(A, fieldname):
+    def typedescrof(self, TYPE):
         raise NotImplementedError
 
     # ---------- the backend-dependent operations ----------
diff --git a/pypy/jit/backend/test/test_random.py b/pypy/jit/backend/test/test_random.py
--- a/pypy/jit/backend/test/test_random.py
+++ b/pypy/jit/backend/test/test_random.py
@@ -495,9 +495,9 @@
     if pytest.config.option.backend == 'llgraph':
         from pypy.jit.backend.llgraph.runner import LLtypeCPU
         return LLtypeCPU(None)
-    elif pytest.config.option.backend == 'x86':
-        from pypy.jit.backend.x86.runner import CPU386
-        return CPU386(None, None)
+    elif pytest.config.option.backend == 'cpu':
+        from pypy.jit.backend.detect_cpu import getcpuclass
+        return getcpuclass()(None, None)
     else:
         assert 0, "unknown backend %r" % pytest.config.option.backend
 
diff --git a/pypy/jit/backend/x86/test/test_zll_random.py b/pypy/jit/backend/test/test_zll_stress.py
rename from pypy/jit/backend/x86/test/test_zll_random.py
rename to pypy/jit/backend/test/test_zll_stress.py
diff --git a/pypy/jit/backend/x86/assembler.py b/pypy/jit/backend/x86/assembler.py
--- a/pypy/jit/backend/x86/assembler.py
+++ b/pypy/jit/backend/x86/assembler.py
@@ -8,8 +8,8 @@
 from pypy.rpython.lltypesystem.lloperation import llop
 from pypy.rpython.annlowlevel import llhelper
 from pypy.jit.backend.model import CompiledLoopToken
-from pypy.jit.backend.x86.regalloc import (RegAlloc, get_ebp_ofs,
-                                           _get_scale, gpr_reg_mgr_cls)
+from pypy.jit.backend.x86.regalloc import (RegAlloc, get_ebp_ofs, _get_scale,
+    gpr_reg_mgr_cls, _valid_addressing_size)
 
 from pypy.jit.backend.x86.arch import (FRAME_FIXED_SIZE, FORCE_INDEX_OFS, WORD,
                                        IS_X86_32, IS_X86_64)
@@ -1601,8 +1601,10 @@
         assert isinstance(itemsize_loc, ImmedLoc)
         if isinstance(index_loc, ImmedLoc):
             temp_loc = imm(index_loc.value * itemsize_loc.value)
+        elif _valid_addressing_size(itemsize_loc.value):
+            return AddressLoc(base_loc, index_loc, _get_scale(itemsize_loc.value), ofs_loc.value)
         else:
-            # XXX should not use IMUL in most cases
+            # XXX should not use IMUL in more cases, it can use a clever LEA
             assert isinstance(temp_loc, RegLoc)
             assert isinstance(index_loc, RegLoc)
             assert not temp_loc.is_xmm
@@ -1619,6 +1621,8 @@
                                                 ofs_loc)
         self.load_from_mem(resloc, src_addr, fieldsize_loc, sign_loc)
 
+    genop_getinteriorfield_raw = genop_getinteriorfield_gc
+
 
     def genop_discard_setfield_gc(self, op, arglocs):
         base_loc, ofs_loc, size_loc, value_loc = arglocs
@@ -1634,6 +1638,8 @@
                                                  ofs_loc)
         self.save_into_mem(dest_addr, value_loc, fieldsize_loc)
 
+    genop_discard_setinteriorfield_raw = genop_discard_setinteriorfield_gc
+
     def genop_discard_setarrayitem_gc(self, op, arglocs):
         base_loc, ofs_loc, value_loc, size_loc, baseofs = arglocs
         assert isinstance(baseofs, ImmedLoc)
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
@@ -1067,6 +1067,8 @@
         self.PerformDiscard(op, [base_loc, ofs, itemsize, fieldsize,
                                  index_loc, temp_loc, value_loc])
 
+    consider_setinteriorfield_raw = consider_setinteriorfield_gc
+
     def consider_strsetitem(self, op):
         args = op.getarglist()
         base_loc = self.rm.make_sure_var_in_reg(op.getarg(0), args)
@@ -1158,6 +1160,8 @@
         self.Perform(op, [base_loc, ofs, itemsize, fieldsize,
                           index_loc, temp_loc, sign_loc], result_loc)
 
+    consider_getinteriorfield_raw = consider_getinteriorfield_gc
+
     def consider_int_is_true(self, op, guard_op):
         # doesn't need arg to be in a register
         argloc = self.loc(op.getarg(0))
@@ -1430,8 +1434,11 @@
     # i.e. the n'th word beyond the fixed frame size.
     return -WORD * (FRAME_FIXED_SIZE + position)
 
+def _valid_addressing_size(size):
+    return size == 1 or size == 2 or size == 4 or size == 8
+
 def _get_scale(size):
-    assert size == 1 or size == 2 or size == 4 or size == 8
+    assert _valid_addressing_size(size)
     if size < 4:
         return size - 1         # 1, 2 => 0, 1
     else:
diff --git a/pypy/jit/backend/x86/test/test_fficall.py b/pypy/jit/backend/x86/test/test_fficall.py
new file mode 100644
--- /dev/null
+++ b/pypy/jit/backend/x86/test/test_fficall.py
@@ -0,0 +1,8 @@
+import py
+from pypy.jit.metainterp.test import test_fficall
+from pypy.jit.backend.x86.test.test_basic import Jit386Mixin
+
+class TestFfiLookups(Jit386Mixin, test_fficall.FfiLookupTests):
+    # for the individual tests see
+    # ====> ../../../metainterp/test/test_fficall.py
+    supports_all = True
diff --git a/pypy/jit/backend/x86/test/test_ztranslation.py b/pypy/jit/backend/x86/test/test_ztranslation.py
--- a/pypy/jit/backend/x86/test/test_ztranslation.py
+++ b/pypy/jit/backend/x86/test/test_ztranslation.py
@@ -1,6 +1,6 @@
 import py, os, sys
 from pypy.tool.udir import udir
-from pypy.rlib.jit import JitDriver, unroll_parameters
+from pypy.rlib.jit import JitDriver, unroll_parameters, set_param
 from pypy.rlib.jit import PARAMETERS, dont_look_inside
 from pypy.rlib.jit import promote
 from pypy.jit.metainterp.jitprof import Profiler
@@ -47,9 +47,9 @@
         def f(i, j):
             for param, _ in unroll_parameters:
                 defl = PARAMETERS[param]
-                jitdriver.set_param(param, defl)
-            jitdriver.set_param("threshold", 3)
-            jitdriver.set_param("trace_eagerness", 2)
+                set_param(jitdriver, param, defl)
+            set_param(jitdriver, "threshold", 3)
+            set_param(jitdriver, "trace_eagerness", 2)
             total = 0
             frame = Frame(i)
             while frame.i > 3:
@@ -213,8 +213,8 @@
             else:
                 return Base()
         def myportal(i):
-            jitdriver.set_param("threshold", 3)
-            jitdriver.set_param("trace_eagerness", 2)
+            set_param(jitdriver, "threshold", 3)
+            set_param(jitdriver, "trace_eagerness", 2)
             total = 0
             n = i
             while True:
diff --git a/pypy/jit/codewriter/codewriter.py b/pypy/jit/codewriter/codewriter.py
--- a/pypy/jit/codewriter/codewriter.py
+++ b/pypy/jit/codewriter/codewriter.py
@@ -104,6 +104,8 @@
         else:
             name = 'unnamed' % id(ssarepr)
         i = 1
+        # escape <lambda> names for windows
+        name = name.replace('<lambda>', '_(lambda)_')
         extra = ''
         while name+extra in self._seen_files:
             i += 1
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
@@ -48,6 +48,8 @@
     OS_LIBFFI_PREPARE           = 60
     OS_LIBFFI_PUSH_ARG          = 61
     OS_LIBFFI_CALL              = 62
+    OS_LIBFFI_GETARRAYITEM      = 63
+    OS_LIBFFI_SETARRAYITEM      = 64
     #
     OS_LLONG_INVERT             = 69
     OS_LLONG_ADD                = 70
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
@@ -1615,6 +1615,12 @@
         elif oopspec_name.startswith('libffi_call_'):
             oopspecindex = EffectInfo.OS_LIBFFI_CALL
             extraeffect = EffectInfo.EF_RANDOM_EFFECTS
+        elif oopspec_name == 'libffi_array_getitem':
+            oopspecindex = EffectInfo.OS_LIBFFI_GETARRAYITEM
+            extraeffect = EffectInfo.EF_CANNOT_RAISE
+        elif oopspec_name == 'libffi_array_setitem':
+            oopspecindex = EffectInfo.OS_LIBFFI_SETARRAYITEM
+            extraeffect = EffectInfo.EF_CANNOT_RAISE
         else:
             assert False, 'unsupported oopspec: %s' % oopspec_name
         return self._handle_oopspec_call(op, args, oopspecindex, extraeffect)
diff --git a/pypy/jit/metainterp/executor.py b/pypy/jit/metainterp/executor.py
--- a/pypy/jit/metainterp/executor.py
+++ b/pypy/jit/metainterp/executor.py
@@ -340,6 +340,8 @@
                          rop.DEBUG_MERGE_POINT,
                          rop.JIT_DEBUG,
                          rop.SETARRAYITEM_RAW,
+                         rop.GETINTERIORFIELD_RAW,
+                         rop.SETINTERIORFIELD_RAW,
                          rop.CALL_RELEASE_GIL,
                          rop.QUASIIMMUT_FIELD,
                          ):      # list of opcodes never executed by pyjitpl
diff --git a/pypy/jit/metainterp/optimizeopt/fficall.py b/pypy/jit/metainterp/optimizeopt/fficall.py
--- a/pypy/jit/metainterp/optimizeopt/fficall.py
+++ b/pypy/jit/metainterp/optimizeopt/fficall.py
@@ -1,11 +1,13 @@
+from pypy.jit.codewriter.effectinfo import EffectInfo
+from pypy.jit.metainterp.optimizeopt.optimizer import Optimization
+from pypy.jit.metainterp.optimizeopt.util import make_dispatcher_method
+from pypy.jit.metainterp.resoperation import rop, ResOperation
+from pypy.rlib import clibffi, libffi
+from pypy.rlib.debug import debug_print
+from pypy.rlib.libffi import Func
+from pypy.rlib.objectmodel import we_are_translated
 from pypy.rpython.annlowlevel import cast_base_ptr_to_instance
-from pypy.rlib.objectmodel import we_are_translated
-from pypy.rlib.libffi import Func
-from pypy.rlib.debug import debug_print
-from pypy.jit.codewriter.effectinfo import EffectInfo
-from pypy.jit.metainterp.resoperation import rop, ResOperation
-from pypy.jit.metainterp.optimizeopt.util import make_dispatcher_method
-from pypy.jit.metainterp.optimizeopt.optimizer import Optimization
+from pypy.rpython.lltypesystem import llmemory
 
 
 class FuncInfo(object):
@@ -78,7 +80,7 @@
 
     def new(self):
         return OptFfiCall()
-    
+
     def begin_optimization(self, funcval, op):
         self.rollback_maybe('begin_optimization', op)
         self.funcinfo = FuncInfo(funcval, self.optimizer.cpu, op)
@@ -116,6 +118,9 @@
             ops = self.do_push_arg(op)
         elif oopspec == EffectInfo.OS_LIBFFI_CALL:
             ops = self.do_call(op)
+        elif (oopspec == EffectInfo.OS_LIBFFI_GETARRAYITEM or
+            oopspec == EffectInfo.OS_LIBFFI_SETARRAYITEM):
+            ops = self.do_getsetarrayitem(op, oopspec)
         #
         for op in ops:
             self.emit_operation(op)
@@ -190,6 +195,53 @@
         ops.append(newop)
         return ops
 
+    def do_getsetarrayitem(self, op, oopspec):
+        ffitypeval = self.getvalue(op.getarg(1))
+        widthval = self.getvalue(op.getarg(2))
+        offsetval = self.getvalue(op.getarg(5))
+        if not ffitypeval.is_constant() or not widthval.is_constant() or not offsetval.is_constant():
+            return [op]
+
+        ffitypeaddr = ffitypeval.box.getaddr()
+        ffitype = llmemory.cast_adr_to_ptr(ffitypeaddr, clibffi.FFI_TYPE_P)
+        offset = offsetval.box.getint()
+        width = widthval.box.getint()
+        descr = self._get_interior_descr(ffitype, width, offset)
+
+        arglist = [
+            self.getvalue(op.getarg(3)).force_box(self.optimizer),
+            self.getvalue(op.getarg(4)).force_box(self.optimizer),
+        ]
+        if oopspec == EffectInfo.OS_LIBFFI_GETARRAYITEM:
+            opnum = rop.GETINTERIORFIELD_RAW
+        elif oopspec == EffectInfo.OS_LIBFFI_SETARRAYITEM:
+            opnum = rop.SETINTERIORFIELD_RAW
+            arglist.append(self.getvalue(op.getarg(6)).force_box(self.optimizer))
+        else:
+            assert False
+        return [
+            ResOperation(opnum, arglist, op.result, descr=descr),
+        ]
+
+    def _get_interior_descr(self, ffitype, width, offset):
+        kind = libffi.types.getkind(ffitype)
+        is_pointer = is_float = is_signed = False
+        if ffitype is libffi.types.pointer:
+            is_pointer = True
+        elif kind == 'i':
+            is_signed = True
+        elif kind == 'f' or kind == 'I' or kind == 'U':
+            # longlongs are treated as floats, see
+            # e.g. llsupport/descr.py:getDescrClass
+            is_float = True
+        else:
+            assert False, "unsupported ffitype or kind"
+        #
+        fieldsize = ffitype.c_size
+        return self.optimizer.cpu.interiorfielddescrof_dynamic(
+            offset, width, fieldsize, is_pointer, is_float, is_signed
+        )
+
     def propagate_forward(self, op):
         if self.logops is not None:
             debug_print(self.logops.repr_of_resop(op))
diff --git a/pypy/jit/metainterp/optimizeopt/optimizer.py b/pypy/jit/metainterp/optimizeopt/optimizer.py
--- a/pypy/jit/metainterp/optimizeopt/optimizer.py
+++ b/pypy/jit/metainterp/optimizeopt/optimizer.py
@@ -348,6 +348,7 @@
         self.opaque_pointers = {}
         self.replaces_guard = {}
         self._newoperations = []
+        self.seen_results = {}
         self.optimizer = self
         self.optpure = None
         self.optearlyforce = None
@@ -542,6 +543,10 @@
                 op = self.store_final_boxes_in_guard(op)
         elif op.can_raise():
             self.exception_might_have_happened = True
+        if op.result:
+            if op.result in self.seen_results:
+                raise ValueError, "invalid optimization"
+            self.seen_results[op.result] = None
         self._newoperations.append(op)
 
     def replace_op(self, old_op, new_op):
diff --git a/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py b/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py
--- a/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py
+++ b/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py
@@ -1191,6 +1191,75 @@
         """
         self.optimize_loop(ops, expected, preamble)
 
+    def test_virtual_recursive(self):
+        ops = """
+        [p0]
+        p41 = getfield_gc(p0, descr=nextdescr)
+        i0 = getfield_gc(p41, descr=valuedescr)
+        p1 = new_with_vtable(ConstClass(node_vtable2))
+        p2 = new_with_vtable(ConstClass(node_vtable2))
+        setfield_gc(p2, p1, descr=nextdescr)
+        setfield_gc(p1, p2, descr=nextdescr)
+        i1 = int_add(i0, 1)
+        setfield_gc(p2, i1, descr=valuedescr)
+        jump(p1)
+        """
+        preamble = """
+        [p0]
+        p41 = getfield_gc(p0, descr=nextdescr)
+        i0 = getfield_gc(p41, descr=valuedescr)
+        i3 = int_add(i0, 1)
+        jump(i3)
+        """
+        expected = """
+        [i0]
+        i1 = int_add(i0, 1)
+        jump(i1)
+        """
+        self.optimize_loop(ops, expected, preamble)
+
+    def test_virtual_recursive_forced(self):
+        ops = """
+        [p0]
+        p41 = getfield_gc(p0, descr=nextdescr)
+        i0 = getfield_gc(p41, descr=valuedescr)
+        p1 = new_with_vtable(ConstClass(node_vtable2))
+        p2 = new_with_vtable(ConstClass(node_vtable2))
+        setfield_gc(p2, p1, descr=nextdescr)
+        setfield_gc(p1, p2, descr=nextdescr)
+        i1 = int_add(i0, 1)
+        setfield_gc(p2, i1, descr=valuedescr)
+        setfield_gc(p0, p1, descr=nextdescr)
+        jump(p1)
+        """
+        preamble = """
+        [p0]
+        p41 = getfield_gc(p0, descr=nextdescr)
+        i0 = getfield_gc(p41, descr=valuedescr)
+        i1 = int_add(i0, 1)
+        p1 = new_with_vtable(ConstClass(node_vtable2))
+        p2 = new_with_vtable(ConstClass(node_vtable2))
+        setfield_gc(p2, i1, descr=valuedescr)
+        setfield_gc(p2, p1, descr=nextdescr)
+        setfield_gc(p1, p2, descr=nextdescr)
+        setfield_gc(p0, p1, descr=nextdescr)
+        jump(p1)
+        """
+        loop = """
+        [p0]
+        p41 = getfield_gc(p0, descr=nextdescr)
+        i0 = getfield_gc(p41, descr=valuedescr)
+        i1 = int_add(i0, 1)
+        p1 = new_with_vtable(ConstClass(node_vtable2))
+        p2 = new_with_vtable(ConstClass(node_vtable2))
+        setfield_gc(p0, p1, descr=nextdescr)
+        setfield_gc(p2, p1, descr=nextdescr)
+        setfield_gc(p1, p2, descr=nextdescr)
+        setfield_gc(p2, i1, descr=valuedescr)
+        jump(p1)
+        """
+        self.optimize_loop(ops, loop, preamble)
+
     def test_virtual_constant_isnull(self):
         ops = """
         [i0]
@@ -5438,6 +5507,96 @@
         jump()
         """
         self.optimize_loop(ops, expected)
+        # ----------
+        ops = """
+        [p1]
+        p0 = new_with_vtable(ConstClass(ptrobj_immut_vtable))
+        setfield_gc(p0, p1, descr=immut_ptrval)
+        escape(p0)
+        jump(p1)
+        """
+        self.optimize_loop(ops, ops)
+        # ----------
+        ops = """
+        []
+        p0 = new_with_vtable(ConstClass(ptrobj_immut_vtable))
+        p1 = new_with_vtable(ConstClass(intobj_immut_vtable))
+        setfield_gc(p1, 1242, descr=immut_intval)
+        setfield_gc(p0, p1, descr=immut_ptrval)
+        escape(p0)
+        jump()
+        """
+        class PtrObj1242(object):
+            _TYPE = llmemory.GCREF.TO
+            def __eq__(slf, other):
+                if slf is other:
+                    return 1
+                p1 = other.container.ptrval
+                p1cast = lltype.cast_pointer(lltype.Ptr(self.INTOBJ_IMMUT), p1)
+                return p1cast.intval == 1242
+        self.namespace['ptrobj1242'] = lltype._ptr(llmemory.GCREF,
+                                                   PtrObj1242())
+        expected = """
+        []
+        escape(ConstPtr(ptrobj1242))
+        jump()
+        """
+        self.optimize_loop(ops, expected)
+
+    def test_immutable_constantfold_recursive(self):
+        ops = """
+        []
+        p0 = new_with_vtable(ConstClass(ptrobj_immut_vtable))
+        setfield_gc(p0, p0, descr=immut_ptrval)
+        escape(p0)
+        jump()
+        """
+        from pypy.rpython.lltypesystem import lltype, llmemory
+        class PtrObjSelf(object):
+            _TYPE = llmemory.GCREF.TO
+            def __eq__(slf, other):
+                if slf is other:
+                    return 1
+                p1 = other.container.ptrval
+                p1cast = lltype.cast_pointer(lltype.Ptr(self.PTROBJ_IMMUT), p1)
+                return p1cast.ptrval == p1
+        self.namespace['ptrobjself'] = lltype._ptr(llmemory.GCREF,
+                                                   PtrObjSelf())
+        expected = """
+        []
+        escape(ConstPtr(ptrobjself))
+        jump()
+        """
+        self.optimize_loop(ops, expected)
+        #
+        ops = """
+        []
+        p0 = new_with_vtable(ConstClass(ptrobj_immut_vtable))
+        p1 = new_with_vtable(ConstClass(ptrobj_immut_vtable))
+        setfield_gc(p0, p1, descr=immut_ptrval)
+        setfield_gc(p1, p0, descr=immut_ptrval)
+        escape(p0)
+        jump()
+        """
+        class PtrObjSelf2(object):
+            _TYPE = llmemory.GCREF.TO
+            def __eq__(slf, other):
+                if slf is other:
+                    return 1
+                p1 = other.container.ptrval
+                p1cast = lltype.cast_pointer(lltype.Ptr(self.PTROBJ_IMMUT), p1)
+                p2 = p1cast.ptrval
+                assert p2 != p1
+                p2cast = lltype.cast_pointer(lltype.Ptr(self.PTROBJ_IMMUT), p2)
+                return p2cast.ptrval == p1
+        self.namespace['ptrobjself2'] = lltype._ptr(llmemory.GCREF,
+                                                    PtrObjSelf2())
+        expected = """
+        []
+        escape(ConstPtr(ptrobjself2))
+        jump()
+        """
+        self.optimize_loop(ops, expected)
 
     # ----------
     def optimize_strunicode_loop(self, ops, optops, preamble):
diff --git a/pypy/jit/metainterp/optimizeopt/test/test_util.py b/pypy/jit/metainterp/optimizeopt/test/test_util.py
--- a/pypy/jit/metainterp/optimizeopt/test/test_util.py
+++ b/pypy/jit/metainterp/optimizeopt/test/test_util.py
@@ -139,6 +139,12 @@
     noimmut_intval = cpu.fielddescrof(INTOBJ_NOIMMUT, 'intval')
     immut_intval = cpu.fielddescrof(INTOBJ_IMMUT, 'intval')
 
+    PTROBJ_IMMUT = lltype.GcStruct('PTROBJ_IMMUT', ('parent', OBJECT),
+                                            ('ptrval', lltype.Ptr(OBJECT)),
+                                            hints={'immutable': True})
+    ptrobj_immut_vtable = lltype.malloc(OBJECT_VTABLE, immortal=True)
+    immut_ptrval = cpu.fielddescrof(PTROBJ_IMMUT, 'ptrval')
+
     arraydescr = cpu.arraydescrof(lltype.GcArray(lltype.Signed))
     floatarraydescr = cpu.arraydescrof(lltype.GcArray(lltype.Float))
 
@@ -246,6 +252,7 @@
     register_known_gctype(cpu, jit_virtual_ref_vtable,vrefinfo.JIT_VIRTUAL_REF)
     register_known_gctype(cpu, intobj_noimmut_vtable, INTOBJ_NOIMMUT)
     register_known_gctype(cpu, intobj_immut_vtable,   INTOBJ_IMMUT)
+    register_known_gctype(cpu, ptrobj_immut_vtable,   PTROBJ_IMMUT)
 
     namespace = locals()
 
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
@@ -87,14 +87,36 @@
     def _get_descr(self):
         raise NotImplementedError
 
-    def _is_immutable_and_filled_with_constants(self, optforce):
+    def _is_immutable_and_filled_with_constants(self, memo=None):
+        # check if it is possible to force the given structure into a
+        # compile-time constant: this is allowed only if it is declared
+        # immutable, if all fields are already filled, and if each field
+        # is either a compile-time constant or (recursively) a structure
+        # which also answers True to the same question.
+        #
+        # check that all fields are filled.  The following equality check
+        # also fails if count == -1, meaning "not an immutable at all".
         count = self._get_descr().count_fields_if_immutable()
-        if count != len(self._fields):    # always the case if count == -1
+        if count != len(self._fields):
             return False
+        #
+        # initialize 'memo'
+        if memo is None:
+            memo = {}
+        elif self in memo:
+            return True   # recursive case: assume yes
+        memo[self] = None
+        #
         for value in self._fields.itervalues():
-            subbox = value.force_box(optforce)
-            if not isinstance(subbox, Const):
-                return False
+            if value.is_constant():
+                pass            # it is a constant value: ok
+            elif (isinstance(value, AbstractVirtualStructValue)
+                  and value.is_virtual()):
+                # recursive check
+                if not value._is_immutable_and_filled_with_constants(memo):
+                    return False
+            else:
+                return False    # not a constant at all
         return True
 
     def force_at_end_of_preamble(self, already_forced, optforce):
@@ -114,7 +136,7 @@
         if not we_are_translated():
             op.name = 'FORCE ' + self.source_op.name
 
-        if self._is_immutable_and_filled_with_constants(optforce):
+        if self._is_immutable_and_filled_with_constants():
             box = optforce.optimizer.constant_fold(op)
             self.make_constant(box)
             for ofs, value in self._fields.iteritems():
diff --git a/pypy/jit/metainterp/resoperation.py b/pypy/jit/metainterp/resoperation.py
--- a/pypy/jit/metainterp/resoperation.py
+++ b/pypy/jit/metainterp/resoperation.py
@@ -461,6 +461,7 @@
     'GETARRAYITEM_GC/2d',
     'GETARRAYITEM_RAW/2d',
     'GETINTERIORFIELD_GC/2d',
+    'GETINTERIORFIELD_RAW/2d',
     'GETFIELD_GC/1d',
     'GETFIELD_RAW/1d',
     '_MALLOC_FIRST',
@@ -479,6 +480,7 @@
     'SETARRAYITEM_GC/3d',
     'SETARRAYITEM_RAW/3d',
     'SETINTERIORFIELD_GC/3d',
+    'SETINTERIORFIELD_RAW/3d',
     'SETFIELD_GC/2d',
     'SETFIELD_RAW/2d',
     'STRSETITEM/3',
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
@@ -14,7 +14,7 @@
 from pypy.rlib.jit import (JitDriver, we_are_jitted, hint, dont_look_inside,
     loop_invariant, elidable, promote, jit_debug, assert_green,
     AssertGreenFailed, unroll_safe, current_trace_length, look_inside_iff,
-    isconstant, isvirtual, promote_string)
+    isconstant, isvirtual, promote_string, set_param)
 from pypy.rlib.rarithmetic import ovfcheck
 from pypy.rpython.lltypesystem import lltype, llmemory, rffi
 from pypy.rpython.ootypesystem import ootype
@@ -1256,15 +1256,18 @@
                 n -= 1
                 x += n
             return x
-        def f(n, threshold):
-            myjitdriver.set_param('threshold', threshold)
+        def f(n, threshold, arg):
+            if arg:
+                set_param(myjitdriver, 'threshold', threshold)
+            else:
+                set_param(None, 'threshold', threshold)
             return g(n)
 
-        res = self.meta_interp(f, [10, 3])
+        res = self.meta_interp(f, [10, 3, 1])
         assert res == 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + 0
         self.check_tree_loop_count(2)
 
-        res = self.meta_interp(f, [10, 13])
+        res = self.meta_interp(f, [10, 13, 0])
         assert res == 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + 0
         self.check_tree_loop_count(0)
 
@@ -2328,8 +2331,8 @@
                                 get_printable_location=get_printable_location)
         bytecode = "0j10jc20a3"
         def f():
-            myjitdriver.set_param('threshold', 7)
-            myjitdriver.set_param('trace_eagerness', 1)
+            set_param(myjitdriver, 'threshold', 7)
+            set_param(myjitdriver, 'trace_eagerness', 1)
             i = j = c = a = 1
             while True:
                 myjitdriver.jit_merge_point(i=i, j=j, c=c, a=a)
@@ -2607,7 +2610,7 @@
         myjitdriver = JitDriver(greens = [], reds = ['n', 'i', 'sa', 'a'])
 
         def f(n, limit):
-            myjitdriver.set_param('retrace_limit', limit)
+            set_param(myjitdriver, 'retrace_limit', limit)
             sa = i = a = 0
             while i < n:
                 myjitdriver.jit_merge_point(n=n, i=i, sa=sa, a=a)
@@ -2625,8 +2628,8 @@
         myjitdriver = JitDriver(greens = [], reds = ['n', 'i', 'sa', 'a'])
 
         def f(n, limit):
-            myjitdriver.set_param('retrace_limit', 3)
-            myjitdriver.set_param('max_retrace_guards', limit)
+            set_param(myjitdriver, 'retrace_limit', 3)
+            set_param(myjitdriver, 'max_retrace_guards', limit)
             sa = i = a = 0
             while i < n:
                 myjitdriver.jit_merge_point(n=n, i=i, sa=sa, a=a)
@@ -2645,7 +2648,7 @@
         myjitdriver = JitDriver(greens = [], reds = ['n', 'i', 'sa', 'a',
                                                      'node'])
         def f(n, limit):
-            myjitdriver.set_param('retrace_limit', limit)
+            set_param(myjitdriver, 'retrace_limit', limit)
             sa = i = a = 0
             node = [1, 2, 3]
             node[1] = n
@@ -2668,10 +2671,10 @@
         myjitdriver = JitDriver(greens = ['pc'], reds = ['n', 'i', 'sa'])
         bytecode = "0+sI0+SI"
         def f(n):
-            myjitdriver.set_param('threshold', 3)
-            myjitdriver.set_param('trace_eagerness', 1)
-            myjitdriver.set_param('retrace_limit', 5)
-            myjitdriver.set_param('function_threshold', -1)
+            set_param(None, 'threshold', 3)
+            set_param(None, 'trace_eagerness', 1)
+            set_param(None, 'retrace_limit', 5)
+            set_param(None, 'function_threshold', -1)
             pc = sa = i = 0
             while pc < len(bytecode):
                 myjitdriver.jit_merge_point(pc=pc, n=n, sa=sa, i=i)
@@ -2728,9 +2731,9 @@
         myjitdriver = JitDriver(greens = ['pc'], reds = ['n', 'a', 'i', 'j', 'sa'])
         bytecode = "ij+Jj+JI"
         def f(n, a):
-            myjitdriver.set_param('threshold', 5)
-            myjitdriver.set_param('trace_eagerness', 1)
-            myjitdriver.set_param('retrace_limit', 2)
+            set_param(None, 'threshold', 5)
+            set_param(None, 'trace_eagerness', 1)
+            set_param(None, 'retrace_limit', 2)
             pc = sa = i = j = 0
             while pc < len(bytecode):
                 myjitdriver.jit_merge_point(pc=pc, n=n, sa=sa, i=i, j=j, a=a)
@@ -2793,8 +2796,8 @@
                 return B(self.val + 1)
         myjitdriver = JitDriver(greens = [], reds = ['sa', 'a'])
         def f():
-            myjitdriver.set_param('threshold', 3)
-            myjitdriver.set_param('trace_eagerness', 2)
+            set_param(None, 'threshold', 3)
+            set_param(None, 'trace_eagerness', 2)
             a = A(0)
             sa = 0
             while a.val < 8:
@@ -2824,8 +2827,8 @@
                 return B(self.val + 1)
         myjitdriver = JitDriver(greens = [], reds = ['sa', 'b', 'a'])
         def f(b):
-            myjitdriver.set_param('threshold', 6)
-            myjitdriver.set_param('trace_eagerness', 4)
+            set_param(None, 'threshold', 6)
+            set_param(None, 'trace_eagerness', 4)
             a = A(0)
             sa = 0
             while a.val < 15:
@@ -2862,10 +2865,10 @@
         myjitdriver = JitDriver(greens = ['pc'], reds = ['n', 'i', 'sa'])
         bytecode = "0+sI0+SI"
         def f(n):
-            myjitdriver.set_param('threshold', 3)
-            myjitdriver.set_param('trace_eagerness', 1)
-            myjitdriver.set_param('retrace_limit', 5)
-            myjitdriver.set_param('function_threshold', -1)
+            set_param(None, 'threshold', 3)
+            set_param(None, 'trace_eagerness', 1)
+            set_param(None, 'retrace_limit', 5)
+            set_param(None, 'function_threshold', -1)
             pc = sa = i = 0
             while pc < len(bytecode):
                 myjitdriver.jit_merge_point(pc=pc, n=n, sa=sa, i=i)
diff --git a/pypy/jit/metainterp/test/test_fficall.py b/pypy/jit/metainterp/test/test_fficall.py
--- a/pypy/jit/metainterp/test/test_fficall.py
+++ b/pypy/jit/metainterp/test/test_fficall.py
@@ -1,19 +1,18 @@
+import py
 
-import py
+from pypy.jit.metainterp.test.support import LLJitMixin
+from pypy.rlib.jit import JitDriver, promote, dont_look_inside
+from pypy.rlib.libffi import (ArgChain, IS_32_BIT, array_getitem, array_setitem,
+    types)
+from pypy.rlib.objectmodel import specialize
 from pypy.rlib.rarithmetic import r_singlefloat, r_longlong, r_ulonglong
-from pypy.rlib.jit import JitDriver, promote, dont_look_inside
+from pypy.rlib.test.test_libffi import TestLibffiCall as _TestLibffiCall
 from pypy.rlib.unroll import unrolling_iterable
-from pypy.rlib.libffi import ArgChain
-from pypy.rlib.libffi import IS_32_BIT
-from pypy.rlib.test.test_libffi import TestLibffiCall as _TestLibffiCall
 from pypy.rpython.lltypesystem import lltype, rffi
-from pypy.rlib.objectmodel import specialize
 from pypy.tool.sourcetools import func_with_new_name
-from pypy.jit.metainterp.test.support import LLJitMixin
 
-class TestFfiCall(LLJitMixin, _TestLibffiCall):
-    supports_all = False     # supports_{floats,longlong,singlefloats}
 
+class FfiCallTests(_TestLibffiCall):
     # ===> ../../../rlib/test/test_libffi.py
 
     def call(self, funcspec, args, RESULT, is_struct=False, jitif=[]):
@@ -92,6 +91,69 @@
     test_byval_result.__doc__ = _TestLibffiCall.test_byval_result.__doc__
     test_byval_result.dont_track_allocations = True
 
+class FfiLookupTests(object):
+    def test_array_fields(self):
+        myjitdriver = JitDriver(
+            greens = [],
+            reds = ["n", "i", "points", "result_point"],
+        )
 
-class TestFfiCallSupportAll(TestFfiCall):
+        POINT = lltype.Struct("POINT",
+            ("x", lltype.Signed),
+            ("y", lltype.Signed),
+        )
+        def f(points, result_point, n):
+            i = 0
+            while i < n:
+                myjitdriver.jit_merge_point(i=i, points=points, n=n,
+                                            result_point=result_point)
+                x = array_getitem(
+                    types.slong, rffi.sizeof(lltype.Signed) * 2, points, i, 0
+                )
+                y = array_getitem(
+                    types.slong, rffi.sizeof(lltype.Signed) * 2, points, i, rffi.sizeof(lltype.Signed)
+                )
+
+                cur_x = array_getitem(
+                    types.slong, rffi.sizeof(lltype.Signed) * 2, result_point, 0, 0
+                )
+                cur_y = array_getitem(
+                    types.slong, rffi.sizeof(lltype.Signed) * 2, result_point, 0, rffi.sizeof(lltype.Signed)
+                )
+
+                array_setitem(
+                    types.slong, rffi.sizeof(lltype.Signed) * 2, result_point, 0, 0, cur_x + x
+                )
+                array_setitem(
+                    types.slong, rffi.sizeof(lltype.Signed) * 2, result_point, 0, rffi.sizeof(lltype.Signed), cur_y + y
+                )
+                i += 1
+
+        def main(n):
+            with lltype.scoped_alloc(rffi.CArray(POINT), n) as points:
+                with lltype.scoped_alloc(rffi.CArray(POINT), 1) as result_point:
+                    for i in xrange(n):
+                        points[i].x = i * 2
+                        points[i].y = i * 2 + 1
+                    points = rffi.cast(rffi.CArrayPtr(lltype.Char), points)
+                    result_point[0].x = 0
+                    result_point[0].y = 0
+                    result_point = rffi.cast(rffi.CArrayPtr(lltype.Char), result_point)
+                    f(points, result_point, n)
+                    result_point = rffi.cast(rffi.CArrayPtr(POINT), result_point)
+                    return result_point[0].x * result_point[0].y
+
+        assert self.meta_interp(main, [10]) == main(10) == 9000
+        self.check_loops({"int_add": 3, "jump": 1, "int_lt": 1, "guard_true": 1,
+                          "getinteriorfield_raw": 4, "setinteriorfield_raw": 2
+        })
+
+
+class TestFfiCall(FfiCallTests, LLJitMixin):
+    supports_all = False
+
+class TestFfiCallSupportAll(FfiCallTests, LLJitMixin):
     supports_all = True     # supports_{floats,longlong,singlefloats}
+
+class TestFfiLookup(FfiLookupTests, LLJitMixin):
+    pass
\ No newline at end of file
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
@@ -1,5 +1,5 @@
 """Tests for multiple JitDrivers."""
-from pypy.rlib.jit import JitDriver, unroll_safe
+from pypy.rlib.jit import JitDriver, unroll_safe, set_param
 from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
 from pypy.jit.metainterp.warmspot import get_stats
 
@@ -113,7 +113,7 @@
             return n
         #
         def loop2(g, r):
-            myjitdriver1.set_param('function_threshold', 0)
+            set_param(None, 'function_threshold', 0)
             while r > 0:
                 myjitdriver2.can_enter_jit(g=g, r=r)
                 myjitdriver2.jit_merge_point(g=g, r=r)
diff --git a/pypy/jit/metainterp/test/test_loop.py b/pypy/jit/metainterp/test/test_loop.py
--- a/pypy/jit/metainterp/test/test_loop.py
+++ b/pypy/jit/metainterp/test/test_loop.py
@@ -1,5 +1,5 @@
 import py
-from pypy.rlib.jit import JitDriver, hint
+from pypy.rlib.jit import JitDriver, hint, set_param
 from pypy.rlib.objectmodel import compute_hash
 from pypy.jit.metainterp.warmspot import ll_meta_interp, get_stats
 from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
@@ -364,7 +364,7 @@
         myjitdriver = JitDriver(greens = ['pos'], reds = ['i', 'j', 'n', 'x'])
         bytecode = "IzJxji"
         def f(n, threshold):
-            myjitdriver.set_param('threshold', threshold)        
+            set_param(myjitdriver, 'threshold', threshold)        
             i = j = x = 0
             pos = 0
             op = '-'
@@ -411,7 +411,7 @@
         myjitdriver = JitDriver(greens = ['pos'], reds = ['i', 'j', 'n', 'x'])
         bytecode = "IzJxji"
         def f(nval, threshold):
-            myjitdriver.set_param('threshold', threshold)        
+            set_param(myjitdriver, 'threshold', threshold)        
             i, j, x = A(0), A(0), A(0)
             n = A(nval)
             pos = 0
diff --git a/pypy/jit/metainterp/test/test_recursive.py b/pypy/jit/metainterp/test/test_recursive.py
--- a/pypy/jit/metainterp/test/test_recursive.py
+++ b/pypy/jit/metainterp/test/test_recursive.py
@@ -1,5 +1,5 @@
 import py
-from pypy.rlib.jit import JitDriver, we_are_jitted, hint
+from pypy.rlib.jit import JitDriver, hint, set_param
 from pypy.rlib.jit import unroll_safe, dont_look_inside, promote
 from pypy.rlib.objectmodel import we_are_translated
 from pypy.rlib.debug import fatalerror
@@ -308,8 +308,8 @@
                 pc += 1
             return n
         def main(n):
-            myjitdriver.set_param('threshold', 3)
-            myjitdriver.set_param('trace_eagerness', 5)            
+            set_param(None, 'threshold', 3)
+            set_param(None, 'trace_eagerness', 5)            
             return f("c-l", n)
         expected = main(100)
         res = self.meta_interp(main, [100], enable_opts='', inline=True)
@@ -329,7 +329,7 @@
                 return recursive(n - 1) + 1
             return 0
         def loop(n):            
-            myjitdriver.set_param("threshold", 10)
+            set_param(myjitdriver, "threshold", 10)
             pc = 0
             while n:
                 myjitdriver.can_enter_jit(n=n)
@@ -351,8 +351,8 @@
             return 0
         myjitdriver = JitDriver(greens=[], reds=['n'])
         def loop(n):
-            myjitdriver.set_param("threshold", 4)
-            myjitdriver.set_param("trace_eagerness", 2)
+            set_param(None, "threshold", 4)
+            set_param(None, "trace_eagerness", 2)
             while n:
                 myjitdriver.can_enter_jit(n=n)
                 myjitdriver.jit_merge_point(n=n)
@@ -482,12 +482,12 @@
         TRACE_LIMIT = 66
  
         def main(inline):
-            myjitdriver.set_param("threshold", 10)
-            myjitdriver.set_param('function_threshold', 60)
+            set_param(None, "threshold", 10)
+            set_param(None, 'function_threshold', 60)
             if inline:
-                myjitdriver.set_param('inlining', True)
+                set_param(None, 'inlining', True)
             else:
-                myjitdriver.set_param('inlining', False)
+                set_param(None, 'inlining', False)
             return loop(100)
 
         res = self.meta_interp(main, [0], enable_opts='', trace_limit=TRACE_LIMIT)
@@ -564,11 +564,11 @@
                 pc += 1
             return n
         def g(m):
-            myjitdriver.set_param('inlining', True)
+            set_param(None, 'inlining', True)
             # carefully chosen threshold to make sure that the inner function
             # cannot be inlined, but the inner function on its own is small
             # enough
-            myjitdriver.set_param('trace_limit', 40)
+            set_param(None, 'trace_limit', 40)
             if m > 1000000:
                 f('', 0)
             result = 0
@@ -1207,9 +1207,9 @@
                     driver.can_enter_jit(c=c, i=i, v=v)
                 break
 
-        def main(c, i, set_param, v):
-            if set_param:
-                driver.set_param('function_threshold', 0)
+        def main(c, i, _set_param, v):
+            if _set_param:
+                set_param(driver, 'function_threshold', 0)
             portal(c, i, v)
 
         self.meta_interp(main, [10, 10, False, False], inline=True)
diff --git a/pypy/jit/metainterp/test/test_warmspot.py b/pypy/jit/metainterp/test/test_warmspot.py
--- a/pypy/jit/metainterp/test/test_warmspot.py
+++ b/pypy/jit/metainterp/test/test_warmspot.py
@@ -1,10 +1,7 @@
 import py
-from pypy.jit.metainterp.warmspot import ll_meta_interp
 from pypy.jit.metainterp.warmspot import get_stats
-from pypy.rlib.jit import JitDriver
-from pypy.rlib.jit import unroll_safe
+from pypy.rlib.jit import JitDriver, set_param, unroll_safe
 from pypy.jit.backend.llgraph import runner
-from pypy.jit.metainterp.history import BoxInt
 
 from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
 from pypy.jit.metainterp.optimizeopt import ALL_OPTS_NAMES
@@ -97,7 +94,7 @@
                 n = A().m(n)
             return n
         def f(n, enable_opts):
-            myjitdriver.set_param('enable_opts', hlstr(enable_opts))
+            set_param(None, 'enable_opts', hlstr(enable_opts))
             return g(n)
 
         # check that the set_param will override the default
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
@@ -1,7 +1,7 @@
 import py
 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 JitDriver, unroll_parameters, set_param
 from pypy.rlib.jit import PARAMETERS, dont_look_inside, hint
 from pypy.jit.metainterp.jitprof import Profiler
 from pypy.rpython.lltypesystem import lltype, llmemory
@@ -57,9 +57,9 @@
                               get_printable_location=get_printable_location)
         def f(i):
             for param, defl in unroll_parameters:
-                jitdriver.set_param(param, defl)
-            jitdriver.set_param("threshold", 3)
-            jitdriver.set_param("trace_eagerness", 2)
+                set_param(jitdriver, param, defl)
+            set_param(jitdriver, "threshold", 3)
+            set_param(jitdriver, "trace_eagerness", 2)
             total = 0
             frame = Frame(i)
             while frame.l[0] > 3:
@@ -117,8 +117,8 @@
                 raise ValueError
             return 2
         def main(i):
-            jitdriver.set_param("threshold", 3)
-            jitdriver.set_param("trace_eagerness", 2)
+            set_param(jitdriver, "threshold", 3)
+            set_param(jitdriver, "trace_eagerness", 2)
             total = 0
             n = i
             while n > 3:
diff --git a/pypy/jit/metainterp/warmspot.py b/pypy/jit/metainterp/warmspot.py
--- a/pypy/jit/metainterp/warmspot.py
+++ b/pypy/jit/metainterp/warmspot.py
@@ -120,7 +120,8 @@
                 op = block.operations[i]
                 if (op.opname == 'jit_marker' and
                     op.args[0].value == marker_name and
-                    op.args[1].value.active):   # the jitdriver
+                    (op.args[1].value is None or
+                    op.args[1].value.active)):   # the jitdriver
                     results.append((graph, block, i))
     return results
 
@@ -846,11 +847,18 @@
         _, PTR_SET_PARAM_STR_FUNCTYPE = self.cpu.ts.get_FuncType(
             [lltype.Ptr(STR)], lltype.Void)
         def make_closure(jd, fullfuncname, is_string):
-            state = jd.warmstate
-            def closure(i):
-                if is_string:
-                    i = hlstr(i)
-                getattr(state, fullfuncname)(i)
+            if jd is None:
+                def closure(i):
+                    if is_string:
+                        i = hlstr(i)
+                    for jd in self.jitdrivers_sd:
+                        getattr(jd.warmstate, fullfuncname)(i)
+            else:
+                state = jd.warmstate
+                def closure(i):
+                    if is_string:
+                        i = hlstr(i)
+                    getattr(state, fullfuncname)(i)
             if is_string:
                 TP = PTR_SET_PARAM_STR_FUNCTYPE
             else:
@@ -859,12 +867,16 @@
             return Constant(funcptr, TP)
         #
         for graph, block, i in find_set_param(graphs):
+            
             op = block.operations[i]
-            for jd in self.jitdrivers_sd:
-                if jd.jitdriver is op.args[1].value:
-                    break
+            if op.args[1].value is not None:
+                for jd in self.jitdrivers_sd:
+                    if jd.jitdriver is op.args[1].value:
+                        break
+                else:
+                    assert 0, "jitdriver of set_param() not found"
             else:
-                assert 0, "jitdriver of set_param() not found"
+                jd = None
             funcname = op.args[2].value
             key = jd, funcname
             if key not in closures:
diff --git a/pypy/module/_rawffi/test/test__rawffi.py b/pypy/module/_rawffi/test/test__rawffi.py
--- a/pypy/module/_rawffi/test/test__rawffi.py
+++ b/pypy/module/_rawffi/test/test__rawffi.py
@@ -1022,6 +1022,12 @@
         assert ret.y == 1234500, "ret.y == %d" % (ret.y,)
         s.free()
 
+    def test_ffi_type(self):
+        import _rawffi
+        EMPTY = _rawffi.Structure([])
+        S2E = _rawffi.Structure([('bah', (EMPTY, 1))])
+        S2E.get_ffi_type()     # does not hang
+
 class AppTestAutoFree:
     def setup_class(cls):
         space = gettestobjspace(usemodules=('_rawffi', 'struct'))
diff --git a/pypy/module/cpyext/include/eval.h b/pypy/module/cpyext/include/eval.h
--- a/pypy/module/cpyext/include/eval.h
+++ b/pypy/module/cpyext/include/eval.h
@@ -14,8 +14,8 @@
 
 PyObject * PyEval_CallFunction(PyObject *obj, const char *format, ...);
 PyObject * PyEval_CallMethod(PyObject *obj, const char *name, const char *format, ...);
-PyObject * PyObject_CallFunction(PyObject *obj, char *format, ...);
-PyObject * PyObject_CallMethod(PyObject *obj, char *name, char *format, ...);
+PyObject * PyObject_CallFunction(PyObject *obj, const char *format, ...);
+PyObject * PyObject_CallMethod(PyObject *obj, const char *name, const char *format, ...);
 PyObject * PyObject_CallFunctionObjArgs(PyObject *callable, ...);
 PyObject * PyObject_CallMethodObjArgs(PyObject *callable, PyObject *name, ...);
 
diff --git a/pypy/module/cpyext/include/modsupport.h b/pypy/module/cpyext/include/modsupport.h
--- a/pypy/module/cpyext/include/modsupport.h
+++ b/pypy/module/cpyext/include/modsupport.h
@@ -48,7 +48,11 @@
 /*
  * This is from pyport.h.  Perhaps it belongs elsewhere.
  */
+#ifdef __cplusplus
+#define PyMODINIT_FUNC extern "C" void
+#else
 #define PyMODINIT_FUNC void
+#endif
 
 
 #ifdef __cplusplus
diff --git a/pypy/module/cpyext/include/pycobject.h b/pypy/module/cpyext/include/pycobject.h
--- a/pypy/module/cpyext/include/pycobject.h
+++ b/pypy/module/cpyext/include/pycobject.h
@@ -33,7 +33,7 @@
 PyAPI_FUNC(void *) PyCObject_GetDesc(PyObject *);
 
 /* Import a pointer to a C object from a module using a PyCObject. */
-PyAPI_FUNC(void *) PyCObject_Import(char *module_name, char *cobject_name);
+PyAPI_FUNC(void *) PyCObject_Import(const char *module_name, const char *cobject_name);
 
 /* Modify a C object. Fails (==0) if object has a destructor. */
 PyAPI_FUNC(int) PyCObject_SetVoidPtr(PyObject *self, void *cobj);
diff --git a/pypy/module/cpyext/include/pyerrors.h b/pypy/module/cpyext/include/pyerrors.h
--- a/pypy/module/cpyext/include/pyerrors.h
+++ b/pypy/module/cpyext/include/pyerrors.h
@@ -11,8 +11,8 @@
     (PyClass_Check((x)) || (PyType_Check((x)) &&                        \
       PyObject_IsSubclass((x), PyExc_BaseException)))
 
-PyObject *PyErr_NewException(char *name, PyObject *base, PyObject *dict);
-PyObject *PyErr_NewExceptionWithDoc(char *name, char *doc, PyObject *base, PyObject *dict);
+PyObject *PyErr_NewException(const char *name, PyObject *base, PyObject *dict);
+PyObject *PyErr_NewExceptionWithDoc(const char *name, const char *doc, PyObject *base, PyObject *dict);
 PyObject *PyErr_Format(PyObject *exception, const char *format, ...);
 
 /* These APIs aren't really part of the error implementation, but
diff --git a/pypy/module/cpyext/modsupport.py b/pypy/module/cpyext/modsupport.py
--- a/pypy/module/cpyext/modsupport.py
+++ b/pypy/module/cpyext/modsupport.py
@@ -54,9 +54,15 @@
     modname = rffi.charp2str(name)
     state = space.fromcache(State)
     f_name, f_path = state.package_context
-    w_mod = PyImport_AddModule(space, f_name)
+    if f_name is not None:
+        modname = f_name
+    w_mod = PyImport_AddModule(space, modname)
+    state.package_context = None, None
 
-    dict_w = {'__file__': space.wrap(f_path)}
+    if f_path is not None:
+        dict_w = {'__file__': space.wrap(f_path)}
+    else:
+        dict_w = {}
     convert_method_defs(space, dict_w, methods, None, w_self, modname)
     for key, w_value in dict_w.items():
         space.setattr(w_mod, space.wrap(key), w_value)
diff --git a/pypy/module/cpyext/presetup.py b/pypy/module/cpyext/presetup.py
--- a/pypy/module/cpyext/presetup.py
+++ b/pypy/module/cpyext/presetup.py
@@ -42,4 +42,4 @@
 patch_distutils()
 
 del sys.argv[0]
-execfile(sys.argv[0], {'__file__': sys.argv[0]})
+execfile(sys.argv[0], {'__file__': sys.argv[0], '__name__': '__main__'})
diff --git a/pypy/module/cpyext/slotdefs.py b/pypy/module/cpyext/slotdefs.py
--- a/pypy/module/cpyext/slotdefs.py
+++ b/pypy/module/cpyext/slotdefs.py
@@ -9,7 +9,8 @@
     unaryfunc, wrapperfunc, ternaryfunc, PyTypeObjectPtr, binaryfunc,
     getattrfunc, getattrofunc, setattrofunc, lenfunc, ssizeargfunc,
     ssizessizeargfunc, ssizeobjargproc, iternextfunc, initproc, richcmpfunc,
-    cmpfunc, hashfunc, descrgetfunc, descrsetfunc, objobjproc, readbufferproc)
+    cmpfunc, hashfunc, descrgetfunc, descrsetfunc, objobjproc, objobjargproc,
+    readbufferproc)
 from pypy.module.cpyext.pyobject import from_ref
 from pypy.module.cpyext.pyerrors import PyErr_Occurred
 from pypy.module.cpyext.state import State
@@ -175,6 +176,15 @@
         space.fromcache(State).check_and_raise_exception(always=True)
     return space.wrap(res)
 
+def wrap_objobjargproc(space, w_self, w_args, func):
+    func_target = rffi.cast(objobjargproc, func)
+    check_num_args(space, w_args, 2)
+    w_key, w_value = space.fixedview(w_args)
+    res = generic_cpy_call(space, func_target, w_self, w_key, w_value)
+    if rffi.cast(lltype.Signed, res) == -1:
+        space.fromcache(State).check_and_raise_exception(always=True)
+    return space.wrap(res)
+
 def wrap_ssizessizeargfunc(space, w_self, w_args, func):
     func_target = rffi.cast(ssizessizeargfunc, func)
     check_num_args(space, w_args, 2)
diff --git a/pypy/module/cpyext/src/cobject.c b/pypy/module/cpyext/src/cobject.c
--- a/pypy/module/cpyext/src/cobject.c
+++ b/pypy/module/cpyext/src/cobject.c
@@ -77,7 +77,7 @@
 }
 
 void *
-PyCObject_Import(char *module_name, char *name)
+PyCObject_Import(const char *module_name, const char *name)
 {
     PyObject *m, *c;
     void *r = NULL;
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
@@ -541,7 +541,7 @@
 }
 
 PyObject *
-PyObject_CallFunction(PyObject *callable, char *format, ...)
+PyObject_CallFunction(PyObject *callable, const char *format, ...)
 {
 	va_list va;
 	PyObject *args;
@@ -558,7 +558,7 @@
 }
 
 PyObject *
-PyObject_CallMethod(PyObject *o, char *name, char *format, ...)
+PyObject_CallMethod(PyObject *o, const char *name, const char *format, ...)
 {
 	va_list va;
 	PyObject *args;
diff --git a/pypy/module/cpyext/src/pyerrors.c b/pypy/module/cpyext/src/pyerrors.c
--- a/pypy/module/cpyext/src/pyerrors.c
+++ b/pypy/module/cpyext/src/pyerrors.c
@@ -21,7 +21,7 @@
 }
 
 PyObject *
-PyErr_NewException(char *name, PyObject *base, PyObject *dict)
+PyErr_NewException(const char *name, PyObject *base, PyObject *dict)
 {
 	char *dot;
 	PyObject *modulename = NULL;
@@ -72,7 +72,7 @@
 
 /* Create an exception with docstring */
 PyObject *
-PyErr_NewExceptionWithDoc(char *name, char *doc, PyObject *base, PyObject *dict)
+PyErr_NewExceptionWithDoc(const char *name, const char *doc, PyObject *base, PyObject *dict)
 {
     int result;
     PyObject *ret = NULL;
diff --git a/pypy/module/cpyext/test/test_typeobject.py b/pypy/module/cpyext/test/test_typeobject.py
--- a/pypy/module/cpyext/test/test_typeobject.py
+++ b/pypy/module/cpyext/test/test_typeobject.py
@@ -397,3 +397,31 @@
             def __str__(self):
                 return "text"
         assert module.tp_str(C()) == "text"
+
+    def test_mp_ass_subscript(self):
+        module = self.import_extension('foo', [
+           ("new_obj", "METH_NOARGS",
+            '''
+                PyObject *obj;
+                Foo_Type.tp_as_mapping = &tp_as_mapping;
+                tp_as_mapping.mp_ass_subscript = mp_ass_subscript;
+                if (PyType_Ready(&Foo_Type) < 0) return NULL;
+                obj = PyObject_New(PyObject, &Foo_Type);
+                return obj;
+            '''
+            )],
+            '''
+            static int
+            mp_ass_subscript(PyObject *self, PyObject *key, PyObject *value)
+            {
+                PyErr_SetNone(PyExc_ZeroDivisionError);
+                return -1;
+            }
+            PyMappingMethods tp_as_mapping;
+            static PyTypeObject Foo_Type = {
+                PyVarObject_HEAD_INIT(NULL, 0)
+                "foo.foo",
+            };
+            ''')
+        obj = module.new_obj()
+        raises(ZeroDivisionError, obj.__setitem__, 5, None)
diff --git a/pypy/module/math/test/test_translated.py b/pypy/module/math/test/test_translated.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/math/test/test_translated.py
@@ -0,0 +1,10 @@
+import py
+from pypy.translator.c.test.test_genc import compile
+from pypy.module.math.interp_math import _gamma
+
+
+def test_gamma_overflow():
+    f = compile(_gamma, [float])
+    assert f(10.0) == 362880.0
+    py.test.raises(OverflowError, f, 1720.0)
+    py.test.raises(OverflowError, f, 172.0)
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
@@ -2,7 +2,7 @@
 
 
 class Module(MixedModule):
-    applevel_name = 'numpy'
+    applevel_name = 'numpypy'
 
     interpleveldefs = {
         'array': 'interp_numarray.SingleDimArray',
diff --git a/pypy/module/micronumpy/app_numpy.py b/pypy/module/micronumpy/app_numpy.py
--- a/pypy/module/micronumpy/app_numpy.py
+++ b/pypy/module/micronumpy/app_numpy.py
@@ -1,6 +1,6 @@
 import math
 
-import numpy
+import numpypy
 
 
 inf = float("inf")
@@ -13,5 +13,5 @@
 
 def mean(a):
     if not hasattr(a, "mean"):
-        a = numpy.array(a)
+        a = numpypy.array(a)
     return a.mean()
diff --git a/pypy/module/micronumpy/bench/add.py b/pypy/module/micronumpy/bench/add.py
--- a/pypy/module/micronumpy/bench/add.py
+++ b/pypy/module/micronumpy/bench/add.py
@@ -1,5 +1,8 @@
 
-import numpy
+try:
+    import numpypy as numpy
+except:
+    import numpy
 
 def f():
     a = numpy.zeros(10000000)
diff --git a/pypy/module/micronumpy/bench/iterate.py b/pypy/module/micronumpy/bench/iterate.py
--- a/pypy/module/micronumpy/bench/iterate.py
+++ b/pypy/module/micronumpy/bench/iterate.py
@@ -1,5 +1,8 @@
 
-import numpy
+try:
+    import numpypy as numpy
+except:
+    import numpy
 
 def f():
     sum = 0
diff --git a/pypy/module/micronumpy/test/test_dtypes.py b/pypy/module/micronumpy/test/test_dtypes.py
--- a/pypy/module/micronumpy/test/test_dtypes.py
+++ b/pypy/module/micronumpy/test/test_dtypes.py
@@ -3,7 +3,7 @@
 
 class AppTestDtypes(BaseNumpyAppTest):
     def test_dtype(self):
-        from numpy import dtype
+        from numpypy import dtype
 
         d = dtype('?')
         assert d.num == 0
@@ -14,7 +14,7 @@
         raises(TypeError, dtype, 1042)
 
     def test_dtype_with_types(self):
-        from numpy import dtype
+        from numpypy import dtype
 
         assert dtype(bool).num == 0
         assert dtype(int).num == 7
@@ -22,13 +22,13 @@
         assert dtype(float).num == 12
 
     def test_array_dtype_attr(self):
-        from numpy import array, dtype
+        from numpypy import array, dtype
 
         a = array(range(5), long)
         assert a.dtype is dtype(long)
 
     def test_repr_str(self):
-        from numpy import dtype
+        from numpypy import dtype
 
         assert repr(dtype) == "<type 'numpy.dtype'>"
         d = dtype('?')
@@ -36,57 +36,57 @@
         assert str(d) == "bool"
 
     def test_bool_array(self):
-        import numpy
+        from numpypy import array, False_, True_
 
-        a = numpy.array([0, 1, 2, 2.5], dtype='?')
-        assert a[0] is numpy.False_
+        a = array([0, 1, 2, 2.5], dtype='?')
+        assert a[0] is False_
         for i in xrange(1, 4):
-            assert a[i] is numpy.True_
+            assert a[i] is True_
 
     def test_copy_array_with_dtype(self):
-        import numpy
+        from numpypy import array, False_, True_
 
-        a = numpy.array([0, 1, 2, 3], dtype=long)
+        a = array([0, 1, 2, 3], dtype=long)
         # int on 64-bit, long in 32-bit
         assert isinstance(a[0], (int, long))
         b = a.copy()
         assert isinstance(b[0], (int, long))
 
-        a = numpy.array([0, 1, 2, 3], dtype=bool)
-        assert a[0] is numpy.False_
+        a = array([0, 1, 2, 3], dtype=bool)
+        assert a[0] is False_
         b = a.copy()
-        assert b[0] is numpy.False_
+        assert b[0] is False_
 
     def test_zeros_bool(self):
-        import numpy
+        from numpypy import zeros, False_
 
-        a = numpy.zeros(10, dtype=bool)
+        a = zeros(10, dtype=bool)
         for i in range(10):
-            assert a[i] is numpy.False_
+            assert a[i] is False_
 
     def test_ones_bool(self):
-        import numpy
+        from numpypy import ones, True_
 
-        a = numpy.ones(10, dtype=bool)
+        a = ones(10, dtype=bool)
         for i in range(10):
-            assert a[i] is numpy.True_
+            assert a[i] is True_
 
     def test_zeros_long(self):
-        from numpy import zeros
+        from numpypy import zeros
         a = zeros(10, dtype=long)
         for i in range(10):
             assert isinstance(a[i], (int, long))
             assert a[1] == 0
 
     def test_ones_long(self):
-        from numpy import ones
+        from numpypy import ones
         a = ones(10, dtype=long)
         for i in range(10):
             assert isinstance(a[i], (int, long))
             assert a[1] == 1
 
     def test_overflow(self):
-        from numpy import array, dtype
+        from numpypy import array, dtype
         assert array([128], 'b')[0] == -128
         assert array([256], 'B')[0] == 0
         assert array([32768], 'h')[0] == -32768
@@ -98,7 +98,7 @@
         raises(OverflowError, "array([2**64], 'Q')")
 
     def test_bool_binop_types(self):
-        from numpy import array, dtype
+        from numpypy import array, dtype
         types = [
             '?', 'b', 'B', 'h', 'H', 'i', 'I', 'l', 'L', 'q', 'Q', 'f', 'd'
         ]
@@ -107,7 +107,7 @@
             assert (a + array([0], t)).dtype is dtype(t)
 
     def test_binop_types(self):
-        from numpy import array, dtype
+        from numpypy import array, dtype
         tests = [('b','B','h'), ('b','h','h'), ('b','H','i'), ('b','i','i'),
                  ('b','l','l'), ('b','q','q'), ('b','Q','d'), ('B','h','h'),
                  ('B','H','H'), ('B','i','i'), ('B','I','I'), ('B','l','l'),
@@ -129,7 +129,7 @@
             assert (array([1], d1) + array([1], d2)).dtype is dtype(dout)
 
     def test_add_int8(self):
-        from numpy import array, dtype
+        from numpypy import array, dtype
 
         a = array(range(5), dtype="int8")
         b = a + a
@@ -138,7 +138,7 @@
             assert b[i] == i * 2
 
     def test_add_int16(self):
-        from numpy import array, dtype
+        from numpypy import array, dtype
 
         a = array(range(5), dtype="int16")
         b = a + a
@@ -147,7 +147,7 @@
             assert b[i] == i * 2
 
     def test_add_uint32(self):
-        from numpy import array, dtype
+        from numpypy import array, dtype
 
         a = array(range(5), dtype="I")
         b = a + a
@@ -156,12 +156,12 @@
             assert b[i] == i * 2
 
     def test_shape(self):
-        from numpy import dtype
+        from numpypy import dtype
 
         assert dtype(long).shape == ()
 
     def test_cant_subclass(self):
-        from numpy import dtype
+        from numpypy import dtype
 
         # You can't subclass dtype
         raises(TypeError, type, "Foo", (dtype,), {})
diff --git a/pypy/module/micronumpy/test/test_module.py b/pypy/module/micronumpy/test/test_module.py
--- a/pypy/module/micronumpy/test/test_module.py
+++ b/pypy/module/micronumpy/test/test_module.py
@@ -3,19 +3,19 @@
 
 class AppTestNumPyModule(BaseNumpyAppTest):
     def test_mean(self):
-        from numpy import array, mean
+        from numpypy import array, mean
         assert mean(array(range(5))) == 2.0
         assert mean(range(5)) == 2.0
 
     def test_average(self):
-        from numpy import array, average
+        from numpypy import array, average
         assert average(range(10)) == 4.5
         assert average(array(range(10))) == 4.5
 
     def test_constants(self):
         import math
-        from numpy import inf, e
+        from numpypy import inf, e
         assert type(inf) is float
         assert inf == float("inf")
         assert e == math.e
-        assert type(e) is float
\ No newline at end of file
+        assert type(e) is float
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
@@ -4,12 +4,12 @@
 
 class AppTestNumArray(BaseNumpyAppTest):
     def test_type(self):
-        from numpy import array
+        from numpypy import array
         ar = array(range(5))
         assert type(ar) is type(ar + ar)
 
     def test_init(self):
-        from numpy import zeros
+        from numpypy import zeros
         a = zeros(15)
         # Check that storage was actually zero'd.
         assert a[10] == 0.0
@@ -18,7 +18,7 @@
         assert a[13] == 5.3
 
     def test_size(self):
-        from numpy import array
+        from numpypy import array
         # XXX fixed on multidim branch
         #assert array(3).size == 1
         a = array([1, 2, 3])
@@ -30,13 +30,13 @@
         Test that empty() works.
         """
 
-        from numpy import empty
+        from numpypy import empty
         a = empty(2)
         a[1] = 1.0
         assert a[1] == 1.0
 
     def test_ones(self):
-        from numpy import ones
+        from numpypy import ones
         a = ones(3)
         assert len(a) == 3
         assert a[0] == 1
@@ -45,19 +45,19 @@
         assert a[2] == 4
 
     def test_copy(self):
-        from numpy import array
+        from numpypy import array
         a = array(range(5))
         b = a.copy()
         for i in xrange(5):
             assert b[i] == a[i]
 
     def test_iterator_init(self):
-        from numpy import array
+        from numpypy import array
         a = array(range(5))
         assert a[3] == 3
 
     def test_repr(self):
-        from numpy import array, zeros
+        from numpypy import array, zeros
         a = array(range(5), float)
         assert repr(a) == "array([0.0, 1.0, 2.0, 3.0, 4.0])"
         a = array([], float)
@@ -72,7 +72,7 @@
         assert repr(a) == "array([True, False, True, False], dtype=bool)"
 
     def test_repr_slice(self):
-        from numpy import array, zeros
+        from numpypy import array, zeros
         a = array(range(5), float)
         b = a[1::2]
         assert repr(b) == "array([1.0, 3.0])"
@@ -81,7 +81,7 @@
         assert repr(b) == "array([0.0, 0.0, 0.0, ..., 0.0, 0.0, 0.0])"
 
     def test_str(self):
-        from numpy import array, zeros
+        from numpypy import array, zeros
         a = array(range(5), float)
         assert str(a) == "[0.0 1.0 2.0 3.0 4.0]"
         assert str((2*a)[:]) == "[0.0 2.0 4.0 6.0 8.0]"
@@ -100,7 +100,7 @@
         assert str(a) == "[0 1 2 3 4]"
 
     def test_str_slice(self):
-        from numpy import array, zeros
+        from numpypy import array, zeros
         a = array(range(5), float)
         b = a[1::2]
         assert str(b) == "[1.0 3.0]"
@@ -109,7 +109,7 @@
         assert str(b) == "[0.0 0.0 0.0 ..., 0.0 0.0 0.0]"
 
     def test_getitem(self):
-        from numpy import array
+        from numpypy import array
         a = array(range(5))
         raises(IndexError, "a[5]")
         a = a + a
@@ -118,7 +118,7 @@
         raises(IndexError, "a[-6]")
 
     def test_getitem_tuple(self):
-        from numpy import array
+        from numpypy import array
         a = array(range(5))
         raises(IndexError, "a[(1,2)]")
         for i in xrange(5):
@@ -128,7 +128,7 @@
             assert a[i] == b[i]
 
     def test_setitem(self):
-        from numpy import array
+        from numpypy import array
         a = array(range(5))
         a[-1] = 5.0
         assert a[4] == 5.0
@@ -136,7 +136,7 @@
         raises(IndexError, "a[-6] = 3.0")
 
     def test_setitem_tuple(self):
-        from numpy import array
+        from numpypy import array
         a = array(range(5))
         raises(IndexError, "a[(1,2)] = [0,1]")
         for i in xrange(5):
@@ -147,7 +147,7 @@
             assert a[i] == i
 
     def test_setslice_array(self):
-        from numpy import array
+        from numpypy import array
         a = array(range(5))
         b = array(range(2))
         a[1:4:2] = b
@@ -158,7 +158,7 @@
         assert b[1] == 0.
 
     def test_setslice_of_slice_array(self):
-        from numpy import array, zeros
+        from numpypy import array, zeros
         a = zeros(5)
         a[::2] = array([9., 10., 11.])
         assert a[0] == 9.
@@ -177,7 +177,7 @@
         assert a[0] == 3.
 
     def test_setslice_list(self):
-        from numpy import array
+        from numpypy import array
         a = array(range(5), float)
         b = [0., 1.]
         a[1:4:2] = b
@@ -185,20 +185,20 @@
         assert a[3] == 1.
 
     def test_setslice_constant(self):
-        from numpy import array
+        from numpypy import array
         a = array(range(5), float)
         a[1:4:2] = 0.
         assert a[1] == 0.
         assert a[3] == 0.
 
     def test_len(self):
-        from numpy import array
+        from numpypy import array
         a = array(range(5))
         assert len(a) == 5
         assert len(a + a) == 5
 
     def test_shape(self):
-        from numpy import array
+        from numpypy import array
         a = array(range(5))
         assert a.shape == (5,)
         b = a + a
@@ -207,7 +207,7 @@
         assert c.shape == (3,)
 
     def test_add(self):
-        from numpy import array
+        from numpypy import array
         a = array(range(5))
         b = a + a
         for i in range(5):
@@ -220,7 +220,7 @@
             assert c[i] == bool(a[i] + b[i])
 
     def test_add_other(self):
-        from numpy import array
+        from numpypy import array
         a = array(range(5))
         b = array(range(4, -1, -1))
         c = a + b
@@ -228,20 +228,20 @@
             assert c[i] == 4
 
     def test_add_constant(self):
-        from numpy import array
+        from numpypy import array
         a = array(range(5))
         b = a + 5
         for i in range(5):
             assert b[i] == i + 5
 
     def test_radd(self):
-        from numpy import array
+        from numpypy import array
         r = 3 + array(range(3))
         for i in range(3):
             assert r[i] == i + 3
 
     def test_add_list(self):
-        from numpy import array
+        from numpypy import array
         a = array(range(5))
         b = list(reversed(range(5)))
         c = a + b
@@ -250,14 +250,14 @@
             assert c[i] == 4
 
     def test_subtract(self):
-        from numpy import array
+        from numpypy 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
+        from numpypy import array
         a = array(range(5))
         b = array([1, 1, 1, 1, 1])
         c = a - b
@@ -265,29 +265,29 @@
             assert c[i] == i - 1
 
     def test_subtract_constant(self):
-        from numpy import array
+        from numpypy import array
         a = array(range(5))
         b = a - 5
         for i in range(5):
             assert b[i] == i - 5
 
     def test_mul(self):
-        import numpy
+        import numpypy
 
-        a = numpy.array(range(5))
+        a = numpypy.array(range(5))
         b = a * a
         for i in range(5):
             assert b[i] == i * i
 
-        a = numpy.array(range(5), dtype=bool)
+        a = numpypy.array(range(5), dtype=bool)
         b = a * a
-        assert b.dtype is numpy.dtype(bool)
-        assert b[0] is numpy.False_
+        assert b.dtype is numpypy.dtype(bool)
+        assert b[0] is numpypy.False_
         for i in range(1, 5):
-            assert b[i] is numpy.True_
+            assert b[i] is numpypy.True_
 
     def test_mul_constant(self):
-        from numpy import array
+        from numpypy import array
         a = array(range(5))
         b = a * 5
         for i in range(5):
@@ -295,7 +295,7 @@
 
     def test_div(self):
         from math import isnan
-        from numpy import array, dtype, inf
+        from numpypy import array, dtype, inf
 
         a = array(range(1, 6))
         b = a / a
@@ -327,7 +327,7 @@
         assert c[2] == -inf
 
     def test_div_other(self):
-        from numpy import array
+        from numpypy import array
         a = array(range(5))
         b = array([2, 2, 2, 2, 2], float)
         c = a / b
@@ -335,14 +335,14 @@
             assert c[i] == i / 2.0
 
     def test_div_constant(self):
-        from numpy import array
+        from numpypy import array
         a = array(range(5))
         b = a / 5.0
         for i in range(5):
             assert b[i] == i / 5.0
 
     def test_pow(self):
-        from numpy import array
+        from numpypy import array
         a = array(range(5), float)
         b = a ** a
         for i in range(5):
@@ -350,7 +350,7 @@
             assert b[i] == i**i
 
     def test_pow_other(self):
-        from numpy import array
+        from numpypy import array
         a = array(range(5), float)
         b = array([2, 2, 2, 2, 2])
         c = a ** b
@@ -358,14 +358,14 @@
             assert c[i] == i ** 2
 
     def test_pow_constant(self):
-        from numpy import array
+        from numpypy import array
         a = array(range(5), float)
         b = a ** 2
         for i in range(5):
             assert b[i] == i ** 2
 
     def test_mod(self):
-        from numpy import array
+        from numpypy import array
         a = array(range(1,6))
         b = a % a
         for i in range(5):
@@ -378,7 +378,7 @@
             assert b[i] == 1
 
     def test_mod_other(self):
-        from numpy import array
+        from numpypy import array
         a = array(range(5))
         b = array([2, 2, 2, 2, 2])
         c = a % b
@@ -386,14 +386,14 @@
             assert c[i] == i % 2
 
     def test_mod_constant(self):
-        from numpy import array
+        from numpypy import array
         a = array(range(5))
         b = a % 2
         for i in range(5):
             assert b[i] == i % 2
 
     def test_pos(self):
-        from numpy import array
+        from numpypy import array
         a = array([1.,-2.,3.,-4.,-5.])
         b = +a
         for i in range(5):
@@ -404,7 +404,7 @@
             assert a[i] == i
 
     def test_neg(self):
-        from numpy import array
+        from numpypy import array
         a = array([1.,-2.,3.,-4.,-5.])
         b = -a
         for i in range(5):
@@ -415,7 +415,7 @@
             assert a[i] == -i
 
     def test_abs(self):
-        from numpy import array
+        from numpypy import array
         a = array([1.,-2.,3.,-4.,-5.])
         b = abs(a)
         for i in range(5):
@@ -426,7 +426,7 @@
             assert a[i + 5] == abs(i)
 
     def test_auto_force(self):
-        from numpy import array
+        from numpypy import array
         a = array(range(5))
         b = a - 1
         a[2] = 3
@@ -440,7 +440,7 @@
         assert c[1] == 4
 
     def test_getslice(self):
-        from numpy import array
+        from numpypy import array
         a = array(range(5))
         s = a[1:5]
         assert len(s) == 4
@@ -454,7 +454,7 @@
         assert s[0] == 5
 
     def test_getslice_step(self):
-        from numpy import array
+        from numpypy import array
         a = array(range(10))
         s = a[1:9:2]
         assert len(s) == 4
@@ -462,7 +462,7 @@
             assert s[i] == a[2*i+1]
 
     def test_slice_update(self):
-        from numpy import array
+        from numpypy import array
         a = array(range(5))
         s = a[0:3]
         s[1] = 10
@@ -473,7 +473,7 @@
 
     def test_slice_invaidate(self):
         # check that slice shares invalidation list with
-        from numpy import array
+        from numpypy import array
         a = array(range(5))
         s = a[0:2]
         b = array([10,11])
@@ -487,13 +487,13 @@
         assert d[1] == 12
 
     def test_mean(self):
-        from numpy import array
+        from numpypy import array
         a = array(range(5))
         assert a.mean() == 2.0
         assert a[:4].mean() == 1.5
 
     def test_sum(self):
-        from numpy import array
+        from numpypy import array
         a = array(range(5))
         assert a.sum() == 10.0
         assert a[:4].sum() == 6.0
@@ -502,32 +502,32 @@
         assert a.sum() == 5
 
     def test_prod(self):
-        from numpy import array
+        from numpypy import array
         a = array(range(1,6))
         assert a.prod() == 120.0
         assert a[:4].prod() == 24.0
 
     def test_max(self):
-        from numpy import array
+        from numpypy import array
         a = array([-1.2, 3.4, 5.7, -3.0, 2.7])
         assert a.max() == 5.7
         b = array([])
         raises(ValueError, "b.max()")
 
     def test_max_add(self):
-        from numpy import array
+        from numpypy import array
         a = array([-1.2, 3.4, 5.7, -3.0, 2.7])
         assert (a+a).max() == 11.4
 
     def test_min(self):
-        from numpy import array
+        from numpypy import array
         a = array([-1.2, 3.4, 5.7, -3.0, 2.7])
         assert a.min() == -3.0
         b = array([])
         raises(ValueError, "b.min()")
 
     def test_argmax(self):
-        from numpy import array
+        from numpypy import array
         a = array([-1.2, 3.4, 5.7, -3.0, 2.7])
         assert a.argmax() == 2
         b = array([])
@@ -537,14 +537,14 @@
         assert a.argmax() == 9
 
     def test_argmin(self):
-        from numpy import array
+        from numpypy import array
         a = array([-1.2, 3.4, 5.7, -3.0, 2.7])
         assert a.argmin() == 3
         b = array([])
         raises(ValueError, "b.argmin()")
 
     def test_all(self):
-        from numpy import array
+        from numpypy import array
         a = array(range(5))
         assert a.all() == False
         a[0] = 3.0
@@ -553,7 +553,7 @@
         assert b.all() == True
 
     def test_any(self):
-        from numpy import array, zeros
+        from numpypy import array, zeros
         a = array(range(5))
         assert a.any() == True
         b = zeros(5)
@@ -562,7 +562,7 @@
         assert c.any() == False
 
     def test_dot(self):
-        from numpy import array
+        from numpypy import array
         a = array(range(5))
         assert a.dot(a) == 30.0
 
@@ -570,14 +570,14 @@
         assert a.dot(range(5)) == 30
 
     def test_dot_constant(self):
-        from numpy import array
+        from numpypy import array
         a = array(range(5))
         b = a.dot(2.5)
         for i in xrange(5):
             assert b[i] == 2.5 * a[i]
 
     def test_dtype_guessing(self):
-        from numpy import array, dtype
+        from numpypy import array, dtype
 
         assert array([True]).dtype is dtype(bool)
         assert array([True, False]).dtype is dtype(bool)
@@ -590,7 +590,7 @@
 
     def test_comparison(self):
         import operator
-        from numpy import array, dtype
+        from numpypy import array, dtype
 
         a = array(range(5))
         b = array(range(5), float)
@@ -616,7 +616,7 @@
         cls.w_data = cls.space.wrap(struct.pack('dddd', 1, 2, 3, 4))
 
     def test_fromstring(self):
-        from numpy import fromstring
+        from numpypy import fromstring
         a = fromstring(self.data)
         for i in range(4):
             assert a[i] == i + 1
diff --git a/pypy/module/micronumpy/test/test_ufuncs.py b/pypy/module/micronumpy/test/test_ufuncs.py
--- a/pypy/module/micronumpy/test/test_ufuncs.py
+++ b/pypy/module/micronumpy/test/test_ufuncs.py
@@ -4,14 +4,14 @@
 
 class AppTestUfuncs(BaseNumpyAppTest):
     def test_ufunc_instance(self):
-        from numpy import add, ufunc
+        from numpypy import add, ufunc
 
         assert isinstance(add, ufunc)
         assert repr(add) == "<ufunc 'add'>"
         assert repr(ufunc) == "<type 'numpy.ufunc'>"
 
     def test_ufunc_attrs(self):
-        from numpy import add, multiply, sin
+        from numpypy import add, multiply, sin
 
         assert add.identity == 0
         assert multiply.identity == 1
@@ -22,7 +22,7 @@
         assert sin.nin == 1
 
     def test_wrong_arguments(self):
-        from numpy import add, sin
+        from numpypy import add, sin
 
         raises(ValueError, add, 1)
         raises(TypeError, add, 1, 2, 3)
@@ -30,14 +30,14 @@
         raises(ValueError, sin)
 
     def test_single_item(self):
-        from numpy import negative, sign, minimum
+        from numpypy import negative, sign, minimum
 
         assert negative(5.0) == -5.0
         assert sign(-0.0) == 0.0
         assert minimum(2.0, 3.0) == 2.0
 
     def test_sequence(self):
-        from numpy import array, negative, minimum
+        from numpypy import array, negative, minimum
         a = array(range(3))
         b = [2.0, 1.0, 0.0]
         c = 1.0
@@ -71,7 +71,7 @@
             assert min_c_b[i] == min(b[i], c)
 
     def test_negative(self):
-        from numpy import array, negative
+        from numpypy import array, negative
 
         a = array([-5.0, 0.0, 1.0])
         b = negative(a)
@@ -86,7 +86,7 @@
         assert negative(a + a)[3] == -6
 
     def test_abs(self):
-        from numpy import array, absolute
+        from numpypy import array, absolute
 
         a = array([-5.0, -0.0, 1.0])
         b = absolute(a)
@@ -94,7 +94,7 @@
             assert b[i] == abs(a[i])
 
     def test_add(self):
-        from numpy import array, add
+        from numpypy import array, add
 
         a = array([-5.0, -0.0, 1.0])
         b = array([ 3.0, -2.0,-3.0])
@@ -103,7 +103,7 @@
             assert c[i] == a[i] + b[i]
 
     def test_divide(self):
-        from numpy import array, divide
+        from numpypy import array, divide
 
         a = array([-5.0, -0.0, 1.0])
         b = array([ 3.0, -2.0,-3.0])
@@ -112,7 +112,7 @@
             assert c[i] == a[i] / b[i]
 
     def test_fabs(self):
-        from numpy import array, fabs
+        from numpypy import array, fabs
         from math import fabs as math_fabs
 
         a = array([-5.0, -0.0, 1.0])
@@ -121,7 +121,7 @@
             assert b[i] == math_fabs(a[i])
 
     def test_minimum(self):
-        from numpy import array, minimum
+        from numpypy import array, minimum
 
         a = array([-5.0, -0.0, 1.0])
         b = array([ 3.0, -2.0,-3.0])
@@ -130,7 +130,7 @@
             assert c[i] == min(a[i], b[i])
 
     def test_maximum(self):
-        from numpy import array, maximum
+        from numpypy import array, maximum
 
         a = array([-5.0, -0.0, 1.0])
         b = array([ 3.0, -2.0,-3.0])
@@ -143,7 +143,7 @@
         assert isinstance(x, (int, long))
 
     def test_multiply(self):
-        from numpy import array, multiply
+        from numpypy import array, multiply
 
         a = array([-5.0, -0.0, 1.0])
         b = array([ 3.0, -2.0,-3.0])
@@ -152,7 +152,7 @@
             assert c[i] == a[i] * b[i]
 
     def test_sign(self):
-        from numpy import array, sign, dtype
+        from numpypy import array, sign, dtype
 
         reference = [-1.0, 0.0, 0.0, 1.0]
         a = array([-5.0, -0.0, 0.0, 6.0])
@@ -171,7 +171,7 @@
         assert a[1] == 0
 
     def test_reciporocal(self):
-        from numpy import array, reciprocal
+        from numpypy import array, reciprocal
 
         reference = [-0.2, float("inf"), float("-inf"), 2.0]
         a = array([-5.0, 0.0, -0.0, 0.5])
@@ -180,7 +180,7 @@
             assert b[i] == reference[i]
 
     def test_subtract(self):
-        from numpy import array, subtract
+        from numpypy import array, subtract
 
         a = array([-5.0, -0.0, 1.0])
         b = array([ 3.0, -2.0,-3.0])
@@ -189,7 +189,7 @@
             assert c[i] == a[i] - b[i]
 
     def test_floor(self):
-        from numpy import array, floor
+        from numpypy import array, floor
 
         reference = [-2.0, -1.0, 0.0, 1.0, 1.0]
         a = array([-1.4, -1.0, 0.0, 1.0, 1.4])
@@ -198,7 +198,7 @@
             assert b[i] == reference[i]
 
     def test_copysign(self):
-        from numpy import array, copysign
+        from numpypy import array, copysign
 
         reference = [5.0, -0.0, 0.0, -6.0]
         a = array([-5.0, 0.0, 0.0, 6.0])
@@ -214,7 +214,7 @@
 
     def test_exp(self):
         import math
-        from numpy import array, exp
+        from numpypy import array, exp
 
         a = array([-5.0, -0.0, 0.0, 12345678.0, float("inf"),
                    -float('inf'), -12343424.0])
@@ -228,7 +228,7 @@
 
     def test_sin(self):
         import math
-        from numpy import array, sin
+        from numpypy import array, sin
 
         a = array([0, 1, 2, 3, math.pi, math.pi*1.5, math.pi*2])
         b = sin(a)
@@ -241,7 +241,7 @@
 
     def test_cos(self):
         import math
-        from numpy import array, cos
+        from numpypy import array, cos
 
         a = array([0, 1, 2, 3, math.pi, math.pi*1.5, math.pi*2])
         b = cos(a)
@@ -250,7 +250,7 @@
 
     def test_tan(self):
         import math
-        from numpy import array, tan
+        from numpypy import array, tan
 
         a = array([0, 1, 2, 3, math.pi, math.pi*1.5, math.pi*2])
         b = tan(a)
@@ -260,7 +260,7 @@
 
     def test_arcsin(self):
         import math
-        from numpy import array, arcsin
+        from numpypy import array, arcsin
 
         a = array([-1, -0.5, -0.33, 0, 0.33, 0.5, 1])
         b = arcsin(a)
@@ -274,7 +274,7 @@
 
     def test_arccos(self):
         import math
-        from numpy import array, arccos
+        from numpypy import array, arccos
 
         a = array([-1, -0.5, -0.33, 0, 0.33, 0.5, 1])
         b = arccos(a)
@@ -289,7 +289,7 @@
 
     def test_arctan(self):
         import math
-        from numpy import array, arctan
+        from numpypy import array, arctan
 
         a = array([-3, -2, -1, 0, 1, 2, 3, float('inf'), float('-inf')])
         b = arctan(a)
@@ -302,7 +302,7 @@
 
     def test_arcsinh(self):
         import math
-        from numpy import arcsinh, inf
+        from numpypy import arcsinh, inf
 
         for v in [inf, -inf, 1.0, math.e]:
             assert math.asinh(v) == arcsinh(v)
@@ -310,7 +310,7 @@
 
     def test_arctanh(self):
         import math
-        from numpy import arctanh
+        from numpypy import arctanh
 
         for v in [.99, .5, 0, -.5, -.99]:
             assert math.atanh(v) == arctanh(v)
@@ -320,13 +320,13 @@
             assert arctanh(v) == math.copysign(float("inf"), v)
 
     def test_reduce_errors(self):
-        from numpy import sin, add
+        from numpypy import sin, add
 
         raises(ValueError, sin.reduce, [1, 2, 3])
         raises(TypeError, add.reduce, 1)
 
     def test_reduce(self):
-        from numpy import add, maximum
+        from numpypy import add, maximum
 
         assert add.reduce([1, 2, 3]) == 6
         assert maximum.reduce([1]) == 1
@@ -335,7 +335,7 @@
 
     def test_comparisons(self):
         import operator
-        from numpy import equal, not_equal, less, less_equal, greater, greater_equal
+        from numpypy import equal, not_equal, less, less_equal, greater, greater_equal
 
         for ufunc, func in [
             (equal, operator.eq),
diff --git a/pypy/module/pyexpat/interp_pyexpat.py b/pypy/module/pyexpat/interp_pyexpat.py
--- a/pypy/module/pyexpat/interp_pyexpat.py
+++ b/pypy/module/pyexpat/interp_pyexpat.py
@@ -3,9 +3,7 @@
 from pypy.interpreter.gateway import NoneNotWrapped
 from pypy.interpreter.gateway import interp2app, unwrap_spec
 from pypy.interpreter.error import OperationError
-from pypy.objspace.descroperation import object_setattr
 from pypy.rlib import rgc
-from pypy.rlib.unroll import unrolling_iterable
 from pypy.rpython.lltypesystem import rffi, lltype
 from pypy.rpython.tool import rffi_platform
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
@@ -339,8 +337,6 @@
     'XML_SetUnknownEncodingHandler',
     [XML_Parser, callback_type, rffi.VOIDP], lltype.Void)
 
-ENUMERATE_SETTERS = unrolling_iterable(SETTERS.items())
-
 # Declarations of external functions
 
 XML_ParserCreate = expat_external(
@@ -545,15 +541,19 @@
                 self.buffer_used = 0
         return False
 
+    def gethandler(self, space, name, index):
+        if name == 'CharacterDataHandler':
+            return self.w_character_data_handler or space.w_None
+        return self.handlers[index]
+
     def sethandler(self, space, name, w_handler, index, setter, handler):
-
         if name == 'CharacterDataHandler':
             self.flush_character_buffer(space)
             if space.is_w(w_handler, space.w_None):
                 self.w_character_data_handler = None
             else:
                 self.w_character_data_handler = w_handler
-
+        #
         self.handlers[index] = w_handler
         setter(self.itself, handler)
 
@@ -580,21 +580,29 @@
         return True
 
 
-    @unwrap_spec(name=str)
-    def setattr(self, space, name, w_value):
-        if name == "namespace_prefixes":
-            XML_SetReturnNSTriplet(self.itself, space.int_w(w_value))
-            return
+    @staticmethod
+    def _make_property(name):
+        index, setter, handler = SETTERS[name]
+        #
+        def descr_get_property(self, space):
+            return self.gethandler(space, name, index)
+        #
+        def descr_set_property(self, space, w_value):
+            return self.sethandler(space, name, w_value,
+                                   index, setter, handler)
+        #
+        return GetSetProperty(descr_get_property,
+                              descr_set_property,
+                              cls=W_XMLParserType)
 
-        for handler_name, (index, setter, handler) in ENUMERATE_SETTERS:
-            if name == handler_name:
-                return self.sethandler(space, handler_name, w_value,
-                                       index, setter, handler)
 
-        # fallback to object.__setattr__()
-        return space.call_function(
-            object_setattr(space),
-            space.wrap(self), space.wrap(name), w_value)
+    def get_namespace_prefixes(self, space):
+        raise OperationError(space.w_AttributeError,
+            space.wrap("not implemented: reading namespace_prefixes"))
+
+    @unwrap_spec(value=int)
+    def set_namespace_prefixes(self, space, value):
+        XML_SetReturnNSTriplet(self.itself, bool(value))
 
     # Parse methods
 
@@ -732,10 +740,18 @@
 if XML_COMBINED_VERSION >= 19505:
     XMLParser_methods.append('UseForeignDTD')
 
+_XMLParser_extras = {}
+for name in XMLParser_methods:
+    _XMLParser_extras[name] = interp2app(getattr(W_XMLParserType, name))
+for name in SETTERS:
+    _XMLParser_extras[name] = W_XMLParserType._make_property(name)
+
 W_XMLParserType.typedef = TypeDef(
     "pyexpat.XMLParserType",
     __doc__ = "XML parser",
-    __setattr__ = interp2app(W_XMLParserType.setattr),
+    namespace_prefixes = GetSetProperty(W_XMLParserType.get_namespace_prefixes,
+                                        W_XMLParserType.set_namespace_prefixes,
+                                        cls=W_XMLParserType),
     returns_unicode = bool_property('returns_unicode', W_XMLParserType),
     ordered_attributes = bool_property('ordered_attributes', W_XMLParserType),
     specified_attributes = bool_property('specified_attributes', W_XMLParserType),
@@ -754,8 +770,7 @@
     CurrentColumnNumber = GetSetProperty(W_XMLParserType.descr_ErrorColumnNumber, cls=W_XMLParserType),
     CurrentByteIndex = GetSetProperty(W_XMLParserType.descr_ErrorByteIndex, cls=W_XMLParserType),
 
-    **dict((name, interp2app(getattr(W_XMLParserType, name)))
-           for name in XMLParser_methods)
+    **_XMLParser_extras
     )
 
 def ParserCreate(space, w_encoding=None, w_namespace_separator=None,
diff --git a/pypy/module/pyexpat/test/test_parser.py b/pypy/module/pyexpat/test/test_parser.py
--- a/pypy/module/pyexpat/test/test_parser.py
+++ b/pypy/module/pyexpat/test/test_parser.py
@@ -52,6 +52,19 @@
                 assert res == 1
                 assert data == [u"\u00f6"]
 
+    def test_get_handler(self):
+        import pyexpat
+        p = pyexpat.ParserCreate()
+        assert p.StartElementHandler is None
+        assert p.EndElementHandler is None
+        def f(*args): pass
+        p.StartElementHandler = f
+        assert p.StartElementHandler is f
+        def g(*args): pass
+        p.EndElementHandler = g
+        assert p.StartElementHandler is f
+        assert p.EndElementHandler is g
+
     def test_intern(self):
         import pyexpat
         p = pyexpat.ParserCreate()
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
@@ -6,6 +6,7 @@
 from pypy.tool.pairtype import extendabletype
 from pypy.rlib.rarithmetic import r_uint, intmask
 from pypy.rlib.jit import JitDriver, hint, we_are_jitted, dont_look_inside
+from pypy.rlib import jit
 from pypy.rlib.jit import current_trace_length, unroll_parameters
 import pypy.interpreter.pyopcode   # for side-effects
 from pypy.interpreter.error import OperationError, operationerrfmt
@@ -200,18 +201,18 @@
     if len(args_w) == 1:
         text = space.str_w(args_w[0])
         try:
-            pypyjitdriver.set_user_param(text)
+            jit.set_user_param(None, text)
         except ValueError:
             raise OperationError(space.w_ValueError,
                                  space.wrap("error in JIT parameters string"))
     for key, w_value in kwds_w.items():
         if key == 'enable_opts':
-            pypyjitdriver.set_param('enable_opts', space.str_w(w_value))
+            jit.set_param(None, 'enable_opts', space.str_w(w_value))
         else:
             intval = space.int_w(w_value)
             for name, _ in unroll_parameters:
                 if name == key and name != 'enable_opts':
-                    pypyjitdriver.set_param(name, intval)
+                    jit.set_param(None, name, intval)
                     break
             else:
                 raise operationerrfmt(space.w_TypeError,
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
@@ -17,7 +17,7 @@
                        'imp', 'sys', 'array', '_ffi', 'itertools', 'operator',
                        'posix', '_socket', '_sre', '_lsprof', '_weakref',
                        '__pypy__', 'cStringIO', '_collections', 'struct',
-                       'mmap']:
+                       'mmap', 'marshal']:
             return True
         return False
 
diff --git a/pypy/module/pypyjit/test_pypy_c/test_string.py b/pypy/module/pypyjit/test_pypy_c/test_string.py
--- a/pypy/module/pypyjit/test_pypy_c/test_string.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_string.py
@@ -147,8 +147,8 @@
             i31 = int_gt(i30, 23)
             guard_false(i31, descr=...)
             copystrcontent(p9, p21, 0, i25, i10)
-            i33 = int_eq(i30, 23)
-            guard_false(i33, descr=...)
+            i33 = int_lt(i30, 23)
+            guard_true(i33, descr=...)
             p35 = call(ConstClass(ll_shrink_array__rpy_stringPtr_Signed), p21, i30, descr=<GcPtrCallDescr>)
             guard_no_exception(descr=...)
             i37 = strlen(p35)
diff --git a/pypy/module/sys/test/test_sysmodule.py b/pypy/module/sys/test/test_sysmodule.py
--- a/pypy/module/sys/test/test_sysmodule.py
+++ b/pypy/module/sys/test/test_sysmodule.py
@@ -567,6 +567,11 @@
         import time
         import thread
 
+        # XXX workaround for now: to prevent deadlocks, call
+        # sys._current_frames() once before starting threads.
+        # This is an issue in non-translated versions only.
+        sys._current_frames()
+
         thread_id = thread.get_ident()
         def other_thread():
             print "thread started"
diff --git a/pypy/module/test_lib_pypy/test_pwd.py b/pypy/module/test_lib_pypy/test_pwd.py
--- a/pypy/module/test_lib_pypy/test_pwd.py
+++ b/pypy/module/test_lib_pypy/test_pwd.py
@@ -1,7 +1,10 @@
+import py, sys
 from pypy.conftest import gettestobjspace
 
 class AppTestPwd:
     def setup_class(cls):
+        if sys.platform == 'win32':
+            py.test.skip("Unix only")
         cls.space = gettestobjspace(usemodules=('_ffi', '_rawffi'))
         cls.space.appexec((), "(): import pwd")
 
diff --git a/pypy/objspace/std/intobject.py b/pypy/objspace/std/intobject.py
--- a/pypy/objspace/std/intobject.py
+++ b/pypy/objspace/std/intobject.py
@@ -16,7 +16,10 @@
 something CPython does not do anymore.
 """
 
-class W_IntObject(W_Object):
+class W_AbstractIntObject(W_Object):
+    __slots__ = ()
+
+class W_IntObject(W_AbstractIntObject):
     __slots__ = 'intval'
     _immutable_fields_ = ['intval']
 
diff --git a/pypy/objspace/std/iterobject.py b/pypy/objspace/std/iterobject.py
--- a/pypy/objspace/std/iterobject.py
+++ b/pypy/objspace/std/iterobject.py
@@ -4,7 +4,10 @@
 from pypy.objspace.std.register_all import register_all
 
 
-class W_AbstractSeqIterObject(W_Object):
+class W_AbstractIterObject(W_Object):
+    __slots__ = ()
+
+class W_AbstractSeqIterObject(W_AbstractIterObject):
     from pypy.objspace.std.itertype import iter_typedef as typedef
 
     def __init__(w_self, w_seq, index=0):
diff --git a/pypy/objspace/std/listobject.py b/pypy/objspace/std/listobject.py
--- a/pypy/objspace/std/listobject.py
+++ b/pypy/objspace/std/listobject.py
@@ -11,7 +11,10 @@
 from pypy.rlib.listsort import make_timsort_class
 from pypy.interpreter.argument import Signature
 
-class W_ListObject(W_Object):
+class W_AbstractListObject(W_Object):
+    __slots__ = ()
+
+class W_ListObject(W_AbstractListObject):
     from pypy.objspace.std.listtype import list_typedef as typedef
 
     def __init__(w_self, wrappeditems):
diff --git a/pypy/objspace/std/longobject.py b/pypy/objspace/std/longobject.py
--- a/pypy/objspace/std/longobject.py
+++ b/pypy/objspace/std/longobject.py
@@ -8,7 +8,10 @@
 from pypy.objspace.std.noneobject import W_NoneObject
 from pypy.rlib.rbigint import rbigint, SHIFT
 
-class W_LongObject(W_Object):
+class W_AbstractLongObject(W_Object):
+    __slots__ = ()
+
+class W_LongObject(W_AbstractLongObject):
     """This is a wrapper of rbigint."""
     from pypy.objspace.std.longtype import long_typedef as typedef
     _immutable_fields_ = ['num']
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
@@ -88,12 +88,7 @@
         if self.config.objspace.std.withtproxy:
             transparent.setup(self)
 
-        interplevel_classes = {}
-        for type, classes in self.model.typeorder.iteritems():
-            if len(classes) >= 3: # XXX what does this 3 mean??!
-                # W_Root, AnyXxx and actual object
-                interplevel_classes[self.gettypefor(type)] = classes[0][0]
-        self._interplevel_classes = interplevel_classes
+        self.setup_isinstance_cache()
 
     def get_builtin_types(self):
         return self.builtin_types
@@ -600,6 +595,63 @@
     def isinstance_w(space, w_inst, w_type):
         return space._type_isinstance(w_inst, w_type)
 
+    def setup_isinstance_cache(self):
+        # This assumes that all classes in the stdobjspace implementing a
+        # particular app-level type are distinguished by a common base class.
+        # Alternatively, you can turn off the cache on specific classes,
+        # like e.g. proxyobject.  It is just a bit less performant but
+        # should not have any bad effect.
+        from pypy.objspace.std.model import W_Root, W_Object
+        #
+        # Build a dict {class: w_typeobject-or-None}.  The value None is used
+        # on classes that are known to be abstract base classes.
+        class2type = {}
+        class2type[W_Root] = None
+        class2type[W_Object] = None
+        for cls in self.model.typeorder.keys():
+            if getattr(cls, 'typedef', None) is None:
+                continue
+            if getattr(cls, 'ignore_for_isinstance_cache', False):
+                continue
+            w_type = self.gettypefor(cls)
+            w_oldtype = class2type.setdefault(cls, w_type)
+            assert w_oldtype is w_type
+        #
+        # Build the real dict {w_typeobject: class-or-base-class}.  For every
+        # w_typeobject we look for the most precise common base class of all
+        # the registered classes.  If no such class is found, we will find
+        # W_Object or W_Root, and complain.  Then you must either add an
+        # artificial common base class, or disable caching on one of the
+        # two classes with ignore_for_isinstance_cache.
+        def getmro(cls):
+            while True:
+                yield cls
+                if cls is W_Root:
+                    break
+                cls = cls.__bases__[0]
+        self._interplevel_classes = {}
+        for cls, w_type in class2type.items():
+            if w_type is None:
+                continue
+            if w_type not in self._interplevel_classes:
+                self._interplevel_classes[w_type] = cls
+            else:
+                cls1 = self._interplevel_classes[w_type]
+                mro1 = list(getmro(cls1))
+                for base in getmro(cls):
+                    if base in mro1:
+                        break
+                if base in class2type and class2type[base] is not w_type:
+                    if class2type.get(base) is None:
+                        msg = ("cannot find a common interp-level base class"
+                               " between %r and %r" % (cls1, cls))
+                    else:
+                        msg = ("%s is a base class of both %r and %r" % (
+                            class2type[base], cls1, cls))
+                    raise AssertionError("%r: %s" % (w_type, msg))
+                class2type[base] = w_type
+                self._interplevel_classes[w_type] = base
+
     @specialize.memo()
     def _get_interplevel_cls(self, w_type):
         if not hasattr(self, "_interplevel_classes"):
diff --git a/pypy/objspace/std/proxyobject.py b/pypy/objspace/std/proxyobject.py
--- a/pypy/objspace/std/proxyobject.py
+++ b/pypy/objspace/std/proxyobject.py
@@ -16,6 +16,8 @@
 def transparent_class(name, BaseCls):
 
     class W_Transparent(BaseCls):
+        ignore_for_isinstance_cache = True
+
         def __init__(self, space, w_type, w_controller):
             self.w_type = w_type
             self.w_controller = w_controller
diff --git a/pypy/objspace/std/ropeobject.py b/pypy/objspace/std/ropeobject.py
--- a/pypy/objspace/std/ropeobject.py
+++ b/pypy/objspace/std/ropeobject.py
@@ -6,7 +6,7 @@
 from pypy.rlib.objectmodel import we_are_translated
 from pypy.objspace.std.inttype import wrapint
 from pypy.objspace.std.sliceobject import W_SliceObject, normalize_simple_slice
-from pypy.objspace.std import slicetype
+from pypy.objspace.std import stringobject, slicetype, iterobject
 from pypy.objspace.std.listobject import W_ListObject
 from pypy.objspace.std.noneobject import W_NoneObject
 from pypy.objspace.std.tupleobject import W_TupleObject
@@ -17,7 +17,7 @@
 from pypy.objspace.std.stringobject import (
     _upper, _lower, DEFAULT_NOOP_TABLE)
 
-class W_RopeObject(W_Object):
+class W_RopeObject(stringobject.W_AbstractStringObject):
     from pypy.objspace.std.stringtype import str_typedef as typedef
     _immutable_fields_ = ['_node']
 
@@ -57,7 +57,7 @@
 
 registerimplementation(W_RopeObject)
 
-class W_RopeIterObject(W_Object):
+class W_RopeIterObject(iterobject.W_AbstractIterObject):
     from pypy.objspace.std.itertype import iter_typedef as typedef
 
     def __init__(w_self, w_rope, index=0):
diff --git a/pypy/objspace/std/ropeunicodeobject.py b/pypy/objspace/std/ropeunicodeobject.py
--- a/pypy/objspace/std/ropeunicodeobject.py
+++ b/pypy/objspace/std/ropeunicodeobject.py
@@ -9,7 +9,7 @@
 from pypy.objspace.std.noneobject import W_NoneObject
 from pypy.rlib import rope
 from pypy.objspace.std.sliceobject import W_SliceObject, normalize_simple_slice
-from pypy.objspace.std import slicetype
+from pypy.objspace.std import unicodeobject, slicetype, iterobject
 from pypy.objspace.std.tupleobject import W_TupleObject
 from pypy.rlib.rarithmetic import intmask, ovfcheck
 from pypy.module.unicodedata import unicodedb
@@ -63,7 +63,7 @@
     return encode_object(space, w_unistr, encoding, errors)
 
 
-class W_RopeUnicodeObject(W_Object):
+class W_RopeUnicodeObject(unicodeobject.W_AbstractUnicodeObject):
     from pypy.objspace.std.unicodetype import unicode_typedef as typedef
     _immutable_fields_ = ['_node']
 
@@ -99,7 +99,7 @@
     return rope.LiteralUnicodeNode(space.unicode_w(w_str))
 
 
-class W_RopeUnicodeIterObject(W_Object):
+class W_RopeUnicodeIterObject(iterobject.W_AbstractIterObject):
     from pypy.objspace.std.itertype import iter_typedef as typedef
 
     def __init__(w_self, w_rope, index=0):
diff --git a/pypy/objspace/std/smallintobject.py b/pypy/objspace/std/smallintobject.py
--- a/pypy/objspace/std/smallintobject.py
+++ b/pypy/objspace/std/smallintobject.py
@@ -6,7 +6,7 @@
 from pypy.objspace.std.model import registerimplementation, W_Object
 from pypy.objspace.std.register_all import register_all
 from pypy.objspace.std.noneobject import W_NoneObject
-from pypy.objspace.std.intobject import W_IntObject
+from pypy.objspace.std.intobject import W_AbstractIntObject, W_IntObject
 from pypy.interpreter.error import OperationError
 from pypy.rlib.objectmodel import UnboxedValue
 from pypy.rlib.rbigint import rbigint
@@ -14,7 +14,7 @@
 from pypy.tool.sourcetools import func_with_new_name
 from pypy.objspace.std.inttype import wrapint
 
-class W_SmallIntObject(W_Object, UnboxedValue):
+class W_SmallIntObject(W_AbstractIntObject, UnboxedValue):
     __slots__ = 'intval'
     from pypy.objspace.std.inttype import int_typedef as typedef
 
diff --git a/pypy/objspace/std/smalllongobject.py b/pypy/objspace/std/smalllongobject.py
--- a/pypy/objspace/std/smalllongobject.py
+++ b/pypy/objspace/std/smalllongobject.py
@@ -9,7 +9,7 @@
 from pypy.rlib.rarithmetic import r_longlong, r_int, r_uint
 from pypy.rlib.rarithmetic import intmask, LONGLONG_BIT
 from pypy.rlib.rbigint import rbigint
-from pypy.objspace.std.longobject import W_LongObject
+from pypy.objspace.std.longobject import W_AbstractLongObject, W_LongObject
 from pypy.objspace.std.intobject import W_IntObject
 from pypy.objspace.std.noneobject import W_NoneObject
 from pypy.interpreter.error import OperationError
@@ -17,7 +17,7 @@
 LONGLONG_MIN = r_longlong((-1) << (LONGLONG_BIT-1))
 
 
-class W_SmallLongObject(W_Object):
+class W_SmallLongObject(W_AbstractLongObject):
     from pypy.objspace.std.longtype import long_typedef as typedef
     _immutable_fields_ = ['longlong']
 
diff --git a/pypy/objspace/std/smalltupleobject.py b/pypy/objspace/std/smalltupleobject.py
--- a/pypy/objspace/std/smalltupleobject.py
+++ b/pypy/objspace/std/smalltupleobject.py
@@ -9,9 +9,9 @@
 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
+from pypy.objspace.std.tupleobject import W_AbstractTupleObject, W_TupleObject
 
-class W_SmallTupleObject(W_Object):
+class W_SmallTupleObject(W_AbstractTupleObject):
     from pypy.objspace.std.tupletype import tuple_typedef as typedef
 
     def tolist(self):
diff --git a/pypy/objspace/std/strbufobject.py b/pypy/objspace/std/strbufobject.py
--- a/pypy/objspace/std/strbufobject.py
+++ b/pypy/objspace/std/strbufobject.py
@@ -1,10 +1,11 @@
 from pypy.objspace.std.model import registerimplementation, W_Object
 from pypy.objspace.std.register_all import register_all
+from pypy.objspace.std.stringobject import W_AbstractStringObject
 from pypy.objspace.std.stringobject import W_StringObject
 from pypy.rlib.rstring import StringBuilder
 from pypy.interpreter.buffer import Buffer
 
-class W_StringBufferObject(W_Object):
+class W_StringBufferObject(W_AbstractStringObject):
     from pypy.objspace.std.stringtype import str_typedef as typedef
 
     w_str = None
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
@@ -18,7 +18,10 @@
 from pypy.objspace.std.stringtype import sliced, wrapstr, wrapchar, \
      stringendswith, stringstartswith, joined2
 
-class W_StringObject(W_Object):
+class W_AbstractStringObject(W_Object):
+    __slots__ = ()
+
+class W_StringObject(W_AbstractStringObject):
     from pypy.objspace.std.stringtype import str_typedef as typedef
     _immutable_fields_ = ['_value']
 
diff --git a/pypy/objspace/std/strjoinobject.py b/pypy/objspace/std/strjoinobject.py
--- a/pypy/objspace/std/strjoinobject.py
+++ b/pypy/objspace/std/strjoinobject.py
@@ -1,10 +1,11 @@
 from pypy.objspace.std.model import registerimplementation, W_Object
 from pypy.objspace.std.register_all import register_all
+from pypy.objspace.std.stringobject import W_AbstractStringObject
 from pypy.objspace.std.stringobject import W_StringObject
 
 from pypy.objspace.std.stringtype import wrapstr
 
-class W_StringJoinObject(W_Object):
+class W_StringJoinObject(W_AbstractStringObject):
     from pypy.objspace.std.stringtype import str_typedef as typedef
 
     def __init__(w_self, joined_strs, until=-1):
diff --git a/pypy/objspace/std/strsliceobject.py b/pypy/objspace/std/strsliceobject.py
--- a/pypy/objspace/std/strsliceobject.py
+++ b/pypy/objspace/std/strsliceobject.py
@@ -1,6 +1,7 @@
 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.stringobject import W_AbstractStringObject
 from pypy.objspace.std.stringobject import W_StringObject
 from pypy.objspace.std.sliceobject import W_SliceObject, normalize_simple_slice
 from pypy.objspace.std.tupleobject import W_TupleObject
@@ -11,7 +12,7 @@
      stringendswith, stringstartswith
 
 
-class W_StringSliceObject(W_Object):
+class W_StringSliceObject(W_AbstractStringObject):
     from pypy.objspace.std.stringtype import str_typedef as typedef
 
     def __init__(w_self, str, start, stop):
diff --git a/pypy/objspace/std/test/test_sliceobject.py b/pypy/objspace/std/test/test_sliceobject.py
--- a/pypy/objspace/std/test/test_sliceobject.py
+++ b/pypy/objspace/std/test/test_sliceobject.py
@@ -1,3 +1,4 @@
+import sys
 from pypy.objspace.std.sliceobject import normalize_simple_slice
 
 
@@ -56,8 +57,9 @@
                         sl = space.newslice(w(start), w(stop), w(step))
                         mystart, mystop, mystep, slicelength = sl.indices4(space, length)
                         assert len(range(length)[start:stop:step]) == slicelength
-                        assert slice(start, stop, step).indices(length) == (
-                                mystart, mystop, mystep)
+                        if sys.version_info >= (2, 6):   # doesn't work in 2.5
+                            assert slice(start, stop, step).indices(length) == (
+                                    mystart, mystop, mystep)
 
 class AppTest_SliceObject:
     def test_new(self):
diff --git a/pypy/objspace/std/test/test_stdobjspace.py b/pypy/objspace/std/test/test_stdobjspace.py
--- a/pypy/objspace/std/test/test_stdobjspace.py
+++ b/pypy/objspace/std/test/test_stdobjspace.py
@@ -50,6 +50,8 @@
     def test_fastpath_isinstance(self):
         from pypy.objspace.std.stringobject import W_StringObject
         from pypy.objspace.std.intobject import W_IntObject
+        from pypy.objspace.std.iterobject import W_AbstractSeqIterObject
+        from pypy.objspace.std.iterobject import W_SeqIterObject
 
         space = self.space
         assert space._get_interplevel_cls(space.w_str) is W_StringObject
@@ -62,9 +64,13 @@
 
         assert space.isinstance_w(X(), space.w_str)
 
+        w_sequenceiterator = space.gettypefor(W_SeqIterObject)
+        cls = space._get_interplevel_cls(w_sequenceiterator)
+        assert cls is W_AbstractSeqIterObject
+
     def test_withstrbuf_fastpath_isinstance(self):
-        from pypy.objspace.std.stringobject import W_StringObject
+        from pypy.objspace.std.stringobject import W_AbstractStringObject
 
-        space = gettestobjspace(withstrbuf=True) 
-        assert space._get_interplevel_cls(space.w_str) is W_StringObject
-        
+        space = gettestobjspace(withstrbuf=True)
+        cls = space._get_interplevel_cls(space.w_str)
+        assert cls is W_AbstractStringObject
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
@@ -9,7 +9,10 @@
 from pypy.interpreter import gateway
 from pypy.rlib.debug import make_sure_not_resized
 
-class W_TupleObject(W_Object):
+class W_AbstractTupleObject(W_Object):
+    __slots__ = ()
+
+class W_TupleObject(W_AbstractTupleObject):
     from pypy.objspace.std.tupletype import tuple_typedef as typedef
     _immutable_fields_ = ['wrappeditems[*]']
 
diff --git a/pypy/objspace/std/unicodeobject.py b/pypy/objspace/std/unicodeobject.py
--- a/pypy/objspace/std/unicodeobject.py
+++ b/pypy/objspace/std/unicodeobject.py
@@ -18,7 +18,10 @@
 from pypy.objspace.std.formatting import mod_format
 from pypy.objspace.std.stringtype import stringstartswith, stringendswith
 
-class W_UnicodeObject(W_Object):
+class W_AbstractUnicodeObject(W_Object):
+    __slots__ = ()
+
+class W_UnicodeObject(W_AbstractUnicodeObject):
     from pypy.objspace.std.unicodetype import unicode_typedef as typedef
     _immutable_fields_ = ['_value']
 
diff --git a/pypy/rlib/_rffi_stacklet.py b/pypy/rlib/_rffi_stacklet.py
--- a/pypy/rlib/_rffi_stacklet.py
+++ b/pypy/rlib/_rffi_stacklet.py
@@ -3,16 +3,27 @@
 from pypy.rpython.lltypesystem import lltype, llmemory, rffi
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
 from pypy.rpython.tool import rffi_platform
+import sys
 
 
 cdir = py.path.local(pypydir) / 'translator' / 'c'
 
-
 eci = ExternalCompilationInfo(
     include_dirs = [cdir],
     includes = ['src/stacklet/stacklet.h'],
     separate_module_sources = ['#include "src/stacklet/stacklet.c"\n'],
 )
+if sys.platform == 'win32':
+    eci.separate_module_files += (cdir / "src/stacklet/switch_x86_msvc.asm", )
+    eci.export_symbols += (
+        'stacklet_newthread',
+        'stacklet_deletethread',
+        'stacklet_new',
+        'stacklet_switch',
+        'stacklet_destroy',
+        '_stacklet_translate_pointer',
+        )
+
 rffi_platform.verify_eci(eci.convert_sources_to_files())
 
 def llexternal(name, args, result, **kwds):
diff --git a/pypy/rlib/clibffi.py b/pypy/rlib/clibffi.py
--- a/pypy/rlib/clibffi.py
+++ b/pypy/rlib/clibffi.py
@@ -30,9 +30,6 @@
 _MAC_OS = platform.name == "darwin"
 _FREEBSD_7 = platform.name == "freebsd7"
 
-_LITTLE_ENDIAN = sys.byteorder == 'little'
-_BIG_ENDIAN = sys.byteorder == 'big'
-
 if _WIN32:
     from pypy.rlib import rwin32
 
@@ -213,26 +210,48 @@
     elif sz == 8: return ffi_type_uint64
     else: raise ValueError("unsupported type size for %r" % (TYPE,))
 
-TYPE_MAP = {
-    rffi.DOUBLE : ffi_type_double,
-    rffi.FLOAT  : ffi_type_float,
-    rffi.LONGDOUBLE : ffi_type_longdouble,
-    rffi.UCHAR  : ffi_type_uchar,
-    rffi.CHAR   : ffi_type_schar,
-    rffi.SHORT  : ffi_type_sshort,
-    rffi.USHORT : ffi_type_ushort,
-    rffi.UINT   : ffi_type_uint,
-    rffi.INT    : ffi_type_sint,
+__int_type_map = [
+    (rffi.UCHAR, ffi_type_uchar),
+    (rffi.SIGNEDCHAR, ffi_type_schar),
+    (rffi.SHORT, ffi_type_sshort),
+    (rffi.USHORT, ffi_type_ushort),
+    (rffi.UINT, ffi_type_uint),
+    (rffi.INT, ffi_type_sint),
     # xxx don't use ffi_type_slong and ffi_type_ulong - their meaning
     # changes from a libffi version to another :-((
-    rffi.ULONG     : _unsigned_type_for(rffi.ULONG),
-    rffi.LONG      : _signed_type_for(rffi.LONG),
-    rffi.ULONGLONG : _unsigned_type_for(rffi.ULONGLONG),
-    rffi.LONGLONG  : _signed_type_for(rffi.LONGLONG),
-    lltype.Void    : ffi_type_void,
-    lltype.UniChar : _unsigned_type_for(lltype.UniChar),
-    lltype.Bool    : _unsigned_type_for(lltype.Bool),
-    }
+    (rffi.ULONG, _unsigned_type_for(rffi.ULONG)),
+    (rffi.LONG, _signed_type_for(rffi.LONG)),
+    (rffi.ULONGLONG, _unsigned_type_for(rffi.ULONGLONG)),
+    (rffi.LONGLONG, _signed_type_for(rffi.LONGLONG)),
+    (lltype.UniChar, _unsigned_type_for(lltype.UniChar)),
+    (lltype.Bool, _unsigned_type_for(lltype.Bool)),
+    ]
+
+__float_type_map = [
+    (rffi.DOUBLE, ffi_type_double),
+    (rffi.FLOAT, ffi_type_float),
+    (rffi.LONGDOUBLE, ffi_type_longdouble),
+    ]
+
+__ptr_type_map = [
+    (rffi.VOIDP, ffi_type_pointer),
+    ]
+
+__type_map = __int_type_map + __float_type_map + [
+    (lltype.Void, ffi_type_void)
+    ]
+
+TYPE_MAP_INT = dict(__int_type_map)
+TYPE_MAP_FLOAT = dict(__float_type_map)
+TYPE_MAP = dict(__type_map)
+
+ffitype_map_int = unrolling_iterable(__int_type_map)
+ffitype_map_int_or_ptr = unrolling_iterable(__int_type_map + __ptr_type_map)
+ffitype_map_float = unrolling_iterable(__float_type_map)
+ffitype_map = unrolling_iterable(__type_map)
+
+del __int_type_map, __float_type_map, __ptr_type_map, __type_map
+
 
 def external(name, args, result, **kwds):
     return rffi.llexternal(name, args, result, compilation_info=eci, **kwds)
@@ -341,38 +360,15 @@
 cast_type_to_ffitype._annspecialcase_ = 'specialize:memo'
 
 def push_arg_as_ffiptr(ffitp, arg, ll_buf):
-    # This is for primitive types.  Note that the exact type of 'arg' may be
-    # different from the expected 'c_size'.  To cope with that, we fall back
-    # to a byte-by-byte copy.
+    # this is for primitive types. For structures and arrays
+    # would be something different (more dynamic)
     TP = lltype.typeOf(arg)
     TP_P = lltype.Ptr(rffi.CArray(TP))
-    TP_size = rffi.sizeof(TP)
-    c_size = intmask(ffitp.c_size)
-    # if both types have the same size, we can directly write the
-    # value to the buffer
-    if c_size == TP_size:
-        buf = rffi.cast(TP_P, ll_buf)
-        buf[0] = arg
-    else:
-        # needs byte-by-byte copying.  Make sure 'arg' is an integer type.
-        # Note that this won't work for rffi.FLOAT/rffi.DOUBLE.
-        assert TP is not rffi.FLOAT and TP is not rffi.DOUBLE
-        if TP_size <= rffi.sizeof(lltype.Signed):
-            arg = rffi.cast(lltype.Unsigned, arg)
-        else:
-            arg = rffi.cast(lltype.UnsignedLongLong, arg)
-        if _LITTLE_ENDIAN:
-            for i in range(c_size):
-                ll_buf[i] = chr(arg & 0xFF)
-                arg >>= 8
-        elif _BIG_ENDIAN:
-            for i in range(c_size-1, -1, -1):
-                ll_buf[i] = chr(arg & 0xFF)
-                arg >>= 8
-        else:
-            raise AssertionError
+    buf = rffi.cast(TP_P, ll_buf)
+    buf[0] = arg
 push_arg_as_ffiptr._annspecialcase_ = 'specialize:argtype(1)'
 
+
 # type defs for callback and closure userdata
 USERDATA_P = lltype.Ptr(lltype.ForwardReference())
 CALLBACK_TP = lltype.Ptr(lltype.FuncType([rffi.VOIDPP, rffi.VOIDP, USERDATA_P],
diff --git a/pypy/rlib/jit.py b/pypy/rlib/jit.py
--- a/pypy/rlib/jit.py
+++ b/pypy/rlib/jit.py
@@ -450,55 +450,6 @@
         # special-cased by ExtRegistryEntry
         pass
 
-    def _set_param(self, name, value):
-        # special-cased by ExtRegistryEntry
-        # (internal, must receive a constant 'name')
-        # if value is DEFAULT, sets the default value.
-        assert name in PARAMETERS
-
-    @specialize.arg(0, 1)
-    def set_param(self, name, value):
-        """Set one of the tunable JIT parameter."""
-        self._set_param(name, value)
-
-    @specialize.arg(0, 1)
-    def set_param_to_default(self, name):
-        """Reset one of the tunable JIT parameters to its default value."""
-        self._set_param(name, DEFAULT)
-
-    def set_user_param(self, text):
-        """Set the tunable JIT parameters from a user-supplied string
-        following the format 'param=value,param=value', or 'off' to
-        disable the JIT.  For programmatic setting of parameters, use
-        directly JitDriver.set_param().
-        """
-        if text == 'off':
-            self.set_param('threshold', -1)
-            self.set_param('function_threshold', -1)
-            return
-        if text == 'default':
-            for name1, _ in unroll_parameters:
-                self.set_param_to_default(name1)
-            return
-        for s in text.split(','):
-            s = s.strip(' ')
-            parts = s.split('=')
-            if len(parts) != 2:
-                raise ValueError
-            name = parts[0]
-            value = parts[1]
-            if name == 'enable_opts':
-                self.set_param('enable_opts', value)
-            else:
-                for name1, _ in unroll_parameters:
-                    if name1 == name and name1 != 'enable_opts':
-                        try:
-                            self.set_param(name1, int(value))
-                        except ValueError:
-                            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
@@ -524,16 +475,61 @@
         self.jit_merge_point = self.jit_merge_point
         self.can_enter_jit = self.can_enter_jit
         self.loop_header = self.loop_header
-        self._set_param = self._set_param
-
         class Entry(ExtEnterLeaveMarker):
             _about_ = (self.jit_merge_point, self.can_enter_jit)
 
         class Entry(ExtLoopHeader):
             _about_ = self.loop_header
 
-        class Entry(ExtSetParam):
-            _about_ = self._set_param
+def _set_param(driver, name, value):
+    # special-cased by ExtRegistryEntry
+    # (internal, must receive a constant 'name')
+    # if value is DEFAULT, sets the default value.
+    assert name in PARAMETERS
+
+ at specialize.arg(0, 1)
+def set_param(driver, name, value):
+    """Set one of the tunable JIT parameter. Driver can be None, then all
+    drivers have this set """
+    _set_param(driver, name, value)
+
+ at specialize.arg(0, 1)
+def set_param_to_default(driver, name):
+    """Reset one of the tunable JIT parameters to its default value."""
+    _set_param(driver, name, DEFAULT)
+
+def set_user_param(driver, text):
+    """Set the tunable JIT parameters from a user-supplied string
+    following the format 'param=value,param=value', or 'off' to
+    disable the JIT.  For programmatic setting of parameters, use
+    directly JitDriver.set_param().
+    """
+    if text == 'off':
+        set_param(driver, 'threshold', -1)
+        set_param(driver, 'function_threshold', -1)
+        return
+    if text == 'default':
+        for name1, _ in unroll_parameters:
+            set_param_to_default(driver, name1)
+        return
+    for s in text.split(','):
+        s = s.strip(' ')
+        parts = s.split('=')
+        if len(parts) != 2:
+            raise ValueError
+        name = parts[0]
+        value = parts[1]
+        if name == 'enable_opts':
+            set_param(driver, 'enable_opts', value)
+        else:
+            for name1, _ in unroll_parameters:
+                if name1 == name and name1 != 'enable_opts':
+                    try:
+                        set_param(driver, name1, int(value))
+                    except ValueError:
+                        raise
+set_user_param._annspecialcase_ = 'specialize:arg(0)'
+
 
 # ____________________________________________________________
 #
@@ -705,8 +701,9 @@
                          resulttype=lltype.Void)
 
 class ExtSetParam(ExtRegistryEntry):
+    _about_ = _set_param
 
-    def compute_result_annotation(self, s_name, s_value):
+    def compute_result_annotation(self, s_driver, s_name, s_value):
         from pypy.annotation import model as annmodel
         assert s_name.is_constant()
         if not self.bookkeeper.immutablevalue(DEFAULT).contains(s_value):
@@ -722,21 +719,22 @@
         from pypy.objspace.flow.model import Constant
 
         hop.exception_cannot_occur()
-        driver = self.instance.im_self
-        name = hop.args_s[0].const
+        driver = hop.inputarg(lltype.Void, arg=0)
+        name = hop.args_s[1].const
         if name == 'enable_opts':
             repr = string_repr
         else:
             repr = lltype.Signed
-        if (isinstance(hop.args_v[1], Constant) and
-            hop.args_v[1].value is DEFAULT):
+        if (isinstance(hop.args_v[2], Constant) and
+            hop.args_v[2].value is DEFAULT):
             value = PARAMETERS[name]
             v_value = hop.inputconst(repr, value)
         else:
-            v_value = hop.inputarg(repr, arg=1)
+            v_value = hop.inputarg(repr, arg=2)
         vlist = [hop.inputconst(lltype.Void, "set_param"),
-                 hop.inputconst(lltype.Void, driver),
+                 driver,
                  hop.inputconst(lltype.Void, name),
                  v_value]
         return hop.genop('jit_marker', vlist,
                          resulttype=lltype.Void)
+
diff --git a/pypy/rlib/libffi.py b/pypy/rlib/libffi.py
--- a/pypy/rlib/libffi.py
+++ b/pypy/rlib/libffi.py
@@ -140,7 +140,7 @@
             self.last.next = arg
             self.last = arg
         self.numargs += 1
-    
+
 
 class AbstractArg(object):
     next = None
@@ -410,3 +410,22 @@
 
     def getaddressindll(self, name):
         return dlsym(self.lib, name)
+
+ at jit.oopspec("libffi_array_getitem(ffitype, width, addr, index, offset)")
+def array_getitem(ffitype, width, addr, index, offset):
+    for TYPE, ffitype2 in clibffi.ffitype_map:
+        if ffitype is ffitype2:
+            addr = rffi.ptradd(addr, index * width)
+            addr = rffi.ptradd(addr, offset)
+            return rffi.cast(rffi.CArrayPtr(TYPE), addr)[0]
+    assert False
+
+ at jit.oopspec("libffi_array_setitem(ffitype, width, addr, index, offset, value)")
+def array_setitem(ffitype, width, addr, index, offset, value):
+    for TYPE, ffitype2 in clibffi.ffitype_map:
+        if ffitype is ffitype2:
+            addr = rffi.ptradd(addr, index * width)
+            addr = rffi.ptradd(addr, offset)
+            rffi.cast(rffi.CArrayPtr(TYPE), addr)[0] = value
+            return
+    assert False
\ No newline at end of file
diff --git a/pypy/rlib/test/test_libffi.py b/pypy/rlib/test/test_libffi.py
--- a/pypy/rlib/test/test_libffi.py
+++ b/pypy/rlib/test/test_libffi.py
@@ -1,11 +1,13 @@
+import sys
+
 import py
-import sys
+
+from pypy.rlib.libffi import (CDLL, Func, get_libc_name, ArgChain, types,
+    IS_32_BIT, array_getitem, array_setitem)
+from pypy.rlib.rarithmetic import r_singlefloat, r_longlong, r_ulonglong
+from pypy.rlib.test.test_clibffi import BaseFfiTest, get_libm_name, make_struct_ffitype_e
 from pypy.rpython.lltypesystem import rffi, lltype
 from pypy.rpython.lltypesystem.ll2ctypes import ALLOCATED
-from pypy.rlib.rarithmetic import r_singlefloat, r_longlong, r_ulonglong
-from pypy.rlib.test.test_clibffi import BaseFfiTest, get_libm_name, make_struct_ffitype_e
-from pypy.rlib.libffi import CDLL, Func, get_libc_name, ArgChain, types
-from pypy.rlib.libffi import IS_32_BIT
 
 class TestLibffiMisc(BaseFfiTest):
 
@@ -52,6 +54,34 @@
         del lib
         assert not ALLOCATED
 
+    def test_array_fields(self):
+        POINT = lltype.Struct("POINT",
+            ("x", lltype.Float),
+            ("y", lltype.Float),
+        )
+        points = lltype.malloc(rffi.CArray(POINT), 2, flavor="raw")
+        points[0].x = 1.0
+        points[0].y = 2.0
+        points[1].x = 3.0
+        points[1].y = 4.0
+        points = rffi.cast(rffi.CArrayPtr(lltype.Char), points)
+        assert array_getitem(types.double, 16, points, 0, 0) == 1.0
+        assert array_getitem(types.double, 16, points, 0, 8) == 2.0
+        assert array_getitem(types.double, 16, points, 1, 0) == 3.0
+        assert array_getitem(types.double, 16, points, 1, 8) == 4.0
+
+        array_setitem(types.double, 16, points, 0, 0, 10.0)
+        array_setitem(types.double, 16, points, 0, 8, 20.0)
+        array_setitem(types.double, 16, points, 1, 0, 30.0)
+        array_setitem(types.double, 16, points, 1, 8, 40.0)
+
+        assert array_getitem(types.double, 16, points, 0, 0) == 10.0
+        assert array_getitem(types.double, 16, points, 0, 8) == 20.0
+        assert array_getitem(types.double, 16, points, 1, 0) == 30.0
+        assert array_getitem(types.double, 16, points, 1, 8) == 40.0
+
+        lltype.free(points, flavor="raw")
+
 class TestLibffiCall(BaseFfiTest):
     """
     Test various kind of calls through libffi.
@@ -109,7 +139,7 @@
         This method is overridden by metainterp/test/test_fficall.py in
         order to do the call in a loop and JIT it. The optional arguments are
         used only by that overridden method.
-        
+
         """
         lib, name, argtypes, restype = funcspec
         func = lib.getpointer(name, argtypes, restype)
@@ -132,7 +162,7 @@
                 return x - y;
             }
         """
-        libfoo = self.get_libfoo() 
+        libfoo = self.get_libfoo()
         func = (libfoo, 'diff_xy', [types.sint, types.slong], types.sint)
         res = self.call(func, [50, 8], lltype.Signed)
         assert res == 42
@@ -144,7 +174,7 @@
                 return (x + (int)y);
             }
         """
-        libfoo = self.get_libfoo() 
+        libfoo = self.get_libfoo()
         func = (libfoo, 'sum_xy', [types.sint, types.double], types.sint)
         res = self.call(func, [38, 4.2], lltype.Signed, jitif=["floats"])
         assert res == 42
@@ -249,7 +279,7 @@
             };
 
             struct pair my_static_pair = {10, 20};
-            
+
             long* get_pointer_to_b()
             {
                 return &my_static_pair.b;
@@ -340,7 +370,7 @@
 
     def test_wrong_number_of_arguments(self):
         from pypy.rpython.llinterp import LLException
-        libfoo = self.get_libfoo() 
+        libfoo = self.get_libfoo()
         func = (libfoo, 'sum_xy', [types.sint, types.double], types.sint)
 
         glob = globals()
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
@@ -1723,7 +1723,7 @@
 class _subarray(_parentable):     # only for direct_fieldptr()
                                   # and direct_arrayitems()
     _kind = "subarray"
-    _cache = weakref.WeakKeyDictionary()  # parentarray -> {subarrays}
+    _cache = {}  # TYPE -> weak{ parentarray -> {subarrays} }
 
     def __init__(self, TYPE, parent, baseoffset_or_fieldname):
         _parentable.__init__(self, TYPE)
@@ -1781,10 +1781,15 @@
 
     def _makeptr(parent, baseoffset_or_fieldname, solid=False):
         try:
-            cache = _subarray._cache.setdefault(parent, {})
+            d = _subarray._cache[parent._TYPE]
+        except KeyError:
+            d = _subarray._cache[parent._TYPE] = weakref.WeakKeyDictionary()
+        try:
+            cache = d.setdefault(parent, {})
         except RuntimeError:    # pointer comparison with a freed structure
             _subarray._cleanup_cache()
-            cache = _subarray._cache.setdefault(parent, {})    # try again
+            # try again
+            return _subarray._makeptr(parent, baseoffset_or_fieldname, solid)
         try:
             subarray = cache[baseoffset_or_fieldname]
         except KeyError:
@@ -1805,14 +1810,18 @@
         raise NotImplementedError('_subarray._getid()')
 
     def _cleanup_cache():
-        newcache = weakref.WeakKeyDictionary()
-        for key, value in _subarray._cache.items():
-            try:
-                if not key._was_freed():
-                    newcache[key] = value
-            except RuntimeError:
-                pass    # ignore "accessing subxxx, but already gc-ed parent"
-        _subarray._cache = newcache
+        for T, d in _subarray._cache.items():
+            newcache = weakref.WeakKeyDictionary()
+            for key, value in d.items():
+                try:
+                    if not key._was_freed():
+                        newcache[key] = value
+                except RuntimeError:
+                    pass    # ignore "accessing subxxx, but already gc-ed parent"
+            if newcache:
+                _subarray._cache[T] = newcache
+            else:
+                del _subarray._cache[T]
     _cleanup_cache = staticmethod(_cleanup_cache)
 
 
diff --git a/pypy/rpython/lltypesystem/module/ll_math.py b/pypy/rpython/lltypesystem/module/ll_math.py
--- a/pypy/rpython/lltypesystem/module/ll_math.py
+++ b/pypy/rpython/lltypesystem/module/ll_math.py
@@ -127,9 +127,12 @@
     return y != y
 
 def ll_math_isinf(y):
-    if use_library_isinf_isnan and not jit.we_are_jitted():
+    if jit.we_are_jitted():
+        return (y + VERY_LARGE_FLOAT) == y
+    elif use_library_isinf_isnan:
         return not _lib_finite(y) and not _lib_isnan(y)
-    return (y + VERY_LARGE_FLOAT) == y
+    else:
+        return y == INFINITY or y == -INFINITY
 
 def ll_math_isfinite(y):
     # Use a custom hack that is reasonably well-suited to the JIT.
diff --git a/pypy/rpython/lltypesystem/rbuilder.py b/pypy/rpython/lltypesystem/rbuilder.py
--- a/pypy/rpython/lltypesystem/rbuilder.py
+++ b/pypy/rpython/lltypesystem/rbuilder.py
@@ -123,9 +123,10 @@
     def ll_build(ll_builder):
         final_size = ll_builder.used
         assert final_size >= 0
-        if final_size == ll_builder.allocated:
-            return ll_builder.buf
-        return rgc.ll_shrink_array(ll_builder.buf, final_size)
+        if final_size < ll_builder.allocated:
+            ll_builder.allocated = final_size
+            ll_builder.buf = rgc.ll_shrink_array(ll_builder.buf, final_size)
+        return ll_builder.buf
 
     @classmethod
     def ll_is_true(cls, ll_builder):
diff --git a/pypy/rpython/lltypesystem/rffi.py b/pypy/rpython/lltypesystem/rffi.py
--- a/pypy/rpython/lltypesystem/rffi.py
+++ b/pypy/rpython/lltypesystem/rffi.py
@@ -862,12 +862,14 @@
     try:
         unsigned = not tp._type.SIGNED
     except AttributeError:
-        if (not isinstance(tp, lltype.Primitive) or
-            tp in (FLOAT, DOUBLE) or
-            cast(lltype.SignedLongLong, cast(tp, -1)) < 0):
+        if not isinstance(tp, lltype.Primitive):
             unsigned = False
+        elif tp in (lltype.Signed, FLOAT, DOUBLE, llmemory.Address):
+            unsigned = False
+        elif tp in (lltype.Char, lltype.UniChar, lltype.Bool):
+            unsigned = True
         else:
-            unsigned = True
+            raise AssertionError("size_and_sign(%r)" % (tp,))
     return size, unsigned
 
 def sizeof(tp):
diff --git a/pypy/rpython/lltypesystem/rstr.py b/pypy/rpython/lltypesystem/rstr.py
--- a/pypy/rpython/lltypesystem/rstr.py
+++ b/pypy/rpython/lltypesystem/rstr.py
@@ -331,6 +331,8 @@
         # unlike CPython, there is no reason to avoid to return -1
         # but our malloc initializes the memory to zero, so we use zero as the
         # special non-computed-yet value.
+        if not s:
+            return 0
         x = s.hash
         if x == 0:
             x = _hash_string(s.chars)
diff --git a/pypy/rpython/lltypesystem/test/test_rffi.py b/pypy/rpython/lltypesystem/test/test_rffi.py
--- a/pypy/rpython/lltypesystem/test/test_rffi.py
+++ b/pypy/rpython/lltypesystem/test/test_rffi.py
@@ -743,8 +743,9 @@
             assert sizeof(lltype.Typedef(ll, 'test')) == sizeof(ll)
         assert not size_and_sign(lltype.Signed)[1]
         assert size_and_sign(lltype.Char) == (1, True)
-        assert not size_and_sign(lltype.UniChar)[1]
+        assert size_and_sign(lltype.UniChar)[1]
         assert size_and_sign(UINT)[1]
+        assert not size_and_sign(INT)[1]
     
     def test_rffi_offsetof(self):
         import struct
diff --git a/pypy/rpython/ootypesystem/rstr.py b/pypy/rpython/ootypesystem/rstr.py
--- a/pypy/rpython/ootypesystem/rstr.py
+++ b/pypy/rpython/ootypesystem/rstr.py
@@ -116,6 +116,8 @@
         return ootype.oounicode(ch, -1)
 
     def ll_strhash(s):
+        if not s:
+            return 0
         return s.ll_hash()
 
     def ll_strfasthash(s):
diff --git a/pypy/rpython/test/test_rbuilder.py b/pypy/rpython/test/test_rbuilder.py
--- a/pypy/rpython/test/test_rbuilder.py
+++ b/pypy/rpython/test/test_rbuilder.py
@@ -1,3 +1,4 @@
+from __future__ import with_statement
 import py
 
 from pypy.rlib.rstring import StringBuilder, UnicodeBuilder
diff --git a/pypy/rpython/test/test_rclass.py b/pypy/rpython/test/test_rclass.py
--- a/pypy/rpython/test/test_rclass.py
+++ b/pypy/rpython/test/test_rclass.py
@@ -457,12 +457,16 @@
                     compute_identity_hash(d))
 
         res = self.interpret(f, [])
-        # xxx this is too precise, checking the exact implementation
-        assert res.item0 == res.item1
+        # xxx the following test is too precise, checking the exact
+        # implementation.  On Python 2.7 it doesn't work anyway, because
+        # object.__hash__(x) is different from id(x).  The test is disabled
+        # for now, and nobody should rely on compute_identity_hash() returning
+        # a value that is (or was) the current_object_addr_as_int().
+        # --- disabled: assert res.item0 == res.item1
         # the following property is essential on top of the lltypesystem
         # otherwise prebuilt dictionaries are broken.  It's wrong on
         # top of the ootypesystem though.
-        if type(self) is TestLLtype:
+        if isinstance(self, LLRtypeMixin):
             assert res.item2 == h_c
             assert res.item3 == h_d
 
diff --git a/pypy/rpython/test/test_rtuple.py b/pypy/rpython/test/test_rtuple.py
--- a/pypy/rpython/test/test_rtuple.py
+++ b/pypy/rpython/test/test_rtuple.py
@@ -180,6 +180,19 @@
         res2 = self.interpret(f, [27, 12])
         assert res1 != res2
 
+    def test_constant_tuple_hash_str(self):
+        from pypy.rlib.objectmodel import compute_hash
+        def f(i):
+            if i:
+                t = (None, "abc")
+            else:
+                t = ("abc", None)
+            return compute_hash(t)
+
+        res1 = self.interpret(f, [0])
+        res2 = self.interpret(f, [1])
+        assert res1 != res2
+
     def test_tuple_to_list(self):
         def f(i, j):
             return list((i, j))
diff --git a/pypy/translator/c/test/test_newgc.py b/pypy/translator/c/test/test_newgc.py
--- a/pypy/translator/c/test/test_newgc.py
+++ b/pypy/translator/c/test/test_newgc.py
@@ -1318,6 +1318,23 @@
         res = self.run('string_builder_over_allocation')
         assert res[1000] == 'y'
 
+    def definestr_string_builder_multiple_builds(cls):
+        import gc
+        def fn(_):
+            s = StringBuilder(4)
+            got = []
+            for i in range(50):
+                s.append(chr(33+i))
+                got.append(s.build())
+                gc.collect()
+            return ' '.join(got)
+        return fn
+
+    def test_string_builder_multiple_builds(self):
+        res = self.run('string_builder_multiple_builds')
+        assert res == ' '.join([''.join(map(chr, range(33, 33+length)))
+                                for length in range(1, 51)])
+
     def define_nursery_hash_base(cls):
         from pypy.rlib.objectmodel import compute_identity_hash
         class A:
diff --git a/pypy/translator/platform/__init__.py b/pypy/translator/platform/__init__.py
--- a/pypy/translator/platform/__init__.py
+++ b/pypy/translator/platform/__init__.py
@@ -42,6 +42,8 @@
 
     so_prefixes = ('',)
 
+    extra_libs = ()
+
     def __init__(self, cc):
         if self.__class__ is Platform:
             raise TypeError("You should not instantiate Platform class directly")
@@ -57,7 +59,11 @@
         compile_args = self._compile_args_from_eci(eci, standalone)
         ofiles = []
         for cfile in cfiles:
-            ofiles.append(self._compile_c_file(self.cc, cfile, compile_args))
+            # Windows hack: use masm for files ending in .asm
+            if str(cfile).lower().endswith('.asm'):
+                ofiles.append(self._compile_c_file(self.masm, cfile, []))
+            else:
+                ofiles.append(self._compile_c_file(self.cc, cfile, compile_args))
         return ofiles
 
     def execute(self, executable, args=None, env=None, compilation_info=None):
@@ -181,7 +187,8 @@
         link_files = self._linkfiles(eci.link_files)
         export_flags = self._exportsymbols_link_flags(eci)
         return (library_dirs + list(self.link_flags) + export_flags +
-                link_files + list(eci.link_extra) + libraries)
+                link_files + list(eci.link_extra) + libraries +
+                list(self.extra_libs))
 
     def _exportsymbols_link_flags(self, eci, relto=None):
         if eci.export_symbols:
diff --git a/pypy/translator/platform/linux.py b/pypy/translator/platform/linux.py
--- a/pypy/translator/platform/linux.py
+++ b/pypy/translator/platform/linux.py
@@ -6,7 +6,8 @@
 class BaseLinux(BasePosix):
     name = "linux"
     
-    link_flags = ('-pthread', '-lrt')
+    link_flags = ('-pthread',)
+    extra_libs = ('-lrt',)
     cflags = ('-O3', '-pthread', '-fomit-frame-pointer',
               '-Wall', '-Wno-unused')
     standalone_only = ()
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
@@ -140,7 +140,7 @@
             ('DEFAULT_TARGET', exe_name.basename),
             ('SOURCES', rel_cfiles),
             ('OBJECTS', rel_ofiles),
-            ('LIBS', self._libs(eci.libraries)),
+            ('LIBS', self._libs(eci.libraries) + list(self.extra_libs)),
             ('LIBDIRS', self._libdirs(rel_libdirs)),
             ('INCLUDEDIRS', self._includedirs(rel_includedirs)),
             ('CFLAGS', cflags),
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
@@ -41,6 +41,7 @@
         if self.strict_on_stderr:
             assert res.err == ''
         assert res.returncode == 0
+        assert '-lrt' in tmpdir.join("Makefile").read()
 
     def test_link_files(self):
         tmpdir = udir.join('link_files' + self.__class__.__name__).ensure(dir=1)
diff --git a/pypy/translator/platform/windows.py b/pypy/translator/platform/windows.py
--- a/pypy/translator/platform/windows.py
+++ b/pypy/translator/platform/windows.py
@@ -71,6 +71,8 @@
     so_ext = 'dll'
     exe_ext = 'exe'
 
+    relevant_environ = ('PATH', 'INCLUDE', 'LIB')
+
     cc = 'cl.exe'
     link = 'link.exe'
 
@@ -80,7 +82,7 @@
     shared_only = ()
     environ = None
 
-    def __init__(self, cc=None):
+    def __init__(self, cc=None, x64=False):
         Platform.__init__(self, 'cl.exe')
         if msvc_compiler_environ:
             self.c_environ = os.environ.copy()
@@ -103,9 +105,16 @@
                                                      env=self.c_environ)
         r = re.search('Macro Assembler', stderr)
         if r is None and os.path.exists('c:/masm32/bin/ml.exe'):
-            self.masm = 'c:/masm32/bin/ml.exe'
+            masm32 = 'c:/masm32/bin/ml.exe'
+            masm64 = 'c:/masm64/bin/ml64.exe'
         else:
-            self.masm = 'ml.exe'
+            masm32 = 'ml.exe'
+            masm64 = 'ml64.exe'
+        
+        if x64:
+            self.masm = masm64
+        else:
+            self.masm = masm32
 
         # Install debug options only when interpreter is in debug mode
         if sys.executable.lower().endswith('_d.exe'):
@@ -165,7 +174,13 @@
 
     def _compile_c_file(self, cc, cfile, compile_args):
         oname = cfile.new(ext='obj')
-        args = ['/nologo', '/c'] + compile_args + [str(cfile), '/Fo%s' % (oname,)]
+        # notabene: (tismer)
+        # This function may be called for .c but also .asm files.
+        # The c compiler accepts any order of arguments, while
+        # the assembler still has the old behavior that all options
+        # must come first, and after the file name all options are ignored.
+        # So please be careful with the oder of parameters! ;-)
+        args = ['/nologo', '/c'] + compile_args + ['/Fo%s' % (oname,), str(cfile)]
         self._execute_c_compiler(cc, args, oname)
         return oname
 
diff --git a/pypy/translator/simplify.py b/pypy/translator/simplify.py
--- a/pypy/translator/simplify.py
+++ b/pypy/translator/simplify.py
@@ -697,10 +697,12 @@
             if op.opname == 'getattr' and op.args[1] == c_append:
                 vlist = variable_families.find_rep(op.args[0])
                 if vlist in newlist_v:
-                    op2 = block.operations[i+1]
-                    if (op2.opname == 'simple_call' and len(op2.args) == 2
-                        and op2.args[0] is op.result):
-                        append_v.append((op.args[0], op.result, block))
+                    for j in range(i + 1, len(block.operations)):
+                        op2 = block.operations[j]
+                        if (op2.opname == 'simple_call' and len(op2.args) == 2
+                            and op2.args[0] is op.result):
+                            append_v.append((op.args[0], op.result, block))
+                            break
     if not append_v:
         return
     detector = ListComprehensionDetector(graph, loops, newlist_v,
diff --git a/pypy/translator/test/test_simplify.py b/pypy/translator/test/test_simplify.py
--- a/pypy/translator/test/test_simplify.py
+++ b/pypy/translator/test/test_simplify.py
@@ -305,6 +305,27 @@
             'hint': 2,
             })
 
+    def test_iterate_over_list(self):
+        def wrap(elem):
+            return elem
+        
+        def f(i):
+            new_l = []
+            l = range(4)
+            for elem in l:
+                new_l.append(wrap(elem))
+            return new_l
+
+        self.check(f, {
+            'hint': 2,
+            'newlist': 1,
+            'iter': 1,
+            'next': 1,
+            'getattr': 1,
+            'simple_call': 3,
+            })
+            
+
 class TestLLSpecializeListComprehension:
     typesystem = 'lltype'
 


More information about the pypy-commit mailing list