[pypy-commit] pypy stacklet: hg merge default

arigo noreply at buildbot.pypy.org
Wed Aug 17 14:41:28 CEST 2011


Author: Armin Rigo <arigo at tunes.org>
Branch: stacklet
Changeset: r46560:d3707329359a
Date: 2011-08-17 14:44 +0200
http://bitbucket.org/pypy/pypy/changeset/d3707329359a/

Log:	hg merge default

diff --git a/ctypes_configure/stdoutcapture.py b/ctypes_configure/stdoutcapture.py
--- a/ctypes_configure/stdoutcapture.py
+++ b/ctypes_configure/stdoutcapture.py
@@ -15,6 +15,15 @@
             not hasattr(os, 'fdopen')):
             self.dummy = 1
         else:
+            try:
+                self.tmpout = os.tmpfile()
+                if mixed_out_err:
+                    self.tmperr = self.tmpout
+                else:
+                    self.tmperr = os.tmpfile()
+            except OSError:     # bah?  on at least one Windows box
+                self.dummy = 1
+                return
             self.dummy = 0
             # make new stdout/stderr files if needed
             self.localoutfd = os.dup(1)
@@ -29,11 +38,6 @@
                 sys.stderr = os.fdopen(self.localerrfd, 'w', 0)
             else:
                 self.saved_stderr = None
-            self.tmpout = os.tmpfile()
-            if mixed_out_err:
-                self.tmperr = self.tmpout
-            else:
-                self.tmperr = os.tmpfile()
             os.dup2(self.tmpout.fileno(), 1)
             os.dup2(self.tmperr.fileno(), 2)
 
diff --git a/lib-python/modified-2.7/test/regrtest.py b/lib-python/modified-2.7/test/regrtest.py
--- a/lib-python/modified-2.7/test/regrtest.py
+++ b/lib-python/modified-2.7/test/regrtest.py
@@ -1403,7 +1403,26 @@
         test_zipimport
         test_zlib
         """,
-    'openbsd3':
+    'openbsd4':
+        """
+        test_ascii_formatd
+        test_bsddb
+        test_bsddb3
+        test_ctypes
+        test_dl
+        test_epoll
+        test_gdbm
+        test_locale
+        test_normalization
+        test_ossaudiodev
+        test_pep277
+        test_tcl
+        test_tk
+        test_ttk_guionly
+        test_ttk_textonly
+        test_multiprocessing
+        """,
+    'openbsd5':
         """
         test_ascii_formatd
         test_bsddb
diff --git a/lib-python/modified-2.7/test/test_fcntl.py b/lib-python/modified-2.7/test/test_fcntl.py
new file mode 100644
--- /dev/null
+++ b/lib-python/modified-2.7/test/test_fcntl.py
@@ -0,0 +1,108 @@
+"""Test program for the fcntl C module.
+
+OS/2+EMX doesn't support the file locking operations.
+
+"""
+import os
+import struct
+import sys
+import unittest
+from test.test_support import (verbose, TESTFN, unlink, run_unittest,
+    import_module)
+
+# Skip test if no fnctl module.
+fcntl = import_module('fcntl')
+
+
+# TODO - Write tests for flock() and lockf().
+
+def get_lockdata():
+    if sys.platform.startswith('atheos'):
+        start_len = "qq"
+    else:
+        try:
+            os.O_LARGEFILE
+        except AttributeError:
+            start_len = "ll"
+        else:
+            start_len = "qq"
+
+    if sys.platform in ('netbsd1', 'netbsd2', 'netbsd3',
+                        'Darwin1.2', 'darwin',
+                        'freebsd2', 'freebsd3', 'freebsd4', 'freebsd5',
+                        'freebsd6', 'freebsd7', 'freebsd8',
+                        'bsdos2', 'bsdos3', 'bsdos4',
+                        'openbsd', 'openbsd2', 'openbsd3', 'openbsd4', 'openbsd5'):
+        if struct.calcsize('l') == 8:
+            off_t = 'l'
+            pid_t = 'i'
+        else:
+            off_t = 'lxxxx'
+            pid_t = 'l'
+        lockdata = struct.pack(off_t + off_t + pid_t + 'hh', 0, 0, 0,
+                               fcntl.F_WRLCK, 0)
+    elif sys.platform in ['aix3', 'aix4', 'hp-uxB', 'unixware7']:
+        lockdata = struct.pack('hhlllii', fcntl.F_WRLCK, 0, 0, 0, 0, 0, 0)
+    elif sys.platform in ['os2emx']:
+        lockdata = None
+    else:
+        lockdata = struct.pack('hh'+start_len+'hh', fcntl.F_WRLCK, 0, 0, 0, 0, 0)
+    if lockdata:
+        if verbose:
+            print 'struct.pack: ', repr(lockdata)
+    return lockdata
+
+lockdata = get_lockdata()
+
+
+class TestFcntl(unittest.TestCase):
+
+    def setUp(self):
+        self.f = None
+
+    def tearDown(self):
+        if self.f and not self.f.closed:
+            self.f.close()
+        unlink(TESTFN)
+
+    def test_fcntl_fileno(self):
+        # the example from the library docs
+        self.f = open(TESTFN, 'w')
+        rv = fcntl.fcntl(self.f.fileno(), fcntl.F_SETFL, os.O_NONBLOCK)
+        if verbose:
+            print 'Status from fcntl with O_NONBLOCK: ', rv
+        if sys.platform not in ['os2emx']:
+            rv = fcntl.fcntl(self.f.fileno(), fcntl.F_SETLKW, lockdata)
+            if verbose:
+                print 'String from fcntl with F_SETLKW: ', repr(rv)
+        self.f.close()
+
+    def test_fcntl_file_descriptor(self):
+        # again, but pass the file rather than numeric descriptor
+        self.f = open(TESTFN, 'w')
+        rv = fcntl.fcntl(self.f, fcntl.F_SETFL, os.O_NONBLOCK)
+        if sys.platform not in ['os2emx']:
+            rv = fcntl.fcntl(self.f, fcntl.F_SETLKW, lockdata)
+        self.f.close()
+
+    def test_fcntl_64_bit(self):
+        # Issue #1309352: fcntl shouldn't fail when the third arg fits in a
+        # C 'long' but not in a C 'int'.
+        try:
+            cmd = fcntl.F_NOTIFY
+            # This flag is larger than 2**31 in 64-bit builds
+            flags = fcntl.DN_MULTISHOT
+        except AttributeError:
+            self.skipTest("F_NOTIFY or DN_MULTISHOT unavailable")
+        fd = os.open(os.path.dirname(os.path.abspath(TESTFN)), os.O_RDONLY)
+        try:
+            fcntl.fcntl(fd, cmd, flags)
+        finally:
+            os.close(fd)
+
+
+def test_main():
+    run_unittest(TestFcntl)
+
+if __name__ == '__main__':
+    test_main()
diff --git a/lib-python/modified-2.7/test/test_tempfile.py b/lib-python/modified-2.7/test/test_tempfile.py
--- a/lib-python/modified-2.7/test/test_tempfile.py
+++ b/lib-python/modified-2.7/test/test_tempfile.py
@@ -23,8 +23,8 @@
 
 # TEST_FILES may need to be tweaked for systems depending on the maximum
 # number of files that can be opened at one time (see ulimit -n)
-if sys.platform in ('openbsd3', 'openbsd4'):
-    TEST_FILES = 48
+if sys.platform.startswith("openbsd"):
+    TEST_FILES = 64 # ulimit -n defaults to 128 for normal users
 else:
     TEST_FILES = 100
 
diff --git a/lib_pypy/_ctypes/structure.py b/lib_pypy/_ctypes/structure.py
--- a/lib_pypy/_ctypes/structure.py
+++ b/lib_pypy/_ctypes/structure.py
@@ -14,6 +14,15 @@
             raise TypeError("Expected CData subclass, got %s" % (tp,))
         if isinstance(tp, StructOrUnionMeta):
             tp._make_final()
+        if len(f) == 3:
+            if (not hasattr(tp, '_type_')
+                or not isinstance(tp._type_, str)
+                or tp._type_ not in "iIhHbBlL"):
+                #XXX: are those all types?
+                #     we just dont get the type name
+                #     in the interp levle thrown TypeError
+                #     from rawffi if there are more
+                raise TypeError('bit fields not allowed for type ' + tp.__name__)
 
     all_fields = []
     for cls in reversed(inspect.getmro(superclass)):
@@ -50,8 +59,9 @@
             if name in anonymous_fields:
                 for subname in value._names:
                     resnames.append(subname)
-                    relpos = startpos + value._fieldtypes[subname].offset
-                    subvalue = value._fieldtypes[subname].ctype
+                    subfield = getattr(value, subname)
+                    relpos = startpos + subfield.offset
+                    subvalue = subfield.ctype
                     fields[subname] = Field(subname,
                                             relpos, subvalue._sizeofinstances(),
                                             subvalue, i, is_bitfield)
@@ -59,7 +69,7 @@
                 resnames.append(name)
         names = resnames
     self._names = names
-    self._fieldtypes = fields
+    self.__dict__.update(fields)
 
 class Field(object):
     def __init__(self, name, offset, size, ctype, num, is_bitfield):
@@ -73,6 +83,35 @@
         return "<Field '%s' offset=%d size=%d>" % (self.name, self.offset,
                                                    self.size)
 
+    def __get__(self, obj, cls=None):
+        if obj is None:
+            return self
+        if self.is_bitfield:
+            # bitfield member, use direct access
+            return obj._buffer.__getattr__(self.name)
+        else:
+            fieldtype = self.ctype
+            offset = self.num
+            suba = obj._subarray(fieldtype, self.name)
+            return fieldtype._CData_output(suba, obj, offset)
+
+
+    def __set__(self, obj, value):
+        fieldtype = self.ctype
+        cobj = fieldtype.from_param(value)
+        if ensure_objects(cobj) is not None:
+            key = keepalive_key(self.num)
+            store_reference(obj, key, cobj._objects)
+        arg = cobj._get_buffer_value()
+        if fieldtype._fficompositesize is not None:
+            from ctypes import memmove
+            dest = obj._buffer.fieldaddress(self.name)
+            memmove(dest, arg, fieldtype._fficompositesize)
+        else:
+            obj._buffer.__setattr__(self.name, arg)
+
+
+
 # ________________________________________________________________
 
 def _set_shape(tp, rawfields, is_union=False):
@@ -81,17 +120,12 @@
     tp._ffiargshape = tp._ffishape = (tp._ffistruct, 1)
     tp._fficompositesize = tp._ffistruct.size
 
-def struct_getattr(self, name):
-    if name not in ('_fields_', '_fieldtypes'):
-        if hasattr(self, '_fieldtypes') and name in self._fieldtypes:
-            return self._fieldtypes[name]
-    return _CDataMeta.__getattribute__(self, name)
 
 def struct_setattr(self, name, value):
     if name == '_fields_':
         if self.__dict__.get('_fields_', None) is not None:
             raise AttributeError("_fields_ is final")
-        if self in [v for k, v in value]:
+        if self in [f[1] for f in value]:
             raise AttributeError("Structure or union cannot contain itself")
         names_and_fields(
             self,
@@ -129,10 +163,8 @@
         if '_fields_' not in self.__dict__:
             self._fields_ = []
             self._names = []
-            self._fieldtypes = {}
             _set_shape(self, [], self._is_union)
 
-    __getattr__ = struct_getattr
     __setattr__ = struct_setattr
 
     def from_address(self, address):
@@ -202,40 +234,6 @@
         A = _rawffi.Array(fieldtype._ffishape)
         return A.fromaddress(address, 1)
 
-    def __setattr__(self, name, value):
-        try:
-            field = self._fieldtypes[name]
-        except KeyError:
-            return _CData.__setattr__(self, name, value)
-        fieldtype = field.ctype
-        cobj = fieldtype.from_param(value)
-        if ensure_objects(cobj) is not None:
-            key = keepalive_key(field.num)
-            store_reference(self, key, cobj._objects)
-        arg = cobj._get_buffer_value()
-        if fieldtype._fficompositesize is not None:
-            from ctypes import memmove
-            dest = self._buffer.fieldaddress(name)
-            memmove(dest, arg, fieldtype._fficompositesize)
-        else:
-            self._buffer.__setattr__(name, arg)
-
-    def __getattribute__(self, name):
-        if name == '_fieldtypes':
-            return _CData.__getattribute__(self, '_fieldtypes')
-        try:
-            field = self._fieldtypes[name]
-        except KeyError:
-            return _CData.__getattribute__(self, name)
-        if field.is_bitfield:
-            # bitfield member, use direct access
-            return self._buffer.__getattr__(name)
-        else:
-            fieldtype = field.ctype
-            offset = field.num
-            suba = self._subarray(fieldtype, name)
-            return fieldtype._CData_output(suba, self, offset)
-
     def _get_buffer_for_param(self):
         return self
 
diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py
--- a/lib_pypy/_sqlite3.py
+++ b/lib_pypy/_sqlite3.py
@@ -724,13 +724,12 @@
             self.statement.reset()
             raise self.connection._get_exception(ret)
 
-        if self.statement.kind == "DQL":
-            if ret == SQLITE_ROW:
-                self.statement._build_row_cast_map()
-                self.statement._readahead()
-            else:
-                self.statement.item = None
-                self.statement.exhausted = True
+        if self.statement.kind == "DQL"and ret == SQLITE_ROW:
+            self.statement._build_row_cast_map()
+            self.statement._readahead()
+        else:
+            self.statement.item = None
+            self.statement.exhausted = True
 
         if self.statement.kind in ("DML", "DDL"):
             self.statement.reset()
@@ -891,7 +890,8 @@
 
         self.statement = c_void_p()
         next_char = c_char_p()
-        ret = sqlite.sqlite3_prepare_v2(self.con.db, sql, -1, byref(self.statement), byref(next_char))
+        sql_char = c_char_p(sql)
+        ret = sqlite.sqlite3_prepare_v2(self.con.db, sql_char, -1, byref(self.statement), byref(next_char))
         if ret == SQLITE_OK and self.statement.value is None:
             # an empty statement, we work around that, as it's the least trouble
             ret = sqlite.sqlite3_prepare_v2(self.con.db, "select 42", -1, byref(self.statement), byref(next_char))
@@ -901,7 +901,9 @@
             raise self.con._get_exception(ret)
         self.con._remember_statement(self)
         if _check_remaining_sql(next_char.value):
-            raise Warning, "One and only one statement required"
+            raise Warning, "One and only one statement required: %r" % (
+                next_char.value,)
+        # sql_char should remain alive until here
 
         self._build_row_cast_map()
 
diff --git a/pypy/annotation/builtin.py b/pypy/annotation/builtin.py
--- a/pypy/annotation/builtin.py
+++ b/pypy/annotation/builtin.py
@@ -308,9 +308,6 @@
             clsdef = clsdef.commonbase(cdef)
     return SomeInstance(clsdef)
 
-def robjmodel_we_are_translated():
-    return immutablevalue(True)
-
 def robjmodel_r_dict(s_eqfn, s_hashfn, s_force_non_null=None):
     if s_force_non_null is None:
         force_non_null = False
@@ -376,8 +373,6 @@
 
 BUILTIN_ANALYZERS[pypy.rlib.rarithmetic.intmask] = rarith_intmask
 BUILTIN_ANALYZERS[pypy.rlib.objectmodel.instantiate] = robjmodel_instantiate
-BUILTIN_ANALYZERS[pypy.rlib.objectmodel.we_are_translated] = (
-    robjmodel_we_are_translated)
 BUILTIN_ANALYZERS[pypy.rlib.objectmodel.r_dict] = robjmodel_r_dict
 BUILTIN_ANALYZERS[pypy.rlib.objectmodel.hlinvoke] = robjmodel_hlinvoke
 BUILTIN_ANALYZERS[pypy.rlib.objectmodel.keepalive_until_here] = robjmodel_keepalive_until_here
diff --git a/pypy/doc/cpython_differences.rst b/pypy/doc/cpython_differences.rst
--- a/pypy/doc/cpython_differences.rst
+++ b/pypy/doc/cpython_differences.rst
@@ -88,6 +88,13 @@
 
     _stackless
 
+  Note that only some of these modules are built-in in a typical
+  CPython installation, and the rest is from non built-in extension
+  modules.  This means that e.g. ``import parser`` will, on CPython,
+  find a local file ``parser.py``, while ``import sys`` will not find a
+  local file ``sys.py``.  In PyPy the difference does not exist: all
+  these modules are built-in.
+
 * Supported by being rewritten in pure Python (possibly using ``ctypes``):
   see the `lib_pypy/`_ directory.  Examples of modules that we
   support this way: ``ctypes``, ``cPickle``, ``cmath``, ``dbm``, ``datetime``...
diff --git a/pypy/doc/garbage_collection.rst b/pypy/doc/garbage_collection.rst
--- a/pypy/doc/garbage_collection.rst
+++ b/pypy/doc/garbage_collection.rst
@@ -147,7 +147,7 @@
 You can read more about them at the start of
 `pypy/rpython/memory/gc/minimark.py`_.
 
-In more details:
+In more detail:
 
 - The small newly malloced objects are allocated in the nursery (case 1).
   All objects living in the nursery are "young".
diff --git a/pypy/doc/getting-started-python.rst b/pypy/doc/getting-started-python.rst
--- a/pypy/doc/getting-started-python.rst
+++ b/pypy/doc/getting-started-python.rst
@@ -32,7 +32,10 @@
 .. _`windows document`: windows.html
 
 You can translate the whole of PyPy's Python interpreter to low level C code,
-or `CLI code`_.
+or `CLI code`_.  If you intend to build using gcc, check to make sure that
+the version you have is not 4.2 or you will run into `this bug`_.
+
+.. _`this bug`: https://bugs.launchpad.net/ubuntu/+source/gcc-4.2/+bug/187391
 
 1. First `download a pre-built PyPy`_ for your architecture which you will
    use to translate your Python interpreter.  It is, of course, possible to
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
@@ -48,12 +48,6 @@
 
 .. image:: image/jitviewer.png
 
-We would like to add one level to this hierarchy, by showing the generated
-machine code for each jit operation.  The necessary information is already in
-the log file produced by the JIT, so it is "only" a matter of teaching the
-jitviewer to display it.  Ideally, the machine code should be hidden by
-default and viewable on request.
-
 The jitviewer is a web application based on flask and jinja2 (and jQuery on
 the client): if you have great web developing skills and want to help PyPy,
 this is an ideal task to get started, because it does not require any deep
diff --git a/pypy/doc/release-1.6.0.rst b/pypy/doc/release-1.6.0.rst
--- a/pypy/doc/release-1.6.0.rst
+++ b/pypy/doc/release-1.6.0.rst
@@ -1,6 +1,6 @@
-===========================
-PyPy 1.6 - faster than ever
-===========================
+=========================================================
+PyPy 1.6 - XXX thing something out (I like kickass panda)
+=========================================================
 
 We're pleased to announce the 1.6 release of PyPy. This release brings a lot
 of bugfixes and performance improvements over 1.5, and improves support for
@@ -15,15 +15,15 @@
 
 PyPy is a very compliant Python interpreter, almost a drop-in replacement for
 CPython 2.7.1. It's fast (`pypy 1.5 and cpython 2.6.2`_ performance comparison)
-due to its integrated tracing JIT compiler. XXX: compare to 2.7.1
+due to its integrated tracing JIT compiler.
 
 This release supports x86 machines running Linux 32/64 or Mac OS X.  Windows 32
 is beta (it roughly works but a lot of small issues have not been fixed so
 far).  Windows 64 is not yet supported.
 
-The main topics of this release are speed and stability: on average, PyPy 1.6
-is between 20% and 30% faster than PyPy 1.5, and overall it's 4.3 times faster
-than CPython when running our set of benchmarks.
+The main topics of this release are speed and stability: on average on
+our benchmark suite, PyPy 1.6 is between 20% and 30% faster than PyPy 1.5,
+which was already much faster than CPython on our set of benchmarks.
 
 The speed improvements have been made possible by optimizing many of the
 layers which compose PyPy.  In particular, we improved: the Garbage Collector,
@@ -55,7 +55,8 @@
   - optimized dictionaries: the internal representation of dictionaries is now
     dynamically selected depending on the type of stored objects, resulting in
     faster code and smaller memory footprint.  For example, dictionaries whose
-    keys are all strings, or all integers.
+    keys are all strings, or all integers. Other dictionaries are also smaller
+    due to bugfixes.
 
 * JitViewer: this is the first official release which includes the JitViewer,
   a web-based tool which helps you to see which parts of your Python code have
@@ -67,13 +68,14 @@
   our `compatibility wiki`_.
 
 * Multibyte encoding support: this was of of the last areas in which we were
-  still behind CPython, but now we fully support them. (XXX: is that true?)
+  still behind CPython, but now we fully support them.
 
 * Preliminary support for NumPy: this release includes a preview of a very
   fast NumPy module integrated with the PyPy JIT.  Unfortunately, this does
   not mean that you can expect to take an existing NumPy program and run it on
   PyPy, because the module is still unfinished and supports only some of the
-  numpy API.  However, what works is blazingly fast :-)
+  numpy API. However, barring some details, what works should be
+  blazingly fast :-)
 
 * Bugfixes: since the 1.5 release we fixed 53 bugs in our `bug tracker`_, not
   counting the numerous bugs that were found and reported through other
@@ -81,5 +83,6 @@
 
 Cheers,
 
-Carl Friedrich Bolz, Laura Creighton, Antonio Cuni, Maciej Fijalkowski,
-Amaury Forgeot d'Arc, Alex Gaynor, Armin Rigo and the PyPy team
+Hakan Ardo, Carl Friedrich Bolz, Laura Creighton, Antonio Cuni,
+Maciej Fijalkowski, Amaury Forgeot d'Arc, Alex Gaynor,
+Armin Rigo and the PyPy team
diff --git a/pypy/interpreter/pyframe.py b/pypy/interpreter/pyframe.py
--- a/pypy/interpreter/pyframe.py
+++ b/pypy/interpreter/pyframe.py
@@ -52,6 +52,9 @@
     escaped                  = False  # see mark_as_escaped()
 
     def __init__(self, space, code, w_globals, closure):
+        if not we_are_translated():
+            assert type(self) in (space.FrameClass, CPythonFrame), (
+                "use space.FrameClass(), not directly PyFrame()")
         self = hint(self, access_directly=True, fresh_virtualizable=True)
         assert isinstance(code, pycode.PyCode)
         self.pycode = code
@@ -80,7 +83,7 @@
         self.escaped = True
 
     def append_block(self, block):
-        block.previous = self.lastblock
+        assert block.previous is self.lastblock
         self.lastblock = block
 
     def pop_block(self):
@@ -106,7 +109,8 @@
         while i >= 0:
             block = lst[i]
             i -= 1
-            self.append_block(block)
+            block.previous = self.lastblock
+            self.lastblock = block
 
     def get_builtin(self):
         if self.space.config.objspace.honor__builtins__:
diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py
--- a/pypy/interpreter/pyopcode.py
+++ b/pypy/interpreter/pyopcode.py
@@ -892,16 +892,16 @@
         raise BytecodeCorruption, "old opcode, no longer in use"
 
     def SETUP_LOOP(self, offsettoend, next_instr):
-        block = LoopBlock(self, next_instr + offsettoend)
-        self.append_block(block)
+        block = LoopBlock(self, next_instr + offsettoend, self.lastblock)
+        self.lastblock = block
 
     def SETUP_EXCEPT(self, offsettoend, next_instr):
-        block = ExceptBlock(self, next_instr + offsettoend)
-        self.append_block(block)
+        block = ExceptBlock(self, next_instr + offsettoend, self.lastblock)
+        self.lastblock = block
 
     def SETUP_FINALLY(self, offsettoend, next_instr):
-        block = FinallyBlock(self, next_instr + offsettoend)
-        self.append_block(block)
+        block = FinallyBlock(self, next_instr + offsettoend, self.lastblock)
+        self.lastblock = block
 
     def SETUP_WITH(self, offsettoend, next_instr):
         w_manager = self.peekvalue()
@@ -915,8 +915,8 @@
         w_exit = self.space.get(w_descr, w_manager)
         self.settopvalue(w_exit)
         w_result = self.space.get_and_call_function(w_enter, w_manager)
-        block = WithBlock(self, next_instr + offsettoend)
-        self.append_block(block)
+        block = WithBlock(self, next_instr + offsettoend, self.lastblock)
+        self.lastblock = block
         self.pushvalue(w_result)
 
     def WITH_CLEANUP(self, oparg, next_instr):
@@ -1247,10 +1247,10 @@
 
     _immutable_ = True
 
-    def __init__(self, frame, handlerposition):
+    def __init__(self, frame, handlerposition, previous):
         self.handlerposition = handlerposition
         self.valuestackdepth = frame.valuestackdepth
-        self.previous = None # this makes a linked list of blocks
+        self.previous = previous   # this makes a linked list of blocks
 
     def __eq__(self, other):
         return (self.__class__ is other.__class__ and
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
@@ -92,6 +92,7 @@
         self.datablockwrapper = None
         self.stack_check_slowpath = 0
         self.propagate_exception_path = 0
+        self.gcrootmap_retaddr_forced = 0
         self.teardown()
 
     def leave_jitted_hook(self):
@@ -357,6 +358,7 @@
         self.stack_check_slowpath = rawstart
 
     @staticmethod
+    @rgc.no_collect
     def _release_gil_asmgcc(css):
         # similar to trackgcroot.py:pypy_asm_stackwalk, first part
         from pypy.rpython.memory.gctransform import asmgcroot
@@ -372,6 +374,7 @@
             before()
 
     @staticmethod
+    @rgc.no_collect
     def _reacquire_gil_asmgcc(css):
         # first reacquire the GIL
         after = rffi.aroundstate.after
@@ -386,12 +389,14 @@
         next.prev = prev
 
     @staticmethod
+    @rgc.no_collect
     def _release_gil_shadowstack():
         before = rffi.aroundstate.before
         if before:
             before()
 
     @staticmethod
+    @rgc.no_collect
     def _reacquire_gil_shadowstack():
         after = rffi.aroundstate.after
         if after:
@@ -2219,13 +2224,27 @@
                 css = get_ebp_ofs(pos + use_words - 1)
                 self._regalloc.close_stack_struct = css
             # The location where the future CALL will put its return address
-            # will be [ESP-WORD], so save that as the next frame's top address
-            self.mc.LEA_rs(eax.value, -WORD)        # LEA EAX, [ESP-4]
+            # will be [ESP-WORD].  But we can't use that as the next frame's
+            # top address!  As the code after releasegil() runs without the
+            # GIL, it might not be set yet by the time we need it (very
+            # unlikely), or it might be overwritten by the following call
+            # to reaquiregil() (much more likely).  So we hack even more
+            # and use a dummy location containing a dummy value (a pointer
+            # to itself) which we pretend is the return address :-/ :-/ :-/
+            # It prevents us to store any %esp-based stack locations but we
+            # don't so far.
+            adr = self.datablockwrapper.malloc_aligned(WORD, WORD)
+            rffi.cast(rffi.CArrayPtr(lltype.Signed), adr)[0] = adr
+            self.gcrootmap_retaddr_forced = adr
             frame_ptr = css + WORD * (2+asmgcroot.FRAME_PTR)
-            self.mc.MOV_br(frame_ptr, eax.value)    # MOV [css.frame], EAX
+            if rx86.fits_in_32bits(adr):
+                self.mc.MOV_bi(frame_ptr, adr)          # MOV [css.frame], adr
+            else:
+                self.mc.MOV_ri(eax.value, adr)          # MOV EAX, adr
+                self.mc.MOV_br(frame_ptr, eax.value)    # MOV [css.frame], EAX
             # Save ebp
             index_of_ebp = css + WORD * (2+asmgcroot.INDEX_OF_EBP)
-            self.mc.MOV_br(index_of_ebp, ebp.value) # MOV [css.ebp], EBP
+            self.mc.MOV_br(index_of_ebp, ebp.value)     # MOV [css.ebp], EBP
             # Call the closestack() function (also releasing the GIL)
             if IS_X86_32:
                 reg = eax
@@ -2253,6 +2272,9 @@
         if gcrootmap.is_shadow_stack:
             args = []
         else:
+            assert self.gcrootmap_retaddr_forced == -1, (
+                      "missing mark_gc_roots() in CALL_RELEASE_GIL")
+            self.gcrootmap_retaddr_forced = 0
             css = self._regalloc.close_stack_struct
             assert css != 0
             if IS_X86_32:
@@ -2503,7 +2525,13 @@
             if gcrootmap.is_shadow_stack:
                 gcrootmap.write_callshape(mark, force_index)
             else:
-                self.mc.insert_gcroot_marker(mark)
+                if self.gcrootmap_retaddr_forced == 0:
+                    self.mc.insert_gcroot_marker(mark)   # common case
+                else:
+                    assert self.gcrootmap_retaddr_forced != -1, (
+                              "two mark_gc_roots() in a CALL_RELEASE_GIL")
+                    gcrootmap.put(self.gcrootmap_retaddr_forced, mark)
+                    self.gcrootmap_retaddr_forced = -1
 
     def target_arglocs(self, loop_token):
         return loop_token._x86_arglocs
diff --git a/pypy/jit/metainterp/pyjitpl.py b/pypy/jit/metainterp/pyjitpl.py
--- a/pypy/jit/metainterp/pyjitpl.py
+++ b/pypy/jit/metainterp/pyjitpl.py
@@ -1427,6 +1427,7 @@
                 # can change from run to run.
                 d = {}
                 for jitcode in self.indirectcalltargets:
+                    assert jitcode.fnaddr not in d
                     d[jitcode.fnaddr] = jitcode
                 self.globaldata.indirectcall_dict = d
             return d.get(fnaddress, None)
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
@@ -2631,6 +2631,8 @@
         self.check_loops(new_with_vtable=1)
 
     def test_release_gil_flush_heap_cache(self):
+        if sys.platform == "win32":
+            py.test.skip("needs 'time'")
         T = rffi.CArrayPtr(rffi.TIME_T)
 
         external = rffi.llexternal("time", [T], rffi.TIME_T, threadsafe=True)
diff --git a/pypy/module/_ssl/interp_ssl.py b/pypy/module/_ssl/interp_ssl.py
--- a/pypy/module/_ssl/interp_ssl.py
+++ b/pypy/module/_ssl/interp_ssl.py
@@ -138,6 +138,11 @@
         return self.space.wrap(rffi.charp2str(self._issuer))
 
     def __del__(self):
+        self.enqueue_for_destruction(self.space, SSLObject.destructor,
+                                     '__del__() method of ')
+
+    def destructor(self):
+        assert isinstance(self, SSLObject)
         if self.peer_cert:
             libssl_X509_free(self.peer_cert)
         if self.ssl:
diff --git a/pypy/module/_ssl/test/test_ssl.py b/pypy/module/_ssl/test/test_ssl.py
--- a/pypy/module/_ssl/test/test_ssl.py
+++ b/pypy/module/_ssl/test/test_ssl.py
@@ -63,7 +63,7 @@
         _ssl.RAND_egd("entropy")
 
     def test_sslwrap(self):
-        import _ssl, _socket, sys
+        import _ssl, _socket, sys, gc
         if sys.platform == 'darwin':
             skip("hangs indefinitely on OSX (also on CPython)")
         s = _socket.socket()
@@ -73,15 +73,19 @@
             assert exc.value.errno == 2 # Cannot find file (=not a socket)
         else:
             assert exc.value.errno == 32 # Broken pipe
+        del exc, ss, s
+        gc.collect()     # force the destructor() to be called now
 
     def test_async_closed(self):
-        import _ssl, _socket
+        import _ssl, _socket, gc
         s = _socket.socket()
         s.settimeout(3)
         ss = _ssl.sslwrap(s, 0)
         s.close()
         exc = raises(_ssl.SSLError, ss.write, "data")
         assert exc.value.strerror == "Underlying socket has been closed."
+        del exc, ss, s
+        gc.collect()     # force the destructor() to be called now
 
 
 class AppTestConnectedSSL:
@@ -104,42 +108,47 @@
             """)
 
     def test_connect(self):
-        import socket
+        import socket, gc
         ss = socket.ssl(self.s)
         self.s.close()
+        del ss; gc.collect()
 
     def test_server(self):
-        import socket
+        import socket, gc
         ss = socket.ssl(self.s)
         assert isinstance(ss.server(), str)
         self.s.close()
+        del ss; gc.collect()
 
     def test_issuer(self):
-        import socket
+        import socket, gc
         ss = socket.ssl(self.s)
         assert isinstance(ss.issuer(), str)
         self.s.close()
+        del ss; gc.collect()
 
     def test_write(self):
-        import socket
+        import socket, gc
         ss = socket.ssl(self.s)
         raises(TypeError, ss.write, 123)
         num_bytes = ss.write("hello\n")
         assert isinstance(num_bytes, int)
         assert num_bytes >= 0
         self.s.close()
+        del ss; gc.collect()
 
     def test_read(self):
-        import socket
+        import socket, gc
         ss = socket.ssl(self.s)
         raises(TypeError, ss.read, "foo")
         ss.write("hello\n")
         data = ss.read()
         assert isinstance(data, str)
         self.s.close()
+        del ss; gc.collect()
 
     def test_read_upto(self):
-        import socket
+        import socket, gc
         ss = socket.ssl(self.s)
         raises(TypeError, ss.read, "foo")
         ss.write("hello\n")
@@ -148,15 +157,17 @@
         assert len(data) == 10
         assert ss.pending() > 50 # many more bytes to read
         self.s.close()
+        del ss; gc.collect()
 
     def test_shutdown(self):
-        import socket, ssl, sys
+        import socket, ssl, sys, gc
         if sys.platform == 'darwin':
             skip("get also on CPython: error: [Errno 0]")
         ss = socket.ssl(self.s)
         ss.write("hello\n")
         assert ss.shutdown() is self.s._sock
         raises(ssl.SSLError, ss.write, "hello\n")
+        del ss; gc.collect()
 
 class AppTestConnectedSSL_Timeout(AppTestConnectedSSL):
     # Same tests, with a socket timeout
diff --git a/pypy/module/array/interp_array.py b/pypy/module/array/interp_array.py
--- a/pypy/module/array/interp_array.py
+++ b/pypy/module/array/interp_array.py
@@ -38,12 +38,10 @@
                 w_initializer = __args__.arguments_w[0]
                 if space.type(w_initializer) is space.w_str:
                     a.fromstring(space.str_w(w_initializer))
-                elif space.type(w_initializer) is space.w_unicode:
-                    a.fromsequence(w_initializer)
                 elif space.type(w_initializer) is space.w_list:
                     a.fromlist(w_initializer)
                 else:
-                    a.extend(w_initializer)
+                    a.extend(w_initializer, True)
             break
     else:
         msg = 'bad typecode (must be c, b, B, u, h, H, i, I, l, L, f or d)'
@@ -287,7 +285,7 @@
                 self.setlen(s)
                 raise
 
-        def extend(self, w_iterable):
+        def extend(self, w_iterable, accept_different_array=False):
             space = self.space
             if isinstance(w_iterable, W_Array):
                 oldlen = self.len
@@ -300,7 +298,8 @@
                     self.buffer[oldlen + i] = w_iterable.buffer[i]
                     i += 1
                 self.setlen(oldlen + i)
-            elif isinstance(w_iterable, W_ArrayBase):
+            elif (not accept_different_array
+                  and isinstance(w_iterable, W_ArrayBase)):
                 msg = "can only extend with array of same kind"
                 raise OperationError(space.w_TypeError, space.wrap(msg))
             else:
diff --git a/pypy/module/array/test/test_array.py b/pypy/module/array/test/test_array.py
--- a/pypy/module/array/test/test_array.py
+++ b/pypy/module/array/test/test_array.py
@@ -64,6 +64,10 @@
             assert self.array(tc).typecode == tc
             raises(TypeError, self.array, tc, None)
 
+        a = self.array('i', (1, 2, 3))
+        b = self.array('h', a)
+        assert list(b) == [1, 2, 3]
+
     def test_value_range(self):
         import sys
         values = (-129, 128, -128, 127, 0, 255, -1, 256,
diff --git a/pypy/module/bz2/interp_bz2.py b/pypy/module/bz2/interp_bz2.py
--- a/pypy/module/bz2/interp_bz2.py
+++ b/pypy/module/bz2/interp_bz2.py
@@ -123,9 +123,9 @@
     def _bzs_total_out(bzs):
         return bzs.total_out
 
-def external(name, args, result):
+def external(name, args, result, **kwds):
     return rffi.llexternal(name, args, result, compilation_info=
-                           CConfig._compilation_info_)
+                           CConfig._compilation_info_, **kwds)
 
 # the least but one parameter should be rffi.VOIDP but it's not used
 # so I trick the compiler to not complain about constanst pointer passed
@@ -143,11 +143,13 @@
                                        rffi.INT], lltype.Void)
 BZ2_bzCompressInit = external('BZ2_bzCompressInit', [bz_stream, rffi.INT,
                               rffi.INT, rffi.INT], rffi.INT)
-BZ2_bzCompressEnd = external('BZ2_bzCompressEnd', [bz_stream], rffi.INT)
+BZ2_bzCompressEnd = external('BZ2_bzCompressEnd', [bz_stream], rffi.INT,
+                             threadsafe=False)
 BZ2_bzCompress = external('BZ2_bzCompress', [bz_stream, rffi.INT], rffi.INT)
 BZ2_bzDecompressInit = external('BZ2_bzDecompressInit', [bz_stream, rffi.INT,
                                                          rffi.INT], rffi.INT)
-BZ2_bzDecompressEnd = external('BZ2_bzDecompressEnd', [bz_stream], rffi.INT)
+BZ2_bzDecompressEnd = external('BZ2_bzDecompressEnd', [bz_stream], rffi.INT,
+                               threadsafe=False)
 BZ2_bzDecompress = external('BZ2_bzDecompress', [bz_stream], rffi.INT)
 
 def _catch_bz2_error(space, bzerror):
diff --git a/pypy/module/cpyext/frameobject.py b/pypy/module/cpyext/frameobject.py
--- a/pypy/module/cpyext/frameobject.py
+++ b/pypy/module/cpyext/frameobject.py
@@ -57,7 +57,7 @@
     code = space.interp_w(PyCode, w_code)
     w_globals = from_ref(space, py_frame.c_f_globals)
 
-    frame = PyFrame(space, code, w_globals, closure=None)
+    frame = space.FrameClass(space, code, w_globals, closure=None)
     frame.f_lineno = py_frame.c_f_lineno
     w_obj = space.wrap(frame)
     track_reference(space, py_obj, w_obj)
diff --git a/pypy/module/fcntl/test/test_fcntl.py b/pypy/module/fcntl/test/test_fcntl.py
--- a/pypy/module/fcntl/test/test_fcntl.py
+++ b/pypy/module/fcntl/test/test_fcntl.py
@@ -47,7 +47,8 @@
                             'freebsd2', 'freebsd3', 'freebsd4', 'freebsd5',
                             'freebsd6', 'freebsd7', 'freebsd8', 'freebsd9',
                             'bsdos2', 'bsdos3', 'bsdos4',
-                            'openbsd', 'openbsd2', 'openbsd3'):
+                            'openbsd', 'openbsd2', 'openbsd3', 'openbsd4',
+                            'openbsd5'):
             if struct.calcsize('l') == 8:
                 off_t = 'l'
                 pid_t = 'i'
@@ -181,7 +182,7 @@
 
     def test_large_flag(self):
         import sys
-        if sys.platform == "darwin":
+        if sys.platform == "darwin" or sys.platform.startswith("openbsd"):
             skip("Mac OS doesn't have any large flag in fcntl.h")
         import fcntl, sys
         if sys.maxint == 2147483647:
diff --git a/pypy/module/imp/importing.py b/pypy/module/imp/importing.py
--- a/pypy/module/imp/importing.py
+++ b/pypy/module/imp/importing.py
@@ -878,7 +878,8 @@
         code_w = parse_source_module(space, pathname, source)
 
         if space.config.objspace.usepycfiles and write_pyc:
-            write_compiled_module(space, code_w, cpathname, mode, mtime)
+            if not space.is_true(space.sys.get('dont_write_bytecode')):
+                write_compiled_module(space, code_w, cpathname, mode, mtime)
 
     update_code_filenames(space, code_w, pathname)
     exec_code_module(space, w_mod, code_w)
diff --git a/pypy/module/imp/test/test_import.py b/pypy/module/imp/test/test_import.py
--- a/pypy/module/imp/test/test_import.py
+++ b/pypy/module/imp/test/test_import.py
@@ -769,6 +769,27 @@
         cpathname = udir.join('test.pyc')
         assert not cpathname.check()
 
+    def test_load_source_module_dont_write_bytecode(self):
+        space = self.space
+        w_modulename = space.wrap('somemodule')
+        w_mod = space.wrap(Module(space, w_modulename))
+        pathname = _testfilesource()
+        stream = streamio.open_file_as_stream(pathname, "r")
+        try:
+            space.setattr(space.sys, space.wrap('dont_write_bytecode'),
+                          space.w_True)
+            w_ret = importing.load_source_module(space,
+                                                 w_modulename,
+                                                 w_mod,
+                                                 pathname,
+                                                 stream.readall())
+        finally:
+            space.setattr(space.sys, space.wrap('dont_write_bytecode'),
+                          space.w_False)
+            stream.close()
+        cpathname = udir.join('test.pyc')
+        assert not cpathname.check()
+
     def test_load_source_module_syntaxerror(self):
         # No .pyc file on SyntaxError
         space = self.space
diff --git a/pypy/module/micronumpy/interp_numarray.py b/pypy/module/micronumpy/interp_numarray.py
--- a/pypy/module/micronumpy/interp_numarray.py
+++ b/pypy/module/micronumpy/interp_numarray.py
@@ -295,7 +295,6 @@
     """
     Intermediate class representing a float literal.
     """
-    _immutable_fields_ = ["float_value"]
     signature = Signature()
 
     def __init__(self, float_value):
@@ -356,8 +355,6 @@
 
 
 class Call1(VirtualArray):
-    _immutable_fields_ = ["function", "values"]
-
     def __init__(self, function, values, signature):
         VirtualArray.__init__(self, signature)
         self.function = function
@@ -376,8 +373,6 @@
     """
     Intermediate class for performing binary operations.
     """
-    _immutable_fields_ = ["function", "left", "right"]
-
     def __init__(self, function, left, right, signature):
         VirtualArray.__init__(self, signature)
         self.function = function
@@ -404,8 +399,6 @@
     Class for representing views of arrays, they will reflect changes of parent
     arrays. Example: slices
     """
-    _immutable_fields_ = ["parent"]
-
     def __init__(self, parent, signature):
         BaseArray.__init__(self)
         self.signature = signature
@@ -433,7 +426,6 @@
         raise NotImplementedError
 
 class SingleDimSlice(ViewArray):
-    _immutable_fields_ = ["start", "stop", "step", "size"]
     static_signature = Signature()
 
     def __init__(self, start, stop, step, slice_length, parent, signature):
diff --git a/pypy/module/posix/app_posix.py b/pypy/module/posix/app_posix.py
--- a/pypy/module/posix/app_posix.py
+++ b/pypy/module/posix/app_posix.py
@@ -315,7 +315,7 @@
             self._proc = proc
         def close(self):
             self._stream.close()
-            return self._proc.wait()
+            return self._proc.wait() or None    # 0 => None
         __del__ = close
         def __getattr__(self, name):
             return getattr(self._stream, name)
diff --git a/pypy/module/posix/interp_posix.py b/pypy/module/posix/interp_posix.py
--- a/pypy/module/posix/interp_posix.py
+++ b/pypy/module/posix/interp_posix.py
@@ -473,7 +473,7 @@
         FIELDS = PORTABLE_STAT_FIELDS
     else:
         FIELDS = STAT_FIELDS    # also when not translating at all
-    return space.newlist([space.wrap(name) for name, _ in FIELDS])
+    return space.newlist([space.wrap(name) for _, (name, _) in FIELDS])
 
 
 class State:
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
@@ -317,7 +317,7 @@
 XML_ParserCreateNS = expat_external(
     'XML_ParserCreateNS', [rffi.CCHARP, rffi.CHAR], XML_Parser)
 XML_ParserFree = expat_external(
-    'XML_ParserFree', [XML_Parser], lltype.Void)
+    'XML_ParserFree', [XML_Parser], lltype.Void, threadsafe=False)
 XML_SetUserData = expat_external(
     'XML_SetUserData', [XML_Parser, rffi.VOIDP], lltype.Void)
 def XML_GetUserData(parser):
diff --git a/pypy/module/test_lib_pypy/ctypes_tests/test_bitfields.py b/pypy/module/test_lib_pypy/ctypes_tests/test_bitfields.py
--- a/pypy/module/test_lib_pypy/ctypes_tests/test_bitfields.py
+++ b/pypy/module/test_lib_pypy/ctypes_tests/test_bitfields.py
@@ -5,8 +5,6 @@
 
 import ctypes
 
-py.test.skip("bitfields not supported")
-
 def setup_module(mod):
     import conftest
     _ctypes_test = str(conftest.sofile)
@@ -14,7 +12,7 @@
     func.argtypes = POINTER(BITS), c_char
     mod.func = func
 
-class BITS(BaseCTypesTestChecker):
+class BITS(Structure):
     _fields_ = [("A", c_int, 1),
                 ("B", c_int, 2),
                 ("C", c_int, 3),
@@ -197,6 +195,8 @@
         try:
             func(*args, **kw)
         except Exception, detail:
+            import traceback
+            traceback.print_exc()
             return detail.__class__, str(detail)
 
     def test_mixed_1(self):
@@ -228,3 +228,24 @@
         class Y(Structure):
             _anonymous_ = ["_"]
             _fields_ = [("_", X)]
+
+    def test_set_fields_attr(self):
+        class A(Structure):
+            pass
+        A._fields_ = [("a", c_byte),
+                      ("b", c_ubyte)]
+
+    def test_set_fields_attr_bitfields(self):
+        class A(Structure):
+            pass
+        A._fields_ = [("a", POINTER(A)),
+                      ("b", c_ubyte, 4)]
+
+
+    def test_set_fields_cycle_fails(self):
+        class A(Structure):
+            pass
+        import pytest
+        pytest.raises(AttributeError, """
+            A._fields_ = [("a", A)]
+                      """)
diff --git a/pypy/module/thread/gil.py b/pypy/module/thread/gil.py
--- a/pypy/module/thread/gil.py
+++ b/pypy/module/thread/gil.py
@@ -98,6 +98,7 @@
     thread.release_NOAUTO(spacestate.ll_GIL)
     set_errno(e)
 before_external_call._gctransformer_hint_cannot_collect_ = True
+before_external_call._dont_reach_me_in_del_ = True
 
 def after_external_call():
     e = get_errno()
@@ -106,6 +107,7 @@
     spacestate.after_thread_switch()
     set_errno(e)
 after_external_call._gctransformer_hint_cannot_collect_ = True
+after_external_call._dont_reach_me_in_del_ = True
 
 # The _gctransformer_hint_cannot_collect_ hack is needed for
 # translations in which the *_external_call() functions are not inlined.
diff --git a/pypy/module/thread/ll_thread.py b/pypy/module/thread/ll_thread.py
--- a/pypy/module/thread/ll_thread.py
+++ b/pypy/module/thread/ll_thread.py
@@ -51,9 +51,9 @@
 
 c_thread_lock_init = llexternal('RPyThreadLockInit', [TLOCKP], rffi.INT,
                                 threadsafe=False)   # may add in a global list
-c_thread_lock_dealloc = llexternal('RPyOpaqueDealloc_ThreadLock', [TLOCKP],
-                                  lltype.Void,
-                                  threadsafe=True)
+c_thread_lock_dealloc_NOAUTO = llexternal('RPyOpaqueDealloc_ThreadLock',
+                                          [TLOCKP], lltype.Void,
+                                          _nowrapper=True)
 c_thread_acquirelock = llexternal('RPyThreadAcquireLock', [TLOCKP, rffi.INT],
                                   rffi.INT,
                                   threadsafe=True)    # release the GIL
@@ -158,9 +158,9 @@
     return ll_lock
 
 def free_ll_lock(ll_lock):
-    c_thread_acquirelock(ll_lock, 0)
-    c_thread_releaselock(ll_lock)
-    c_thread_lock_dealloc(ll_lock)
+    acquire_NOAUTO(ll_lock, False)
+    release_NOAUTO(ll_lock)
+    c_thread_lock_dealloc_NOAUTO(ll_lock)
     lltype.free(ll_lock, flavor='raw', track_allocation=False)
 
 def acquire_NOAUTO(ll_lock, flag):
diff --git a/pypy/module/thread/os_thread.py b/pypy/module/thread/os_thread.py
--- a/pypy/module/thread/os_thread.py
+++ b/pypy/module/thread/os_thread.py
@@ -252,4 +252,6 @@
 def interrupt_main(space):
     """Raise a KeyboardInterrupt in the main thread.
 A subthread can use this function to interrupt the main thread."""
+    if space.check_signal_action is None:   # no signal module!
+        raise OperationError(space.w_KeyboardInterrupt, space.w_None)
     space.check_signal_action.set_interrupt()
diff --git a/pypy/module/thread/test/test_ll_thread.py b/pypy/module/thread/test/test_ll_thread.py
--- a/pypy/module/thread/test/test_ll_thread.py
+++ b/pypy/module/thread/test/test_ll_thread.py
@@ -52,6 +52,13 @@
             assert get_ident() == state.z.ident
             state.seen_value = state.z.value
             state.z = None
+            # I think that we would need here a memory barrier in order
+            # to make the test pass reliably.  The issue is that the
+            # main thread may see 'state.done = 1' before seeing the
+            # effect of the other assignments done above.  For now let's
+            # emulate the write barrier by doing a system call and
+            # waiting a bit...
+            time.sleep(0.012)
             state.done = 1
 
         def g(i):
diff --git a/pypy/objspace/flow/flowcontext.py b/pypy/objspace/flow/flowcontext.py
--- a/pypy/objspace/flow/flowcontext.py
+++ b/pypy/objspace/flow/flowcontext.py
@@ -406,8 +406,8 @@
         w_exit = self.space.getattr(w_manager, self.space.wrap("__exit__"))
         self.settopvalue(w_exit)
         w_result = self.space.call_method(w_manager, "__enter__")
-        block = WithBlock(self, next_instr + offsettoend)
-        self.append_block(block)
+        block = WithBlock(self, next_instr + offsettoend, self.lastblock)
+        self.lastblock = block
         self.pushvalue(w_result)
 
     # XXX Unimplemented 2.7 opcodes ----------------
diff --git a/pypy/objspace/flow/specialcase.py b/pypy/objspace/flow/specialcase.py
--- a/pypy/objspace/flow/specialcase.py
+++ b/pypy/objspace/flow/specialcase.py
@@ -4,6 +4,7 @@
 from pypy.interpreter.error import OperationError
 from pypy.tool.cache import Cache
 from pypy.rlib.rarithmetic import r_uint
+from pypy.rlib.objectmodel import we_are_translated
 import py
 
 def sc_import(space, fn, args):
@@ -129,6 +130,9 @@
         return Constant(r_uint(w_value.value))
     return space.do_operation('simple_call', space.wrap(r_uint), w_value)
 
+def sc_we_are_translated(space, we_are_translated, args):
+    return Constant(True)
+
 def setup(space):
     # fn = pyframe.normalize_exception.get_function(space)
     # this is now routed through the objspace, directly.
@@ -144,3 +148,5 @@
     # (normally, the 32-bit constant is a long, and is not allowed to
     # show up in the flow graphs at all)
     space.specialcases[r_uint] = sc_r_uint
+    # special case we_are_translated() to return True
+    space.specialcases[we_are_translated] = sc_we_are_translated
diff --git a/pypy/objspace/flow/test/test_objspace.py b/pypy/objspace/flow/test/test_objspace.py
--- a/pypy/objspace/flow/test/test_objspace.py
+++ b/pypy/objspace/flow/test/test_objspace.py
@@ -501,6 +501,24 @@
             assert op.args[1].value == 3
 
     #__________________________________________________________
+
+    def wearetranslated(x):
+        from pypy.rlib.objectmodel import we_are_translated
+        if we_are_translated():
+            return x
+        else:
+            some_name_error_here
+
+    def test_wearetranslated(self):
+        x = self.codetest(self.wearetranslated)
+        from pypy.translator.simplify import join_blocks
+        join_blocks(x)
+        # check that 'x' is an empty graph
+        assert len(x.startblock.operations) == 0
+        assert len(x.startblock.exits) == 1
+        assert x.startblock.exits[0].target is x.returnblock
+
+    #__________________________________________________________
     def jump_target_specialization(x):
         if x:
             n = 5
diff --git a/pypy/objspace/std/test/test_mapdict.py b/pypy/objspace/std/test/test_mapdict.py
--- a/pypy/objspace/std/test/test_mapdict.py
+++ b/pypy/objspace/std/test/test_mapdict.py
@@ -1000,45 +1000,57 @@
 
     def test_mix_classes(self):
         import __pypy__
-        class A(object):
-            def f(self):
-                return 42
-        class B(object):
-            def f(self):
-                return 43
-        class C(object):
-            def f(self):
-                return 44
-        l = [A(), B(), C()] * 10
-        __pypy__.reset_method_cache_counter()
-        # 'exec' to make sure that a.f() is compiled with CALL_METHOD
-        exec """for i, a in enumerate(l):
-                    assert a.f() == 42 + i % 3
-"""
-        cache_counter = __pypy__.mapdict_cache_counter("f")
-        assert cache_counter[0] >= 15
-        assert cache_counter[1] >= 3 # should be (27, 3)
-        assert sum(cache_counter) == 30
+        seen = []
+        for i in range(20):
+            class A(object):
+                def f(self):
+                    return 42
+            class B(object):
+                def f(self):
+                    return 43
+            class C(object):
+                def f(self):
+                    return 44
+            l = [A(), B(), C()] * 10
+            __pypy__.reset_method_cache_counter()
+            # 'exec' to make sure that a.f() is compiled with CALL_METHOD
+            exec """for i, a in enumerate(l):
+                        assert a.f() == 42 + i % 3
+            """ in locals()
+            cache_counter = __pypy__.mapdict_cache_counter("f")
+            if cache_counter == (27, 3):
+                break
+            # keep them alive, to make sure that on the
+            # next try they have difference addresses
+            seen.append((l, cache_counter))
+        else:
+            assert 0, "failed: got %r" % ([got[1] for got in seen],)
 
     def test_mix_classes_attribute(self):
         import __pypy__
-        class A(object):
-            def __init__(self):
-                self.x = 42
-        class B(object):
-            def __init__(self):
-                self.x = 43
-        class C(object):
-            def __init__(self):
-                self.x = 44
-        l = [A(), B(), C()] * 10
-        __pypy__.reset_method_cache_counter()
-        for i, a in enumerate(l):
-            assert a.x == 42 + i % 3
-        cache_counter = __pypy__.mapdict_cache_counter("x")
-        assert cache_counter[0] >= 15
-        assert cache_counter[1] >= 3 # should be (27, 3)
-        assert sum(cache_counter) == 30
+        seen = []
+        for i in range(20):
+            class A(object):
+                def __init__(self):
+                    self.x = 42
+            class B(object):
+                def __init__(self):
+                    self.x = 43
+            class C(object):
+                def __init__(self):
+                    self.x = 44
+            l = [A(), B(), C()] * 10
+            __pypy__.reset_method_cache_counter()
+            for i, a in enumerate(l):
+                assert a.x == 42 + i % 3
+            cache_counter = __pypy__.mapdict_cache_counter("x")
+            if cache_counter == (27, 3):
+                break
+            # keep them alive, to make sure that on the
+            # next try they have difference addresses
+            seen.append((l, cache_counter))
+        else:
+            assert 0, "failed: got %r" % ([got[1] for got in seen],)
 
 class TestDictSubclassShortcutBug(object):
     def setup_class(cls):
diff --git a/pypy/objspace/std/test/test_unicodeobject.py b/pypy/objspace/std/test/test_unicodeobject.py
--- a/pypy/objspace/std/test/test_unicodeobject.py
+++ b/pypy/objspace/std/test/test_unicodeobject.py
@@ -211,6 +211,20 @@
         assert u'hello '.capitalize() == u'Hello '
         assert u'aaaa'.capitalize() == u'Aaaa'
         assert u'AaAa'.capitalize() == u'Aaaa'
+        # check that titlecased chars are lowered correctly
+        # \u1ffc is the titlecased char
+        assert (u'\u1ff3\u1ff3\u1ffc\u1ffc'.capitalize() ==
+                u'\u1ffc\u1ff3\u1ff3\u1ff3')
+        # check with cased non-letter chars
+        assert (u'\u24c5\u24ce\u24c9\u24bd\u24c4\u24c3'.capitalize() ==
+                u'\u24c5\u24e8\u24e3\u24d7\u24de\u24dd')
+        assert (u'\u24df\u24e8\u24e3\u24d7\u24de\u24dd'.capitalize() ==
+                u'\u24c5\u24e8\u24e3\u24d7\u24de\u24dd')
+        assert u'\u2160\u2161\u2162'.capitalize() == u'\u2160\u2171\u2172'
+        assert u'\u2170\u2171\u2172'.capitalize() == u'\u2160\u2171\u2172'
+        # check with Ll chars with no upper - nothing changes here
+        assert (u'\u019b\u1d00\u1d86\u0221\u1fb7'.capitalize() ==
+                u'\u019b\u1d00\u1d86\u0221\u1fb7')
 
     def test_rjust(self):
         s = u"abc"
@@ -834,4 +848,4 @@
         assert type(b) is unicode
         assert b == u'hello \u1234'
 
-        assert u'%s' % S(u'mar\xe7') == u'mar\xe7'
\ No newline at end of file
+        assert u'%s' % S(u'mar\xe7') == u'mar\xe7'
diff --git a/pypy/rlib/_rsocket_rffi.py b/pypy/rlib/_rsocket_rffi.py
--- a/pypy/rlib/_rsocket_rffi.py
+++ b/pypy/rlib/_rsocket_rffi.py
@@ -455,9 +455,9 @@
 #    eci = ExternalCompilationInfo(includes=includes, libraries=libraries,
 #                                  separate_module_sources=sources)
 
-def external(name, args, result):
+def external(name, args, result, **kwds):
     return rffi.llexternal(name, args, result, compilation_info=eci,
-                           calling_conv=calling_conv)
+                           calling_conv=calling_conv, **kwds)
 
 def external_c(name, args, result, **kwargs):
     return rffi.llexternal(name, args, result, compilation_info=eci,
@@ -476,9 +476,9 @@
 socket = external('socket', [rffi.INT, rffi.INT, rffi.INT], socketfd_type)
 
 if WIN32:
-    socketclose = external('closesocket', [socketfd_type], rffi.INT)
+    socketclose = external('closesocket', [socketfd_type], rffi.INT, threadsafe=False)
 else:
-    socketclose = external('close', [socketfd_type], rffi.INT)
+    socketclose = external('close', [socketfd_type], rffi.INT, threadsafe=False)
 
 socketconnect = external('connect', [socketfd_type, sockaddr_ptr, socklen_t], rffi.INT)
 
diff --git a/pypy/rlib/objectmodel.py b/pypy/rlib/objectmodel.py
--- a/pypy/rlib/objectmodel.py
+++ b/pypy/rlib/objectmodel.py
@@ -157,7 +157,7 @@
 
 def we_are_translated():
     return False
-# annotation -> True
+# annotation -> True (replaced by the flow objspace)
 
 def keepalive_until_here(*values):
     pass
diff --git a/pypy/rlib/rbigint.py b/pypy/rlib/rbigint.py
--- a/pypy/rlib/rbigint.py
+++ b/pypy/rlib/rbigint.py
@@ -215,6 +215,7 @@
         # then modify the result.
         return _decimalstr_to_bigint(s)
 
+    @jit.elidable
     def toint(self):
         """
         Get an integer from a bigint object.
@@ -294,6 +295,7 @@
     def ne(self, other):
         return not self.eq(other)
 
+    @jit.elidable
     def lt(self, other):
         if self.sign > other.sign:
             return False
@@ -1603,7 +1605,7 @@
     elif (base & (base - 1)) == 0:
         # JRH: special case for power-of-2 bases
         accum = 0
-        accumbits = 0  # # of bits in accum 
+        accumbits = 0  # # of bits in accum
         basebits = 1   # # of bits in base-1
         i = base
         while 1:
diff --git a/pypy/rlib/rdynload.py b/pypy/rlib/rdynload.py
--- a/pypy/rlib/rdynload.py
+++ b/pypy/rlib/rdynload.py
@@ -63,7 +63,7 @@
 
 if not _WIN32:
     c_dlopen = external('dlopen', [rffi.CCHARP, rffi.INT], rffi.VOIDP)
-    c_dlclose = external('dlclose', [rffi.VOIDP], rffi.INT)
+    c_dlclose = external('dlclose', [rffi.VOIDP], rffi.INT, threadsafe=False)
     c_dlerror = external('dlerror', [], rffi.CCHARP)
     c_dlsym = external('dlsym', [rffi.VOIDP, rffi.CCHARP], rffi.VOIDP)
 
diff --git a/pypy/rlib/rmmap.py b/pypy/rlib/rmmap.py
--- a/pypy/rlib/rmmap.py
+++ b/pypy/rlib/rmmap.py
@@ -118,7 +118,7 @@
     has_mremap = cConfig['has_mremap']
     c_mmap, c_mmap_safe = external('mmap', [PTR, size_t, rffi.INT, rffi.INT,
                                rffi.INT, off_t], PTR)
-    c_munmap, c_munmap_safe = external('munmap', [PTR, size_t], rffi.INT)
+    _, c_munmap_safe = external('munmap', [PTR, size_t], rffi.INT)
     c_msync, _ = external('msync', [PTR, size_t, rffi.INT], rffi.INT)
     if has_mremap:
         c_mremap, _ = external('mremap',
@@ -174,7 +174,8 @@
     DuplicateHandle = winexternal('DuplicateHandle', [HANDLE, HANDLE, HANDLE, LPHANDLE, DWORD, BOOL, DWORD], BOOL)
     CreateFileMapping = winexternal('CreateFileMappingA', [HANDLE, rwin32.LPSECURITY_ATTRIBUTES, DWORD, DWORD, DWORD, LPCSTR], HANDLE)
     MapViewOfFile = winexternal('MapViewOfFile', [HANDLE, DWORD, DWORD, DWORD, SIZE_T], LPCSTR)##!!LPVOID)
-    UnmapViewOfFile = winexternal('UnmapViewOfFile', [LPCVOID], BOOL)
+    UnmapViewOfFile = winexternal('UnmapViewOfFile', [LPCVOID], BOOL,
+                                  threadsafe=False)
     FlushViewOfFile = winexternal('FlushViewOfFile', [LPCVOID, SIZE_T], BOOL)
     SetFilePointer = winexternal('SetFilePointer', [HANDLE, LONG, PLONG, DWORD], DWORD)
     SetEndOfFile = winexternal('SetEndOfFile', [HANDLE], BOOL)
@@ -294,7 +295,7 @@
                 os.close(self.fd)
                 self.fd = -1
             if self.size > 0:
-                c_munmap(self.getptr(0), self.size)
+                c_munmap_safe(self.getptr(0), self.size)
                 self.setdata(NODATA, 0)
 
     def __del__(self):
diff --git a/pypy/rlib/ropenssl.py b/pypy/rlib/ropenssl.py
--- a/pypy/rlib/ropenssl.py
+++ b/pypy/rlib/ropenssl.py
@@ -273,7 +273,7 @@
 EVP_MD_CTX_copy = external(
     'EVP_MD_CTX_copy', [EVP_MD_CTX, EVP_MD_CTX], rffi.INT)
 EVP_MD_CTX_cleanup = external(
-    'EVP_MD_CTX_cleanup', [EVP_MD_CTX], rffi.INT)
+    'EVP_MD_CTX_cleanup', [EVP_MD_CTX], rffi.INT, threadsafe=False)
 
 def init_ssl():
     libssl_SSL_load_error_strings()
diff --git a/pypy/rlib/runicode.py b/pypy/rlib/runicode.py
--- a/pypy/rlib/runicode.py
+++ b/pypy/rlib/runicode.py
@@ -1505,17 +1505,16 @@
             rffi.free_nonmovingbuffer(s, dataptr)
 
     def unicode_encode_mbcs(p, size, errors, errorhandler=None):
+        if size == 0:
+            return ''
         dataptr = rffi.get_nonmoving_unicodebuffer(p)
         try:
             # first get the size of the result
-            if size > 0:
-                mbcssize = WideCharToMultiByte(CP_ACP, 0,
-                                               dataptr, size, None, 0,
-                                               None, None)
-                if mbcssize == 0:
-                    raise rwin32.lastWindowsError()
-            else:
-                mbcssize = 0
+            mbcssize = WideCharToMultiByte(CP_ACP, 0,
+                                           dataptr, size, None, 0,
+                                           None, None)
+            if mbcssize == 0:
+                raise rwin32.lastWindowsError()
 
             raw_buf, gc_buf = rffi.alloc_buffer(mbcssize)
             try:
diff --git a/pypy/rlib/rwin32.py b/pypy/rlib/rwin32.py
--- a/pypy/rlib/rwin32.py
+++ b/pypy/rlib/rwin32.py
@@ -79,8 +79,9 @@
 for k, v in rffi_platform.configure(CConfig).items():
     globals()[k] = v
 
-def winexternal(name, args, result):
-    return rffi.llexternal(name, args, result, compilation_info=eci, calling_conv='win')
+def winexternal(name, args, result, **kwds):
+    return rffi.llexternal(name, args, result, compilation_info=eci,
+                           calling_conv='win', **kwds)
 
 if WIN32:
     HANDLE = rffi.COpaquePtr(typedef='HANDLE')
@@ -92,7 +93,7 @@
     INVALID_HANDLE_VALUE = rffi.cast(HANDLE, -1)
     PFILETIME = rffi.CArrayPtr(FILETIME)
 
-    GetLastError = winexternal('GetLastError', [], DWORD)
+    GetLastError = winexternal('GetLastError', [], DWORD, threadsafe=False)
     SetLastError = winexternal('SetLastError', [DWORD], lltype.Void)
 
     # In tests, the first call to GetLastError is always wrong, because error
@@ -103,10 +104,10 @@
     GetProcAddress = winexternal('GetProcAddress',
                                  [HMODULE, rffi.CCHARP],
                                  rffi.VOIDP)
-    FreeLibrary = winexternal('FreeLibrary', [HMODULE], BOOL)
+    FreeLibrary = winexternal('FreeLibrary', [HMODULE], BOOL, threadsafe=False)
 
     LocalFree = winexternal('LocalFree', [HLOCAL], DWORD)
-    CloseHandle = winexternal('CloseHandle', [HANDLE], BOOL)
+    CloseHandle = winexternal('CloseHandle', [HANDLE], BOOL, threadsafe=False)
 
     FormatMessage = winexternal(
         'FormatMessageA',
diff --git a/pypy/rlib/rzlib.py b/pypy/rlib/rzlib.py
--- a/pypy/rlib/rzlib.py
+++ b/pypy/rlib/rzlib.py
@@ -131,7 +131,8 @@
     rffi.INT)
 _deflate = zlib_external('deflate', [z_stream_p, rffi.INT], rffi.INT)
 
-_deflateEnd = zlib_external('deflateEnd', [z_stream_p], rffi.INT)
+_deflateEnd = zlib_external('deflateEnd', [z_stream_p], rffi.INT,
+                            threadsafe=False)
 
 def _deflateInit2(stream, level, method, wbits, memlevel, strategy):
     size = rffi.sizeof(z_stream)
@@ -149,7 +150,8 @@
     rffi.INT)
 _inflate = zlib_external('inflate', [z_stream_p, rffi.INT], rffi.INT)
 
-_inflateEnd = zlib_external('inflateEnd', [z_stream_p], rffi.INT)
+_inflateEnd = zlib_external('inflateEnd', [z_stream_p], rffi.INT,
+                            threadsafe=False)
 
 def _inflateInit2(stream, wbits):
     size = rffi.sizeof(z_stream)
diff --git a/pypy/rpython/lltypesystem/lloperation.py b/pypy/rpython/lltypesystem/lloperation.py
--- a/pypy/rpython/lltypesystem/lloperation.py
+++ b/pypy/rpython/lltypesystem/lloperation.py
@@ -528,6 +528,7 @@
     'debug_catch_exception':   LLOp(),
     'debug_reraise_traceback': LLOp(),
     'debug_print_traceback':   LLOp(),
+    'debug_nonnull_pointer':   LLOp(canrun=True),
 
     # __________ instrumentation _________
     'instrument_count':     LLOp(),
diff --git a/pypy/rpython/lltypesystem/opimpl.py b/pypy/rpython/lltypesystem/opimpl.py
--- a/pypy/rpython/lltypesystem/opimpl.py
+++ b/pypy/rpython/lltypesystem/opimpl.py
@@ -526,6 +526,9 @@
 def op_have_debug_prints():
     return debug.have_debug_prints()
 
+def op_debug_nonnull_pointer(x):
+    assert x
+
 def op_gc_stack_bottom():
     pass       # marker for trackgcroot.py
 
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
@@ -755,21 +755,18 @@
             return hlstrtype(gc_buf)
 
         new_buf = lltype.malloc(STRTYPE, needed_size)
-        try:
-            str_chars_offset = (offsetof(STRTYPE, 'chars') + \
-                                itemoffsetof(STRTYPE.chars, 0))
-            if gc_buf:
-                src = cast_ptr_to_adr(gc_buf) + str_chars_offset
-            else:
-                src = cast_ptr_to_adr(raw_buf) + itemoffsetof(TYPEP.TO, 0)
-            dest = cast_ptr_to_adr(new_buf) + str_chars_offset
-            ## FIXME: This is bad, because dest could potentially move
-            ## if there are threads involved.
-            raw_memcopy(src, dest,
-                        llmemory.sizeof(ll_char_type) * needed_size)
-            return hlstrtype(new_buf)
-        finally:
-            keepalive_until_here(new_buf)
+        str_chars_offset = (offsetof(STRTYPE, 'chars') + \
+                            itemoffsetof(STRTYPE.chars, 0))
+        if gc_buf:
+            src = cast_ptr_to_adr(gc_buf) + str_chars_offset
+        else:
+            src = cast_ptr_to_adr(raw_buf) + itemoffsetof(TYPEP.TO, 0)
+        dest = cast_ptr_to_adr(new_buf) + str_chars_offset
+        raw_memcopy(src, dest,
+                    llmemory.sizeof(ll_char_type) * needed_size)
+        keepalive_until_here(gc_buf)
+        keepalive_until_here(new_buf)
+        return hlstrtype(new_buf)
 
     # (char*, str) -> None
     def keep_buffer_alive_until_here(raw_buf, gc_buf):
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
@@ -3,6 +3,7 @@
 from pypy.rpython.error import TyperError
 from pypy.rlib.objectmodel import malloc_zero_filled, we_are_translated
 from pypy.rlib.objectmodel import _hash_string, enforceargs
+from pypy.rlib.objectmodel import keepalive_until_here
 from pypy.rlib.debug import ll_assert
 from pypy.rlib.jit import elidable, we_are_jitted, dont_look_inside
 from pypy.rlib.rarithmetic import ovfcheck
@@ -67,6 +68,8 @@
         src = llmemory.cast_ptr_to_adr(src) + _str_ofs(srcstart)
         dst = llmemory.cast_ptr_to_adr(dst) + _str_ofs(dststart)
         llmemory.raw_memcopy(src, dst, llmemory.sizeof(CHAR_TP) * length)
+        keepalive_until_here(src)
+        keepalive_until_here(dst)
     copy_string_contents._always_inline_ = True
     #copy_string_contents.oopspec = (
     #    '%s.copy_contents(src, dst, srcstart, dststart, length)' % name)
diff --git a/pypy/rpython/memory/gc/minimark.py b/pypy/rpython/memory/gc/minimark.py
--- a/pypy/rpython/memory/gc/minimark.py
+++ b/pypy/rpython/memory/gc/minimark.py
@@ -1697,8 +1697,8 @@
         #
         # Add the roots from the other sources.
         self.root_walker.walk_roots(
-            MiniMarkGC._collect_ref,  # stack roots
-            MiniMarkGC._collect_ref,  # static in prebuilt non-gc structures
+            MiniMarkGC._collect_ref_stk, # stack roots
+            MiniMarkGC._collect_ref_stk, # static in prebuilt non-gc structures
             None)   # we don't need the static in all prebuilt gc objects
         #
         # If we are in an inner collection caused by a call to a finalizer,
@@ -1715,8 +1715,10 @@
     def _collect_obj(obj, objects_to_trace):
         objects_to_trace.append(obj)
 
-    def _collect_ref(self, root):
-        self.objects_to_trace.append(root.address[0])
+    def _collect_ref_stk(self, root):
+        obj = root.address[0]
+        llop.debug_nonnull_pointer(lltype.Void, obj)
+        self.objects_to_trace.append(obj)
 
     def _collect_ref_rec(self, root, ignored):
         self.objects_to_trace.append(root.address[0])
diff --git a/pypy/rpython/module/ll_os.py b/pypy/rpython/module/ll_os.py
--- a/pypy/rpython/module/ll_os.py
+++ b/pypy/rpython/module/ll_os.py
@@ -877,7 +877,8 @@
 
     @registering(os.close)
     def register_os_close(self):
-        os_close = self.llexternal(underscore_on_windows+'close', [rffi.INT], rffi.INT)
+        os_close = self.llexternal(underscore_on_windows+'close', [rffi.INT],
+                                   rffi.INT, threadsafe=False)
         
         def close_llimpl(fd):
             error = rffi.cast(lltype.Signed, os_close(rffi.cast(rffi.INT, fd)))
diff --git a/pypy/rpython/module/ll_os_stat.py b/pypy/rpython/module/ll_os_stat.py
--- a/pypy/rpython/module/ll_os_stat.py
+++ b/pypy/rpython/module/ll_os_stat.py
@@ -21,7 +21,7 @@
 #   sub-second timestamps.
 # - TIMESPEC is defined when the "struct stat" contains st_atim field.
 
-if sys.platform.startswith('linux'):
+if sys.platform.startswith('linux') or sys.platform.startswith('openbsd'):
     TIMESPEC = platform.Struct('struct timespec',
                                [('tv_sec', rffi.TIME_T),
                                 ('tv_nsec', rffi.LONG)])
@@ -185,9 +185,9 @@
 def build_stat_result(st):
     # only for LL backends
     if TIMESPEC is not None:
-        atim = st.c_st_atim; atime = atim.c_tv_sec + 1E-9 * atim.c_tv_nsec
-        mtim = st.c_st_mtim; mtime = mtim.c_tv_sec + 1E-9 * mtim.c_tv_nsec
-        ctim = st.c_st_ctim; ctime = ctim.c_tv_sec + 1E-9 * ctim.c_tv_nsec
+        atim = st.c_st_atim; atime = int(atim.c_tv_sec) + 1E-9 * int(atim.c_tv_nsec)
+        mtim = st.c_st_mtim; mtime = int(mtim.c_tv_sec) + 1E-9 * int(mtim.c_tv_nsec)
+        ctim = st.c_st_ctim; ctime = int(ctim.c_tv_sec) + 1E-9 * int(ctim.c_tv_nsec)
     else:
         atime = st.c_st_atime
         mtime = st.c_st_mtime
diff --git a/pypy/rpython/raddress.py b/pypy/rpython/raddress.py
--- a/pypy/rpython/raddress.py
+++ b/pypy/rpython/raddress.py
@@ -7,7 +7,6 @@
 from pypy.rpython.rptr import PtrRepr
 from pypy.rpython.lltypesystem import lltype
 from pypy.rlib.rarithmetic import r_uint
-from pypy.rlib.objectmodel import we_are_translated
 
 
 class __extend__(annmodel.SomeAddress):
diff --git a/pypy/rpython/rbuiltin.py b/pypy/rpython/rbuiltin.py
--- a/pypy/rpython/rbuiltin.py
+++ b/pypy/rpython/rbuiltin.py
@@ -283,10 +283,6 @@
         v_error = hop.inputarg(lltype.Signed, arg=1)
         r_self.setfield(v_self, 'winerror', v_error, hop.llops)
 
-def rtype_we_are_translated(hop):
-    hop.exception_cannot_occur()
-    return hop.inputconst(lltype.Bool, True)
-
 def rtype_hlinvoke(hop):
     _, s_repr = hop.r_s_popfirstarg()
     r_callable = s_repr.const
@@ -553,7 +549,6 @@
 BUILTIN_TYPER[lltype.Ptr] = rtype_const_result
 BUILTIN_TYPER[lltype.runtime_type_info] = rtype_runtime_type_info
 BUILTIN_TYPER[rarithmetic.intmask] = rtype_intmask
-BUILTIN_TYPER[objectmodel.we_are_translated] = rtype_we_are_translated
 
 BUILTIN_TYPER[objectmodel.hlinvoke] = rtype_hlinvoke
 
diff --git a/pypy/rpython/tool/rffi_platform.py b/pypy/rpython/tool/rffi_platform.py
--- a/pypy/rpython/tool/rffi_platform.py
+++ b/pypy/rpython/tool/rffi_platform.py
@@ -11,6 +11,7 @@
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
 from pypy.translator.platform import CompilationError
 from pypy.tool.udir import udir
+from pypy.tool.autopath import pypydir
 from pypy.rlib.rarithmetic import r_uint, r_longlong, r_ulonglong, intmask
 
 # ____________________________________________________________
@@ -699,6 +700,13 @@
 
 # ____________________________________________________________
 
+PYPY_EXTERNAL_DIR = py.path.local(pypydir).join('..', '..')
+# XXX make this configurable
+if sys.platform == 'win32':
+    libdir = py.path.local('c:/buildslave/support') # on the bigboard buildbot
+    if libdir.check():
+        PYPY_EXTERNAL_DIR = libdir
+
 def configure_external_library(name, eci, configurations,
                                symbol=None, _cache={}):
     """try to find the external library.
@@ -740,11 +748,7 @@
             if prefix and not os.path.isabs(prefix):
                 import glob
 
-                # XXX make this a global option?
-                from pypy.tool.autopath import pypydir
-                external_dir = py.path.local(pypydir).join('..', '..')
-
-                entries = glob.glob(str(external_dir.join(prefix + '*')))
+                entries = glob.glob(str(PYPY_EXTERNAL_DIR.join(prefix + '*')))
                 if entries:
                     # Get last version
                     prefix = sorted(entries)[-1]
@@ -780,14 +784,16 @@
         from pypy.translator.platform import platform
     if sys.platform == 'win32':
         library_dir = 'Release'
+        libraries = ['gc']
         includes=['gc.h']
     else:
         library_dir = ''
+        libraries = ['gc', 'dl']
         includes=['gc/gc.h']
     eci = ExternalCompilationInfo(
         platform=platform,
         includes=includes,
-        libraries=['gc', 'dl'],
+        libraries=libraries,
         )
     return configure_external_library(
         'gc', eci,
diff --git a/pypy/tool/pytest/test/test_pytestsupport.py b/pypy/tool/pytest/test/test_pytestsupport.py
--- a/pypy/tool/pytest/test/test_pytestsupport.py
+++ b/pypy/tool/pytest/test/test_pytestsupport.py
@@ -2,7 +2,6 @@
 from pypy.interpreter.gateway import app2interp_temp
 from pypy.interpreter.argument import Arguments
 from pypy.interpreter.pycode import PyCode
-from pypy.interpreter.pyframe import PyFrame
 from pypy.tool.pytest.appsupport import (AppFrame, build_pytest_assertion,
     AppExceptionInfo, interpret)
 import py
@@ -20,7 +19,7 @@
 def test_AppFrame(space):
     import sys
     co = PyCode._from_code(space, somefunc.func_code)
-    pyframe = PyFrame(space, co, space.newdict(), None)
+    pyframe = space.FrameClass(space, co, space.newdict(), None)
     runner = AppFrame(space, pyframe)
     interpret("f = lambda x: x+1", runner, should_fail=False)
     msg = interpret("assert isinstance(f(2), float)", runner)
diff --git a/pypy/tool/release/force-builds.py b/pypy/tool/release/force-builds.py
--- a/pypy/tool/release/force-builds.py
+++ b/pypy/tool/release/force-builds.py
@@ -26,7 +26,7 @@
     'pypy-c-app-level-win-x86-32',
     'pypy-c-jit-linux-x86-32',
     'pypy-c-jit-linux-x86-64',
-#    'pypy-c-jit-macosx-x86-32',
+    'pypy-c-jit-macosx-x86-64',
     'pypy-c-jit-win-x86-32',
 ]
 
diff --git a/pypy/tool/release/package.py b/pypy/tool/release/package.py
--- a/pypy/tool/release/package.py
+++ b/pypy/tool/release/package.py
@@ -50,8 +50,8 @@
             pypy_c_dir = py.path.local(override_pypy_c).dirname
         else:
             pypy_c_dir = basedir.join('pypy', 'translator', 'goal')
-        pypy_c = pypy_c_dir.join(rename_pypy_c + '.exe')
-        libpypy_c = pypy_c_dir.join('lib' + rename_pypy_c + '.dll')
+        pypy_c = pypy_c_dir.join('pypy-c.exe')
+        libpypy_c = pypy_c_dir.join('libpypy-c.dll')
         binaries = [(pypy_c, pypy_c.basename),
                     (libpypy_c, libpypy_c.basename),
                     (pypy_c_dir.join('libexpat.dll'), 'libexpat.dll')]
diff --git a/pypy/translator/c/funcgen.py b/pypy/translator/c/funcgen.py
--- a/pypy/translator/c/funcgen.py
+++ b/pypy/translator/c/funcgen.py
@@ -820,6 +820,11 @@
                                          cdecl(typename, ''))
         return result
 
+    def OP_DEBUG_NONNULL_POINTER(self, op):
+        expr = self.expr(op.args[0])
+        return 'if ((-8192 <= (long)%s) && (((long)%s) < 8192)) abort();' % (
+            expr, expr)
+
     def OP_INSTRUMENT_COUNT(self, op):
         counter_label = op.args[1].value
         self.db.instrument_ncounter = max(self.db.instrument_ncounter,
diff --git a/pypy/translator/c/gc.py b/pypy/translator/c/gc.py
--- a/pypy/translator/c/gc.py
+++ b/pypy/translator/c/gc.py
@@ -228,7 +228,7 @@
         if sys.platform.startswith('linux'):
             pre_include_bits += ["#define _REENTRANT 1",
                                  "#define GC_LINUX_THREADS 1"]
-        if sys.platform != "win32":
+        if sys.platform != "win32" and not sys.platform.startswith("openbsd"):
             # GC_REDIRECT_TO_LOCAL is not supported on Win32 by gc6.8
             pre_include_bits += ["#define GC_REDIRECT_TO_LOCAL 1"]
 
diff --git a/pypy/translator/c/gcc/instruction.py b/pypy/translator/c/gcc/instruction.py
--- a/pypy/translator/c/gcc/instruction.py
+++ b/pypy/translator/c/gcc/instruction.py
@@ -68,15 +68,21 @@
 class Insn(object):
     _args_ = []
     _locals_ = []
+    hack = None
 
     def __repr__(self):
-        return '%s(%s)' % (self.__class__.__name__,
+        return '%s(%s) --- %r' % (self.__class__.__name__,
                            ', '.join([str(getattr(self, name))
-                                      for name in self._args_]))
+                                      for name in self._args_]),
+                                  self.hack)
     def requestgcroots(self, tracker):
         return {}
 
     def source_of(self, localvar, tag):
+        if tag is None:
+            if self.hack is None:
+                self.hack = set()
+            self.hack.add(localvar)
         return localvar
 
     def all_sources_of(self, localvar):
@@ -139,7 +145,7 @@
     def source_of(self, localvar, tag):
         if localvar == self.target:
             return somenewvalue
-        return localvar
+        return Insn.source_of(self, localvar, tag)
 
     def all_sources_of(self, localvar):
         if localvar == self.target:
@@ -157,7 +163,7 @@
     def source_of(self, localvar, tag):
         if localvar == self.target:
             return self.source
-        return localvar
+        return Insn.source_of(self, localvar, tag)
 
     def all_sources_of(self, localvar):
         if localvar == self.target:
diff --git a/pypy/translator/c/gcc/test/elf64/track_zero.s b/pypy/translator/c/gcc/test/elf64/track_zero.s
new file mode 100644
--- /dev/null
+++ b/pypy/translator/c/gcc/test/elf64/track_zero.s
@@ -0,0 +1,18 @@
+	.type	pypy_g_do_call_1, @function
+pypy_g_do_call_1:
+	pushq	%rbx
+	pushq	%r12
+	movq	%rdi, %rbx
+	movq	%rsi, %r12
+	call	number1
+	;; expected {16(%rsp) | 8(%rsp), (%rsp), %r13, %r14, %r15, %rbp | %r12}
+	testq	%rbx, %rbx	; here rbx is an integer, not a gc ref
+	je .L1			; if rbx==0, jump to L1, where rbx==NULLGCREF
+	movq	(%rax), %rbx	; else load a gc ref
+.L1:
+	/* GCROOT %rbx */
+	/* GCROOT %r12 */
+	popq	%r12
+	popq	%rbx
+	ret
+	.size	pypy_g_do_call_1, .-pypy_g_do_call_1
diff --git a/pypy/translator/c/gcc/test/elf64/track_zero_2.s b/pypy/translator/c/gcc/test/elf64/track_zero_2.s
new file mode 100644
--- /dev/null
+++ b/pypy/translator/c/gcc/test/elf64/track_zero_2.s
@@ -0,0 +1,18 @@
+	.type	pypy_g_do_call_1, @function
+pypy_g_do_call_1:
+	pushq	%rbx
+	pushq	%r12
+	movq	%rdi, %rbx
+	movq	%rsi, %r12
+	call	number1
+	;; expected {16(%rsp) | 8(%rsp), (%rsp), %r13, %r14, %r15, %rbp | %rbx, %r12}
+	testq	%rbx, %rbx
+	je .L1
+	movq	(%rax), %r12
+.L1:
+	/* GCROOT %rbx */
+	/* GCROOT %r12 */
+	popq	%r12
+	popq	%rbx
+	ret
+	.size	pypy_g_do_call_1, .-pypy_g_do_call_1
diff --git a/pypy/translator/c/gcc/test/elf64/track_zero_3.s b/pypy/translator/c/gcc/test/elf64/track_zero_3.s
new file mode 100644
--- /dev/null
+++ b/pypy/translator/c/gcc/test/elf64/track_zero_3.s
@@ -0,0 +1,14 @@
+	.type	pypy_g_do_call_1, @function
+pypy_g_do_call_1:
+	pushq	%rbx
+	movq	%rdi, %rbx
+	call	number1
+	;; expected {8(%rsp) | (%rsp), %r12, %r13, %r14, %r15, %rbp | %rbx}
+	testq	%rax, %rax
+	je .L1
+	call	RPyAssertFailed
+.L1:
+	/* GCROOT %rbx */
+	popq	%rbx
+	ret
+	.size	pypy_g_do_call_1, .-pypy_g_do_call_1
diff --git a/pypy/translator/c/gcc/test/elf64/track_zero_4.s b/pypy/translator/c/gcc/test/elf64/track_zero_4.s
new file mode 100644
--- /dev/null
+++ b/pypy/translator/c/gcc/test/elf64/track_zero_4.s
@@ -0,0 +1,18 @@
+	.type	pypy_g_do_call_1, @function
+pypy_g_do_call_1:
+	pushq	%rbx
+	pushq	%r12
+	movq	%rdi, %rbx
+	movq	%rsi, %r12
+	call	number1
+	;; expected {16(%rsp) | 8(%rsp), (%rsp), %r13, %r14, %r15, %rbp | %r12}
+	testq	%rbx, %rbx
+	movq	%r12, %rbx
+	je .L1
+	movq	(%rax), %rbx
+.L1:
+	/* GCROOT %rbx */
+	popq	%r12
+	popq	%rbx
+	ret
+	.size	pypy_g_do_call_1, .-pypy_g_do_call_1
diff --git a/pypy/translator/c/gcc/trackgcroot.py b/pypy/translator/c/gcc/trackgcroot.py
--- a/pypy/translator/c/gcc/trackgcroot.py
+++ b/pypy/translator/c/gcc/trackgcroot.py
@@ -163,6 +163,9 @@
         # Add the instruction to the list, and link it to the previous one.
         previnsn = self.insns[-1]
         self.insns.append(insn)
+        if (isinstance(insn, (InsnSetLocal, InsnCopyLocal)) and
+            insn.target == self.tested_for_zero):
+            self.tested_for_zero = None
 
         try:
             lst = insn.previous_insns
@@ -173,6 +176,7 @@
 
     def parse_instructions(self):
         self.insns = [InsnFunctionStart(self.CALLEE_SAVE_REGISTERS, self.WORD)]
+        self.tested_for_zero = None
         ignore_insns = False
         for lineno, line in enumerate(self.lines):
             if lineno < self.skip:
@@ -186,6 +190,14 @@
             elif match:
                 if not ignore_insns:
                     opname = match.group(1)
+                    #
+                    try:
+                        cf = self.OPS_WITH_PREFIXES_CHANGING_FLAGS[opname]
+                    except KeyError:
+                        cf = self.find_missing_changing_flags(opname)
+                    if cf:
+                        self.tested_for_zero = None
+                    #
                     try:
                         meth = getattr(self, 'visit_' + opname)
                     except AttributeError:
@@ -222,6 +234,15 @@
                 raise UnrecognizedOperation(opname)
         setattr(cls, 'visit_' + opname, cls.visit_nop)
 
+    @classmethod
+    def find_missing_changing_flags(cls, opname):
+        prefix = opname
+        while prefix and prefix not in cls.OPS_WITH_PREFIXES_CHANGING_FLAGS:
+            prefix = prefix[:-1]
+        cf = cls.OPS_WITH_PREFIXES_CHANGING_FLAGS.get(prefix, False)
+        cls.OPS_WITH_PREFIXES_CHANGING_FLAGS[opname] = cf
+        return cf
+
     def list_collecting_call_insns(self):
         return [insn for insn in self.insns if isinstance(insn, InsnCall)
                      if insn.name not in self.cannot_collect]
@@ -467,6 +488,19 @@
         'movz', 
         ])
 
+    # a partial list is hopefully good enough for now; it's all to support
+    # only one corner case, tested in elf64/track_zero.s
+    OPS_WITH_PREFIXES_CHANGING_FLAGS = dict.fromkeys([
+        'cmp', 'test', 'lahf', 'cld', 'std', 'rep',
+        'ucomi', 'comi',
+        'add', 'sub', 'xor',
+        'inc', 'dec', 'not', 'neg', 'or', 'and', 'sbb', 'adc',
+        'shl', 'shr', 'sal', 'sar', 'rol', 'ror', 'mul', 'imul', 'div', 'idiv',
+        'bt', 'call', 'int',
+        'jmp',     # not really changing flags, but we shouldn't assume
+                   # anything about the operations on the following lines
+        ], True)
+
     visit_movb = visit_nop
     visit_movw = visit_nop
     visit_addb = visit_nop
@@ -687,11 +721,13 @@
             return InsnRet(self.CALLEE_SAVE_REGISTERS)
         return InsnStop("jump")
     
-    def register_jump_to(self, label):
-        if not isinstance(self.insns[-1], InsnStop):
-            self.labels[label].previous_insns.append(self.insns[-1])
+    def register_jump_to(self, label, lastinsn=None):
+        if lastinsn is None:
+            lastinsn = self.insns[-1]
+        if not isinstance(lastinsn, InsnStop):
+            self.labels[label].previous_insns.append(lastinsn)
 
-    def conditional_jump(self, line):
+    def conditional_jump(self, line, je=False, jne=False):
         match = self.r_jump.match(line)
         if not match:
             match = self.r_jump_rel_label.match(line)
@@ -708,12 +744,22 @@
                 i += 1
         else:
             label = match.group(1)
-        self.register_jump_to(label)
-        return [InsnCondJump(label)]
+        prefix = []
+        lastinsn = None
+        postfix = []
+        if self.tested_for_zero is not None:
+            if je:
+                # generate pseudo-code...
+                prefix = [InsnCopyLocal(self.tested_for_zero, '%tmp'),
+                          InsnSetLocal(self.tested_for_zero)]
+                postfix = [InsnCopyLocal('%tmp', self.tested_for_zero)]
+                lastinsn = prefix[-1]
+            elif jne:
+                postfix = [InsnSetLocal(self.tested_for_zero)]
+        self.register_jump_to(label, lastinsn)
+        return prefix + [InsnCondJump(label)] + postfix
 
     visit_jmpl = visit_jmp
-    visit_je = conditional_jump
-    visit_jne = conditional_jump
     visit_jg = conditional_jump
     visit_jge = conditional_jump
     visit_jl = conditional_jump
@@ -731,6 +777,20 @@
     visit_jc = conditional_jump
     visit_jnc = conditional_jump
 
+    def visit_je(self, line):
+        return self.conditional_jump(line, je=True)
+
+    def visit_jne(self, line):
+        return self.conditional_jump(line, jne=True)
+
+    def _visit_test(self, line):
+        match = self.r_binaryinsn.match(line)
+        source = match.group("source")
+        target = match.group("target")
+        if source == target:
+            self.tested_for_zero = source
+        return []
+
     def _visit_xchg(self, line):
         # only support the format used in VALGRIND_DISCARD_TRANSLATIONS
         # which is to use a marker no-op "xchgl %ebx, %ebx"
@@ -884,6 +944,7 @@
     visit_and = FunctionGcRootTracker._visit_and
 
     visit_xchgl = FunctionGcRootTracker._visit_xchg
+    visit_testl = FunctionGcRootTracker._visit_test
 
     # used in "xor reg, reg" to create a NULL GC ptr
     visit_xorl = FunctionGcRootTracker.binary_insn
@@ -942,6 +1003,7 @@
 
     visit_xorq = FunctionGcRootTracker.binary_insn
     visit_xchgq = FunctionGcRootTracker._visit_xchg
+    visit_testq = FunctionGcRootTracker._visit_test
 
     # FIXME: similar to visit_popl for 32-bit
     def visit_popq(self, line):
diff --git a/pypy/translator/goal/app_main.py b/pypy/translator/goal/app_main.py
--- a/pypy/translator/goal/app_main.py
+++ b/pypy/translator/goal/app_main.py
@@ -33,11 +33,9 @@
         except:
             # not an integer: print it to stderr
             try:
-                stderr = sys.stderr
-            except AttributeError:
+                print >> sys.stderr, exitcode
+            except:
                 pass   # too bad
-            else:
-                stderr.write(exitcode)
             exitcode = 1
     raise SystemExit(exitcode)
 
@@ -424,8 +422,11 @@
     # (relevant in case of "reload(sys)")
     sys.argv[:] = argv
 
-    if (PYTHON26 and not options["ignore_environment"] and os.getenv('PYTHONNOUSERSITE')):
-        options["no_user_site"] = True
+    if PYTHON26 and not options["ignore_environment"]:
+        if os.getenv('PYTHONNOUSERSITE'):
+            options["no_user_site"] = True
+        if os.getenv('PYTHONDONTWRITEBYTECODE'):
+            options["dont_write_bytecode"] = True
 
     if (options["interactive"] or
         (not options["ignore_environment"] and os.getenv('PYTHONINSPECT'))):
@@ -434,7 +435,8 @@
     if PYTHON26 and we_are_translated():
         flags = [options[flag] for flag in sys_flags]
         sys.flags = type(sys.flags)(flags)
-        sys.py3kwarning = sys.flags.py3k_warning
+        sys.py3kwarning = bool(sys.flags.py3k_warning)
+        sys.dont_write_bytecode = bool(sys.flags.dont_write_bytecode)
 
         if sys.py3kwarning:
             print >> sys.stderr, (
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
@@ -252,6 +252,13 @@
         host_factory = Freebsd
     else:
         host_factory = Freebsd_64
+elif "openbsd" in sys.platform:
+    from pypy.translator.platform.openbsd import OpenBSD, OpenBSD_64
+    import platform
+    if platform.architecture()[0] == '32bit':
+        host_factory = OpenBSD
+    else:
+        host_factory = OpenBSD_64
 elif os.name == 'nt':
     from pypy.translator.platform.windows import Windows
     host_factory = Windows
diff --git a/pypy/translator/platform/openbsd.py b/pypy/translator/platform/openbsd.py
new file mode 100644
--- /dev/null
+++ b/pypy/translator/platform/openbsd.py
@@ -0,0 +1,61 @@
+"""Support for OpenBSD."""
+
+import os
+
+from pypy.translator.platform import posix
+
+def get_env(key, default):
+    if key in os.environ:
+        return os.environ[key]
+    else:
+        return default
+
+def get_env_vector(key, default):
+    string = get_env(key, default)
+    # XXX: handle quotes
+    return string.split()
+
+class OpenBSD(posix.BasePosix):
+    name = "openbsd"
+
+    link_flags = get_env_vector("LDFLAGS", '-pthread')
+    cflags = get_env_vector("CFLAGS", "-O3 -pthread -fomit-frame-pointer -D_BSD_SOURCE")
+    standalone_only = []
+    shared_only = []
+    so_ext = 'so'
+    make_cmd = 'gmake'
+
+    def __init__(self, cc=None):
+        if cc is None:
+            cc = get_env("CC", "gcc")
+        super(OpenBSD, self).__init__(cc)
+
+    def _args_for_shared(self, args):
+        return ['-shared'] + args
+
+    def _preprocess_include_dirs(self, include_dirs):
+        res_incl_dirs = list(include_dirs)
+        res_incl_dirs.append(os.path.join(get_env("LOCALBASE", "/usr/local"), "include"))
+        return res_incl_dirs
+
+    def _preprocess_library_dirs(self, library_dirs):
+        res_lib_dirs = list(library_dirs)
+        res_lib_dirs.append(os.path.join(get_env("LOCALBASE", "/usr/local"), "lib"))
+        return res_lib_dirs
+
+    def _include_dirs_for_libffi(self):
+        return [os.path.join(get_env("LOCALBASE", "/usr/local"), "include")]
+
+    def _library_dirs_for_libffi(self):
+        return [os.path.join(get_env("LOCALBASE", "/usr/local"), "lib")]
+
+    def _libs(self, libraries):
+        libraries=set(libraries + ("intl", "iconv", "compat"))
+        return ['-l%s' % lib for lib in libraries if lib not in ["crypt", "dl", "rt"]]
+
+    def check___thread(self):
+        # currently __thread is not supported by Darwin gccs
+        return False
+
+class OpenBSD_64(OpenBSD):
+    shared_only = ('-fPIC',)
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
@@ -231,6 +231,9 @@
             linkflags = self._args_for_shared(linkflags) + [
                 '/EXPORT:$(PYPY_MAIN_FUNCTION)']
         linkflags += self._exportsymbols_link_flags(eci, relto=path)
+        # Make sure different functions end up at different addresses!
+        # This is required for the JIT.
+        linkflags.append('/opt:noicf')
 
         if shared:
             so_name = exe_name.new(purebasename='lib' + exe_name.purebasename,


More information about the pypy-commit mailing list