[pypy-svn] pypy new-dict-proxy: merge default

cfbolz commits-noreply at bitbucket.org
Mon Apr 18 14:11:12 CEST 2011


Author: Carl Friedrich Bolz <cfbolz at gmx.de>
Branch: new-dict-proxy
Changeset: r43448:f0418b95a2b0
Date: 2011-04-18 14:09 +0200
http://bitbucket.org/pypy/pypy/changeset/f0418b95a2b0/

Log:	merge default

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

diff --git a/pypy/rlib/test/test_runicode.py b/pypy/rlib/test/test_runicode.py
--- a/pypy/rlib/test/test_runicode.py
+++ b/pypy/rlib/test/test_runicode.py
@@ -31,22 +31,28 @@
 
     def checkdecode(self, s, encoding):
         decoder = self.getdecoder(encoding)
-        if isinstance(s, str):
-            trueresult = s.decode(encoding)
-        else:
-            trueresult = s
-            s = s.encode(encoding)
+        try:
+            if isinstance(s, str):
+                trueresult = s.decode(encoding)
+            else:
+                trueresult = s
+                s = s.encode(encoding)
+        except LookupError, e:
+            py.test.skip(e)
         result, consumed = decoder(s, len(s), True)
         assert consumed == len(s)
         self.typeequals(trueresult, result)
 
     def checkencode(self, s, encoding):
         encoder = self.getencoder(encoding)
-        if isinstance(s, unicode):
-            trueresult = s.encode(encoding)
-        else:
-            trueresult = s
-            s = s.decode(encoding)
+        try:
+            if isinstance(s, unicode):
+                trueresult = s.encode(encoding)
+            else:
+                trueresult = s
+                s = s.decode(encoding)
+        except LookupError, e:
+            py.test.skip(e)
         result = encoder(s, len(s), True)
         self.typeequals(trueresult, result)
 
@@ -66,9 +72,10 @@
         assert called[0]
         assert "42424242" in result
 
-    def checkdecodeerror(self, s, encoding, start, stop, addstuff=True):
+    def checkdecodeerror(self, s, encoding, start, stop,
+                         addstuff=True, msg=None):
         called = [0]
-        def errorhandler(errors, enc, msg, t, startingpos,
+        def errorhandler(errors, enc, errmsg, t, startingpos,
                          endingpos):
             called[0] += 1
             if called[0] == 1:
@@ -77,6 +84,8 @@
                 assert t is s
                 assert start == startingpos
                 assert stop == endingpos
+                if msg is not None:
+                    assert errmsg == msg
                 return u"42424242", stop
             return u"", endingpos
         decoder = self.getdecoder(encoding)
@@ -90,7 +99,7 @@
 
 
 class TestDecoding(UnicodeTests):
-    
+
     # XXX test bom recognition in utf-16
     # XXX test proper error handling
 
@@ -131,6 +140,96 @@
                          "utf-32 utf-32-be utf-32-le").split():
             self.checkdecode(uni, encoding)
 
+    def test_ascii_error(self):
+        self.checkdecodeerror("abc\xFF\xFF\xFFcde", "ascii", 3, 4)
+
+    def test_utf16_errors(self):
+        # trunkated BOM
+        for s in ["\xff", "\xfe"]:
+            self.checkdecodeerror(s, "utf-16", 0, len(s), addstuff=False)
+
+        for s in [
+                  # unexpected end of data ascii
+                  "\xff\xfeF",
+                  # unexpected end of data
+                  '\xff\xfe\xc0\xdb\x00', '\xff\xfe\xc0\xdb', '\xff\xfe\xc0',
+                  ]:
+            self.checkdecodeerror(s, "utf-16", 2, len(s), addstuff=False)
+        for s in [
+                  # illegal surrogate
+                  "\xff\xfe\xff\xdb\xff\xff",
+                  ]:
+            self.checkdecodeerror(s, "utf-16", 2, 4, addstuff=False)
+
+    def test_utf16_bugs(self):
+        s = '\x80-\xe9\xdeL\xa3\x9b'
+        py.test.raises(UnicodeDecodeError, runicode.str_decode_utf_16_le,
+                       s, len(s), True)
+
+    def test_utf7_bugs(self):
+        u = u'A\u2262\u0391.'
+        assert runicode.unicode_encode_utf_7(u, len(u), None) == 'A+ImIDkQ.'
+
+    def test_utf7_tofrom_utf8_bug(self):
+        def _assert_decu7(input, expected):
+            assert runicode.str_decode_utf_7(input, len(input), None) == (expected, len(input))
+
+        _assert_decu7('+-', u'+')
+        _assert_decu7('+-+-', u'++')
+        _assert_decu7('+-+AOQ-', u'+\xe4')
+        _assert_decu7('+AOQ-', u'\xe4')
+        _assert_decu7('+AOQ-', u'\xe4')
+        _assert_decu7('+AOQ- ', u'\xe4 ')
+        _assert_decu7(' +AOQ-', u' \xe4')
+        _assert_decu7(' +AOQ- ', u' \xe4 ')
+        _assert_decu7('+AOQ-+AOQ-', u'\xe4\xe4')
+
+        s_utf7 = 'Die M+AOQ-nner +AOQ-rgen sich!'
+        s_utf8 = u'Die M&#228;nner &#228;rgen sich!'
+        s_utf8_esc = u'Die M\xe4nner \xe4rgen sich!'
+
+        _assert_decu7(s_utf7, s_utf8_esc)
+        _assert_decu7(s_utf7, s_utf8)
+
+        assert runicode.unicode_encode_utf_7(s_utf8_esc, len(s_utf8_esc), None) == s_utf7
+        assert runicode.unicode_encode_utf_7(s_utf8,     len(s_utf8_esc), None) == s_utf7
+
+    def test_utf7_partial(self):
+        s = u"a+-b".encode('utf-7')
+        assert s == "a+--b"
+        decode = self.getdecoder('utf-7')
+        assert decode(s, 1, None) == (u'a', 1)
+        assert decode(s, 2, None) == (u'a', 1)
+        assert decode(s, 3, None) == (u'a+', 3)
+        assert decode(s, 4, None) == (u'a+-', 4)
+        assert decode(s, 5, None) == (u'a+-b', 5)
+
+    def test_utf7_surrogates(self):
+        encode = self.getencoder('utf-7')
+        u = u'\U000abcde'
+        assert encode(u, len(u), None) == '+2m/c3g-'
+        decode = self.getdecoder('utf-7')
+        s = '+3ADYAA-'
+        raises(UnicodeError, decode, s, len(s), None)
+        def replace_handler(errors, codec, message, input, start, end):
+            return u'?', end
+        assert decode(s, len(s), None, final=True,
+                      errorhandler = replace_handler) == (u'??', len(s))
+
+
+class TestUTF8Decoding(UnicodeTests):
+    def __init__(self):
+        self.decoder = self.getdecoder('utf-8')
+
+    def replace_handler(self, errors, codec, message, input, start, end):
+        return u'\ufffd', end
+
+    def ignore_handler(self, errors, codec, message, input, start, end):
+        return u'', end
+
+    def to_bytestring(self, bytes):
+        return ''.join(chr(int(c, 16)) for c in bytes.split())
+
     def test_single_chars_utf8(self):
         for s in ["\xd7\x90", "\xd6\x96", "\xeb\x96\x95", "\xf0\x90\x91\x93"]:
             self.checkdecode(s, "utf-8")
@@ -140,30 +239,297 @@
         # This test will raise an error with python 3.x
         self.checkdecode(u"\ud800", "utf-8")
 
+    def test_invalid_start_byte(self):
+        """
+        Test that an 'invalid start byte' error is raised when the first byte
+        is not in the ASCII range or is not a valid start byte of a 2-, 3-, or
+        4-bytes sequence. The invalid start byte is replaced with a single
+        U+FFFD when errors='replace'.
+        E.g. <80> is a continuation byte and can appear only after a start byte.
+        """
+        FFFD = u'\ufffd'
+        for byte in '\x80\xA0\x9F\xBF\xC0\xC1\xF5\xFF':
+            raises(UnicodeDecodeError, self.decoder, byte, 1, None, final=True)
+            self.checkdecodeerror(byte, 'utf-8', 0, 1, addstuff=False,
+                                  msg='invalid start byte')
+            assert self.decoder(byte, 1, None, final=True,
+                       errorhandler=self.replace_handler) == (FFFD, 1)
+            assert (self.decoder('aaaa' + byte + 'bbbb', 9, None,
+                        final=True, errorhandler=self.replace_handler) ==
+                        (u'aaaa'+ FFFD + u'bbbb', 9))
+            assert self.decoder(byte, 1, None, final=True,
+                           errorhandler=self.ignore_handler) == (u'', 1)
+            assert (self.decoder('aaaa' + byte + 'bbbb', 9, None,
+                        final=True, errorhandler=self.ignore_handler) ==
+                        (u'aaaabbbb', 9))
+
+    def test_unexpected_end_of_data(self):
+        """
+        Test that an 'unexpected end of data' error is raised when the string
+        ends after a start byte of a 2-, 3-, or 4-bytes sequence without having
+        enough continuation bytes.  The incomplete sequence is replaced with a
+        single U+FFFD when errors='replace'.
+        E.g. in the sequence <F3 80 80>, F3 is the start byte of a 4-bytes
+        sequence, but it's followed by only 2 valid continuation bytes and the
+        last continuation bytes is missing.
+        Note: the continuation bytes must be all valid, if one of them is
+        invalid another error will be raised.
+        """
+        sequences = [
+            'C2', 'DF',
+            'E0 A0', 'E0 BF', 'E1 80', 'E1 BF', 'EC 80', 'EC BF',
+            'ED 80', 'ED 9F', 'EE 80', 'EE BF', 'EF 80', 'EF BF',
+            'F0 90', 'F0 BF', 'F0 90 80', 'F0 90 BF', 'F0 BF 80', 'F0 BF BF',
+            'F1 80', 'F1 BF', 'F1 80 80', 'F1 80 BF', 'F1 BF 80', 'F1 BF BF',
+            'F3 80', 'F3 BF', 'F3 80 80', 'F3 80 BF', 'F3 BF 80', 'F3 BF BF',
+            'F4 80', 'F4 8F', 'F4 80 80', 'F4 80 BF', 'F4 8F 80', 'F4 8F BF'
+        ]
+        FFFD = u'\ufffd'
+        for seq in sequences:
+            seq = self.to_bytestring(seq)
+            raises(UnicodeDecodeError, self.decoder, seq, len(seq),
+                   None, final=True)
+            self.checkdecodeerror(seq, 'utf-8', 0, len(seq), addstuff=False,
+                                  msg='unexpected end of data')
+            assert self.decoder(seq, len(seq), None, final=True,
+                       errorhandler=self.replace_handler) == (FFFD, len(seq))
+            assert (self.decoder('aaaa' + seq + 'bbbb', len(seq) + 8, None,
+                        final=True, errorhandler=self.replace_handler) ==
+                        (u'aaaa'+ FFFD + u'bbbb', len(seq) + 8))
+            assert self.decoder(seq, len(seq), None, final=True,
+                           errorhandler=self.ignore_handler) == (u'', len(seq))
+            assert (self.decoder('aaaa' + seq + 'bbbb', len(seq) + 8, None,
+                        final=True, errorhandler=self.ignore_handler) ==
+                        (u'aaaabbbb', len(seq) + 8))
+
+    def test_invalid_cb_for_2bytes_seq(self):
+        """
+        Test that an 'invalid continuation byte' error is raised when the
+        continuation byte of a 2-bytes sequence is invalid.  The start byte
+        is replaced by a single U+FFFD and the second byte is handled
+        separately when errors='replace'.
+        E.g. in the sequence <C2 41>, C2 is the start byte of a 2-bytes
+        sequence, but 41 is not a valid continuation byte because it's the
+        ASCII letter 'A'.
+        """
+        FFFD = u'\ufffd'
+        FFFDx2 = FFFD * 2
+        sequences = [
+            ('C2 00', FFFD+u'\x00'), ('C2 7F', FFFD+u'\x7f'),
+            ('C2 C0', FFFDx2), ('C2 FF', FFFDx2),
+            ('DF 00', FFFD+u'\x00'), ('DF 7F', FFFD+u'\x7f'),
+            ('DF C0', FFFDx2), ('DF FF', FFFDx2),
+        ]
+        for seq, res in sequences:
+            seq = self.to_bytestring(seq)
+            raises(UnicodeDecodeError, self.decoder, seq, len(seq),
+                   None, final=True)
+            self.checkdecodeerror(seq, 'utf-8', 0, 1, addstuff=False,
+                                  msg='invalid continuation byte')
+            assert self.decoder(seq, len(seq), None, final=True,
+                       errorhandler=self.replace_handler) == (res, len(seq))
+            assert (self.decoder('aaaa' + seq + 'bbbb', len(seq) + 8, None,
+                        final=True, errorhandler=self.replace_handler) ==
+                        (u'aaaa' + res + u'bbbb', len(seq) + 8))
+            res = res.replace(FFFD, u'')
+            assert self.decoder(seq, len(seq), None, final=True,
+                           errorhandler=self.ignore_handler) == (res, len(seq))
+            assert (self.decoder('aaaa' + seq + 'bbbb', len(seq) + 8, None,
+                        final=True, errorhandler=self.ignore_handler) ==
+                        (u'aaaa' + res + u'bbbb', len(seq) + 8))
+
+    def test_invalid_cb_for_3bytes_seq(self):
+        """
+        Test that an 'invalid continuation byte' error is raised when the
+        continuation byte(s) of a 3-bytes sequence are invalid.  When
+        errors='replace', if the first continuation byte is valid, the first
+        two bytes (start byte + 1st cb) are replaced by a single U+FFFD and the
+        third byte is handled separately, otherwise only the start byte is
+        replaced with a U+FFFD and the other continuation bytes are handled
+        separately.
+        E.g. in the sequence <E1 80 41>, E1 is the start byte of a 3-bytes
+        sequence, 80 is a valid continuation byte, but 41 is not a valid cb
+        because it's the ASCII letter 'A'.
+        Note: when the start byte is E0 or ED, the valid ranges for the first
+        continuation byte are limited to A0..BF and 80..9F respectively.
+        However, when the start byte is ED, Python 2 considers all the bytes
+        in range 80..BF valid.  This is fixed in Python 3.
+        """
+        FFFD = u'\ufffd'
+        FFFDx2 = FFFD * 2
+        sequences = [
+            ('E0 00', FFFD+u'\x00'), ('E0 7F', FFFD+u'\x7f'), ('E0 80', FFFDx2),
+            ('E0 9F', FFFDx2), ('E0 C0', FFFDx2), ('E0 FF', FFFDx2),
+            ('E0 A0 00', FFFD+u'\x00'), ('E0 A0 7F', FFFD+u'\x7f'),
+            ('E0 A0 C0', FFFDx2), ('E0 A0 FF', FFFDx2),
+            ('E0 BF 00', FFFD+u'\x00'), ('E0 BF 7F', FFFD+u'\x7f'),
+            ('E0 BF C0', FFFDx2), ('E0 BF FF', FFFDx2), ('E1 00', FFFD+u'\x00'),
+            ('E1 7F', FFFD+u'\x7f'), ('E1 C0', FFFDx2), ('E1 FF', FFFDx2),
+            ('E1 80 00', FFFD+u'\x00'), ('E1 80 7F', FFFD+u'\x7f'),
+            ('E1 80 C0', FFFDx2), ('E1 80 FF', FFFDx2),
+            ('E1 BF 00', FFFD+u'\x00'), ('E1 BF 7F', FFFD+u'\x7f'),
+            ('E1 BF C0', FFFDx2), ('E1 BF FF', FFFDx2), ('EC 00', FFFD+u'\x00'),
+            ('EC 7F', FFFD+u'\x7f'), ('EC C0', FFFDx2), ('EC FF', FFFDx2),
+            ('EC 80 00', FFFD+u'\x00'), ('EC 80 7F', FFFD+u'\x7f'),
+            ('EC 80 C0', FFFDx2), ('EC 80 FF', FFFDx2),
+            ('EC BF 00', FFFD+u'\x00'), ('EC BF 7F', FFFD+u'\x7f'),
+            ('EC BF C0', FFFDx2), ('EC BF FF', FFFDx2), ('ED 00', FFFD+u'\x00'),
+            ('ED 7F', FFFD+u'\x7f'),
+            # ('ED A0', FFFDx2), ('ED BF', FFFDx2), # see note ^
+            ('ED C0', FFFDx2), ('ED FF', FFFDx2), ('ED 80 00', FFFD+u'\x00'),
+            ('ED 80 7F', FFFD+u'\x7f'), ('ED 80 C0', FFFDx2),
+            ('ED 80 FF', FFFDx2), ('ED 9F 00', FFFD+u'\x00'),
+            ('ED 9F 7F', FFFD+u'\x7f'), ('ED 9F C0', FFFDx2),
+            ('ED 9F FF', FFFDx2), ('EE 00', FFFD+u'\x00'),
+            ('EE 7F', FFFD+u'\x7f'), ('EE C0', FFFDx2), ('EE FF', FFFDx2),
+            ('EE 80 00', FFFD+u'\x00'), ('EE 80 7F', FFFD+u'\x7f'),
+            ('EE 80 C0', FFFDx2), ('EE 80 FF', FFFDx2),
+            ('EE BF 00', FFFD+u'\x00'), ('EE BF 7F', FFFD+u'\x7f'),
+            ('EE BF C0', FFFDx2), ('EE BF FF', FFFDx2), ('EF 00', FFFD+u'\x00'),
+            ('EF 7F', FFFD+u'\x7f'), ('EF C0', FFFDx2), ('EF FF', FFFDx2),
+            ('EF 80 00', FFFD+u'\x00'), ('EF 80 7F', FFFD+u'\x7f'),
+            ('EF 80 C0', FFFDx2), ('EF 80 FF', FFFDx2),
+            ('EF BF 00', FFFD+u'\x00'), ('EF BF 7F', FFFD+u'\x7f'),
+            ('EF BF C0', FFFDx2), ('EF BF FF', FFFDx2),
+        ]
+        for seq, res in sequences:
+            seq = self.to_bytestring(seq)
+            raises(UnicodeDecodeError, self.decoder, seq, len(seq),
+                   None, final=True)
+            self.checkdecodeerror(seq, 'utf-8', 0, len(seq)-1, addstuff=False,
+                                  msg='invalid continuation byte')
+            assert self.decoder(seq, len(seq), None, final=True,
+                       errorhandler=self.replace_handler) == (res, len(seq))
+            assert (self.decoder('aaaa' + seq + 'bbbb', len(seq) + 8, None,
+                        final=True, errorhandler=self.replace_handler) ==
+                        (u'aaaa' + res + u'bbbb', len(seq) + 8))
+            res = res.replace(FFFD, u'')
+            assert self.decoder(seq, len(seq), None, final=True,
+                           errorhandler=self.ignore_handler) == (res, len(seq))
+            assert (self.decoder('aaaa' + seq + 'bbbb', len(seq) + 8, None,
+                        final=True, errorhandler=self.ignore_handler) ==
+                        (u'aaaa' + res + u'bbbb', len(seq) + 8))
+
+    def test_invalid_cb_for_4bytes_seq(self):
+        """
+        Test that an 'invalid continuation byte' error is raised when the
+        continuation byte(s) of a 4-bytes sequence are invalid.  When
+        errors='replace',the start byte and all the following valid
+        continuation bytes are replaced with a single U+FFFD, and all the bytes
+        starting from the first invalid continuation bytes (included) are
+        handled separately.
+        E.g. in the sequence <E1 80 41>, E1 is the start byte of a 3-bytes
+        sequence, 80 is a valid continuation byte, but 41 is not a valid cb
+        because it's the ASCII letter 'A'.
+        Note: when the start byte is E0 or ED, the valid ranges for the first
+        continuation byte are limited to A0..BF and 80..9F respectively.
+        However, when the start byte is ED, Python 2 considers all the bytes
+        in range 80..BF valid.  This is fixed in Python 3.
+        """
+        FFFD = u'\ufffd'
+        FFFDx2 = FFFD * 2
+        sequences = [
+            ('F0 00', FFFD+u'\x00'), ('F0 7F', FFFD+u'\x7f'), ('F0 80', FFFDx2),
+            ('F0 8F', FFFDx2), ('F0 C0', FFFDx2), ('F0 FF', FFFDx2),
+            ('F0 90 00', FFFD+u'\x00'), ('F0 90 7F', FFFD+u'\x7f'),
+            ('F0 90 C0', FFFDx2), ('F0 90 FF', FFFDx2),
+            ('F0 BF 00', FFFD+u'\x00'), ('F0 BF 7F', FFFD+u'\x7f'),
+            ('F0 BF C0', FFFDx2), ('F0 BF FF', FFFDx2),
+            ('F0 90 80 00', FFFD+u'\x00'), ('F0 90 80 7F', FFFD+u'\x7f'),
+            ('F0 90 80 C0', FFFDx2), ('F0 90 80 FF', FFFDx2),
+            ('F0 90 BF 00', FFFD+u'\x00'), ('F0 90 BF 7F', FFFD+u'\x7f'),
+            ('F0 90 BF C0', FFFDx2), ('F0 90 BF FF', FFFDx2),
+            ('F0 BF 80 00', FFFD+u'\x00'), ('F0 BF 80 7F', FFFD+u'\x7f'),
+            ('F0 BF 80 C0', FFFDx2), ('F0 BF 80 FF', FFFDx2),
+            ('F0 BF BF 00', FFFD+u'\x00'), ('F0 BF BF 7F', FFFD+u'\x7f'),
+            ('F0 BF BF C0', FFFDx2), ('F0 BF BF FF', FFFDx2),
+            ('F1 00', FFFD+u'\x00'), ('F1 7F', FFFD+u'\x7f'), ('F1 C0', FFFDx2),
+            ('F1 FF', FFFDx2), ('F1 80 00', FFFD+u'\x00'),
+            ('F1 80 7F', FFFD+u'\x7f'), ('F1 80 C0', FFFDx2),
+            ('F1 80 FF', FFFDx2), ('F1 BF 00', FFFD+u'\x00'),
+            ('F1 BF 7F', FFFD+u'\x7f'), ('F1 BF C0', FFFDx2),
+            ('F1 BF FF', FFFDx2), ('F1 80 80 00', FFFD+u'\x00'),
+            ('F1 80 80 7F', FFFD+u'\x7f'), ('F1 80 80 C0', FFFDx2),
+            ('F1 80 80 FF', FFFDx2), ('F1 80 BF 00', FFFD+u'\x00'),
+            ('F1 80 BF 7F', FFFD+u'\x7f'), ('F1 80 BF C0', FFFDx2),
+            ('F1 80 BF FF', FFFDx2), ('F1 BF 80 00', FFFD+u'\x00'),
+            ('F1 BF 80 7F', FFFD+u'\x7f'), ('F1 BF 80 C0', FFFDx2),
+            ('F1 BF 80 FF', FFFDx2), ('F1 BF BF 00', FFFD+u'\x00'),
+            ('F1 BF BF 7F', FFFD+u'\x7f'), ('F1 BF BF C0', FFFDx2),
+            ('F1 BF BF FF', FFFDx2), ('F3 00', FFFD+u'\x00'),
+            ('F3 7F', FFFD+u'\x7f'), ('F3 C0', FFFDx2), ('F3 FF', FFFDx2),
+            ('F3 80 00', FFFD+u'\x00'), ('F3 80 7F', FFFD+u'\x7f'),
+            ('F3 80 C0', FFFDx2), ('F3 80 FF', FFFDx2),
+            ('F3 BF 00', FFFD+u'\x00'), ('F3 BF 7F', FFFD+u'\x7f'),
+            ('F3 BF C0', FFFDx2), ('F3 BF FF', FFFDx2),
+            ('F3 80 80 00', FFFD+u'\x00'), ('F3 80 80 7F', FFFD+u'\x7f'),
+            ('F3 80 80 C0', FFFDx2), ('F3 80 80 FF', FFFDx2),
+            ('F3 80 BF 00', FFFD+u'\x00'), ('F3 80 BF 7F', FFFD+u'\x7f'),
+            ('F3 80 BF C0', FFFDx2), ('F3 80 BF FF', FFFDx2),
+            ('F3 BF 80 00', FFFD+u'\x00'), ('F3 BF 80 7F', FFFD+u'\x7f'),
+            ('F3 BF 80 C0', FFFDx2), ('F3 BF 80 FF', FFFDx2),
+            ('F3 BF BF 00', FFFD+u'\x00'), ('F3 BF BF 7F', FFFD+u'\x7f'),
+            ('F3 BF BF C0', FFFDx2), ('F3 BF BF FF', FFFDx2),
+            ('F4 00', FFFD+u'\x00'), ('F4 7F', FFFD+u'\x7f'), ('F4 90', FFFDx2),
+            ('F4 BF', FFFDx2), ('F4 C0', FFFDx2), ('F4 FF', FFFDx2),
+            ('F4 80 00', FFFD+u'\x00'), ('F4 80 7F', FFFD+u'\x7f'),
+            ('F4 80 C0', FFFDx2), ('F4 80 FF', FFFDx2),
+            ('F4 8F 00', FFFD+u'\x00'), ('F4 8F 7F', FFFD+u'\x7f'),
+            ('F4 8F C0', FFFDx2), ('F4 8F FF', FFFDx2),
+            ('F4 80 80 00', FFFD+u'\x00'), ('F4 80 80 7F', FFFD+u'\x7f'),
+            ('F4 80 80 C0', FFFDx2), ('F4 80 80 FF', FFFDx2),
+            ('F4 80 BF 00', FFFD+u'\x00'), ('F4 80 BF 7F', FFFD+u'\x7f'),
+            ('F4 80 BF C0', FFFDx2), ('F4 80 BF FF', FFFDx2),
+            ('F4 8F 80 00', FFFD+u'\x00'), ('F4 8F 80 7F', FFFD+u'\x7f'),
+            ('F4 8F 80 C0', FFFDx2), ('F4 8F 80 FF', FFFDx2),
+            ('F4 8F BF 00', FFFD+u'\x00'), ('F4 8F BF 7F', FFFD+u'\x7f'),
+            ('F4 8F BF C0', FFFDx2), ('F4 8F BF FF', FFFDx2)
+        ]
+        for seq, res in sequences:
+            seq = self.to_bytestring(seq)
+            raises(UnicodeDecodeError, self.decoder, seq, len(seq),
+                   None, final=True)
+            self.checkdecodeerror(seq, 'utf-8', 0, len(seq)-1, addstuff=False,
+                                  msg='invalid continuation byte')
+            assert self.decoder(seq, len(seq), None, final=True,
+                       errorhandler=self.replace_handler) == (res, len(seq))
+            assert (self.decoder('aaaa' + seq + 'bbbb', len(seq) + 8, None,
+                        final=True, errorhandler=self.replace_handler) ==
+                        (u'aaaa' + res + u'bbbb', len(seq) + 8))
+            res = res.replace(FFFD, u'')
+            assert self.decoder(seq, len(seq), None, final=True,
+                           errorhandler=self.ignore_handler) == (res, len(seq))
+            assert (self.decoder('aaaa' + seq + 'bbbb', len(seq) + 8, None,
+                        final=True, errorhandler=self.ignore_handler) ==
+                        (u'aaaa' + res + u'bbbb', len(seq) + 8))
+
     def test_utf8_errors(self):
-        for s in [# unexpected end of data
-                  "\xd7", "\xd6", "\xeb\x96", "\xf0\x90\x91"]:
-            self.checkdecodeerror(s, "utf-8", 0, len(s), addstuff=False)
-
-        # unexpected code byte
-        for s in ["\x81", "\xbf"]:
-            self.checkdecodeerror(s, "utf-8", 0, 1, addstuff=True)
+        # unexpected end of data
+        for s in ['\xd7', '\xd6', '\xeb\x96', '\xf0\x90\x91', '\xc2', '\xdf']:
+            self.checkdecodeerror(s, 'utf-8', 0, len(s), addstuff=False,
+                                  msg='unexpected end of data')
 
         # invalid data 2 byte
         for s in ["\xd7\x50", "\xd6\x06", "\xd6\xD6"]:
-            self.checkdecodeerror(s, "utf-8", 0, 1, addstuff=True)
+            self.checkdecodeerror(s, "utf-8", 0, 1, addstuff=True,
+                                  msg='invalid continuation byte')
         # invalid data 3 byte
         for s in ["\xeb\x56\x95", "\xeb\x06\x95", "\xeb\xD6\x95"]:
-            self.checkdecodeerror(s, "utf-8", 0, 1, addstuff=True)
+            self.checkdecodeerror(s, "utf-8", 0, 1, addstuff=True,
+                                  msg='invalid continuation byte')
         for s in ["\xeb\x96\x55", "\xeb\x96\x05", "\xeb\x96\xD5"]:
-            self.checkdecodeerror(s, "utf-8", 0, 2, addstuff=True)
+            self.checkdecodeerror(s, "utf-8", 0, 2, addstuff=True,
+                                  msg='invalid continuation byte')
         # invalid data 4 byte
         for s in ["\xf0\x50\x91\x93", "\xf0\x00\x91\x93", "\xf0\xd0\x91\x93"]:
-            self.checkdecodeerror(s, "utf-8", 0, 1, addstuff=True)
+            self.checkdecodeerror(s, "utf-8", 0, 1, addstuff=True,
+                                  msg='invalid continuation byte')
         for s in ["\xf0\x90\x51\x93", "\xf0\x90\x01\x93", "\xf0\x90\xd1\x93"]:
-            self.checkdecodeerror(s, "utf-8", 0, 2, addstuff=True)
+            self.checkdecodeerror(s, "utf-8", 0, 2, addstuff=True,
+                                  msg='invalid continuation byte')
         for s in ["\xf0\x90\x91\x53", "\xf0\x90\x91\x03", "\xf0\x90\x91\xd3"]:
-            self.checkdecodeerror(s, "utf-8", 0, 3, addstuff=True)
+            self.checkdecodeerror(s, "utf-8", 0, 3, addstuff=True,
+                                  msg='invalid continuation byte')
 
 
     def test_issue8271(self):
@@ -249,97 +615,18 @@
             ('\x61\xF1\x80\x80\xE1\x80\xC2\x62\x80\x63\x80\xBF\x64',
              u'\x61\uFFFD\uFFFD\uFFFD\x62\uFFFD\x63\uFFFD\uFFFD\x64'),
         ]
-        def replace_handler(errors, codec, message, input, start, end):
-            return FFFD, end
-        def ignore_handler(errors, codec, message, input, start, end):
-            return u'', end
+
         for n, (seq, res) in enumerate(sequences):
             decoder = self.getdecoder('utf-8')
             raises(UnicodeDecodeError, decoder, seq, len(seq), None, final=True)
             assert decoder(seq, len(seq), None, final=True,
-                           errorhandler=replace_handler) == (res, len(seq))
+                           errorhandler=self.replace_handler) == (res, len(seq))
             assert decoder(seq + 'b', len(seq) + 1, None, final=True,
-                           errorhandler=replace_handler) == (res + u'b',
-                                                             len(seq) + 1)
+                           errorhandler=self.replace_handler) == (res + u'b',
+                                                                  len(seq) + 1)
             res = res.replace(FFFD, u'')
             assert decoder(seq, len(seq), None, final=True,
-                           errorhandler=ignore_handler) == (res, len(seq))
-
-    def test_ascii_error(self):
-        self.checkdecodeerror("abc\xFF\xFF\xFFcde", "ascii", 3, 4)
-
-    def test_utf16_errors(self):
-        # trunkated BOM
-        for s in ["\xff", "\xfe"]:
-            self.checkdecodeerror(s, "utf-16", 0, len(s), addstuff=False)
-
-        for s in [
-                  # unexpected end of data ascii
-                  "\xff\xfeF",
-                  # unexpected end of data
-                  '\xff\xfe\xc0\xdb\x00', '\xff\xfe\xc0\xdb', '\xff\xfe\xc0', 
-                  ]:
-            self.checkdecodeerror(s, "utf-16", 2, len(s), addstuff=False)
-        for s in [
-                  # illegal surrogate
-                  "\xff\xfe\xff\xdb\xff\xff",
-                  ]:
-            self.checkdecodeerror(s, "utf-16", 2, 4, addstuff=False)
-
-    def test_utf16_bugs(self):
-        s = '\x80-\xe9\xdeL\xa3\x9b'
-        py.test.raises(UnicodeDecodeError, runicode.str_decode_utf_16_le,
-                       s, len(s), True)
-
-    def test_utf7_bugs(self):
-        u = u'A\u2262\u0391.'
-        assert runicode.unicode_encode_utf_7(u, len(u), None) == 'A+ImIDkQ.'
-
-    def test_utf7_tofrom_utf8_bug(self):
-        def _assert_decu7(input, expected):
-            assert runicode.str_decode_utf_7(input, len(input), None) == (expected, len(input))
-
-        _assert_decu7('+-', u'+')
-        _assert_decu7('+-+-', u'++')
-        _assert_decu7('+-+AOQ-', u'+\xe4')
-        _assert_decu7('+AOQ-', u'\xe4')
-        _assert_decu7('+AOQ-', u'\xe4')
-        _assert_decu7('+AOQ- ', u'\xe4 ')
-        _assert_decu7(' +AOQ-', u' \xe4')
-        _assert_decu7(' +AOQ- ', u' \xe4 ')
-        _assert_decu7('+AOQ-+AOQ-', u'\xe4\xe4')
-
-        s_utf7 = 'Die M+AOQ-nner +AOQ-rgen sich!'
-        s_utf8 = u'Die M&#228;nner &#228;rgen sich!'
-        s_utf8_esc = u'Die M\xe4nner \xe4rgen sich!'
-
-        _assert_decu7(s_utf7, s_utf8_esc)
-        _assert_decu7(s_utf7, s_utf8)
-
-        assert runicode.unicode_encode_utf_7(s_utf8_esc, len(s_utf8_esc), None) == s_utf7
-        assert runicode.unicode_encode_utf_7(s_utf8,     len(s_utf8_esc), None) == s_utf7
-
-    def test_utf7_partial(self):
-        s = u"a+-b".encode('utf-7')
-        assert s == "a+--b"
-        decode = self.getdecoder('utf-7')
-        assert decode(s, 1, None) == (u'a', 1)
-        assert decode(s, 2, None) == (u'a', 1)
-        assert decode(s, 3, None) == (u'a+', 3)
-        assert decode(s, 4, None) == (u'a+-', 4)
-        assert decode(s, 5, None) == (u'a+-b', 5)
-
-    def test_utf7_surrogates(self):
-        encode = self.getencoder('utf-7')
-        u = u'\U000abcde'
-        assert encode(u, len(u), None) == '+2m/c3g-'
-        decode = self.getdecoder('utf-7')
-        s = '+3ADYAA-'
-        raises(UnicodeError, decode, s, len(s), None)
-        def replace_handler(errors, codec, message, input, start, end):
-            return u'?', end
-        assert decode(s, len(s), None, final=True,
-                      errorhandler = replace_handler) == (u'??', len(s))
+                           errorhandler=self.ignore_handler) == (res, len(seq))
 
 
 class TestEncoding(UnicodeTests):
@@ -376,7 +663,7 @@
                 self.checkencode(uni, "utf-7")
             for encoding in ("utf-8 utf-16 utf-16-be utf-16-le "
                              "utf-32 utf-32-be utf-32-le").split():
-                self.checkencode(uni, encoding)                
+                self.checkencode(uni, encoding)
 
     def test_maxunicode(self):
         uni = unichr(sys.maxunicode)
@@ -384,7 +671,7 @@
             self.checkencode(uni, "utf-7")
         for encoding in ("utf-8 utf-16 utf-16-be utf-16-le "
                          "utf-32 utf-32-be utf-32-le").split():
-            self.checkencode(uni, encoding)        
+            self.checkencode(uni, encoding)
 
     def test_single_chars_utf8(self):
         # check every number of bytes per char
@@ -394,7 +681,7 @@
     def test_utf8_surrogates(self):
         # check replacing of two surrogates by single char while encoding
         # make sure that the string itself is not marshalled
-        u = u"\ud800" 
+        u = u"\ud800"
         for i in range(4):
             u += u"\udc00"
         self.checkencode(u, "utf-8")
@@ -422,7 +709,7 @@
     def test_utf8(self):
         from pypy.rpython.test.test_llinterp import interpret
         def f(x):
-            
+
             s1 = "".join(["\xd7\x90\xd6\x96\xeb\x96\x95\xf0\x90\x91\x93"] * x)
             u, consumed = runicode.str_decode_utf_8(s1, len(s1), True)
             s2 = runicode.unicode_encode_utf_8(u, len(u), True)
@@ -438,6 +725,6 @@
             u = runicode.UNICHR(x)
             t = runicode.ORD(u)
             return t
-            
+
         res = interpret(f, [0x10140])
         assert res == 0x10140

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

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

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

diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -119,13 +119,16 @@
     Impara, Germany
     Change Maker, Sweden 
 
+The PyPy Logo as used by http://speed.pypy.org and others was created
+by Samuel Reis and is distributed on terms of Creative Commons Share Alike
+License.
  
-License for 'lib-python/2.5.2' and 'lib-python/2.5.2-modified'
+License for 'lib-python/2.7.0' and 'lib-python/2.7.0-modified'
 ============================================================== 
 
 Except when otherwise stated (look for LICENSE files or
 copyright/license information at the beginning of each file) the files
-in the 'lib-python/2.5.2' and 'lib-python/2.5.2-modified' directories
+in the 'lib-python/2.7.0' and 'lib-python/2.7.0-modified' directories
 are all copyrighted by the Python Software Foundation and licensed under
 the Python Software License of which you can find a copy here:
 http://www.python.org/doc/Copyright.html 
@@ -158,21 +161,12 @@
 ======================================
 
 The following files are from the website of The Unicode Consortium
-at http://www.unicode.org/. For the terms of use of these files, see
-http://www.unicode.org/terms_of_use.html
+at http://www.unicode.org/.  For the terms of use of these files, see
+http://www.unicode.org/terms_of_use.html .  Or they are derived from
+files from the above website, and the same terms of use apply.
 
-    CompositionExclusions-3.2.0.txt
-    CompositionExclusions-4.1.0.txt
-    CompositionExclusions-5.0.0.txt
-    EastAsianWidth-3.2.0.txt
-    EastAsianWidth-4.1.0.txt
-    EastAsianWidth-5.0.0.txt
-    UnicodeData-3.2.0.txt
-    UnicodeData-4.1.0.txt
-    UnicodeData-5.0.0.txt
-    
-The following files are derived from files from the above website. The same
-terms of use apply.
-    UnihanNumeric-3.2.0.txt
-    UnihanNumeric-4.1.0.txt
-    UnihanNumeric-5.0.0.txt
+    CompositionExclusions-*.txt
+    EastAsianWidth-*.txt
+    LineBreak-*.txt
+    UnicodeData-*.txt
+    UnihanNumeric-*.txt

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

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

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


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

diff --git a/pypy/jit/metainterp/test/test_send.py b/pypy/jit/metainterp/test/test_send.py
--- a/pypy/jit/metainterp/test/test_send.py
+++ b/pypy/jit/metainterp/test/test_send.py
@@ -1,7 +1,7 @@
 import py
 from pypy.rlib.jit import JitDriver, hint, purefunction
 from pypy.jit.codewriter.policy import StopAtXPolicy
-from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
+from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
 
 class SendTests(object):
     

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

diff --git a/pypy/jit/metainterp/test/test_dict.py b/pypy/jit/metainterp/test/test_dict.py
--- a/pypy/jit/metainterp/test/test_dict.py
+++ b/pypy/jit/metainterp/test/test_dict.py
@@ -1,5 +1,5 @@
 import py
-from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
+from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
 from pypy.rlib.jit import JitDriver
 from pypy.rlib import objectmodel
 

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

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

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

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

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

diff --git a/pypy/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
@@ -79,7 +79,8 @@
 
    possibly replacing ``--opt=jit`` with another `optimization level`_
    of your choice like ``--opt=2`` if you do not want the included JIT
-   compiler.  As of March 2011, Intel **32-bit** environment needs ``4GB``.
+   compiler.  As of March 2011, Intel 32-bit environment needs **at
+   least** 2GB, and 64-bit needs 4GB.
 
 .. _`optimization level`: config/opt.html
 

diff --git a/pypy/annotation/description.py b/pypy/annotation/description.py
--- a/pypy/annotation/description.py
+++ b/pypy/annotation/description.py
@@ -880,6 +880,11 @@
         except AttributeError:
             return False
 
+    def warn_missing_attribute(self, attr):
+        # only warn for missing attribute names whose name doesn't start
+        # with '$', to silence the warnings about '$memofield_xxx'.
+        return not self.has_attribute(attr) and not attr.startswith('$')
+
     def read_attribute(self, attr):
         try:
             return self.attrcache[attr]

diff --git a/pypy/jit/metainterp/test/test_memmgr.py b/pypy/jit/metainterp/test/test_memmgr.py
--- a/pypy/jit/metainterp/test/test_memmgr.py
+++ b/pypy/jit/metainterp/test/test_memmgr.py
@@ -12,7 +12,7 @@
 
 import py
 from pypy.jit.metainterp.memmgr import MemoryManager
-from pypy.jit.metainterp.test.test_basic import LLJitMixin
+from pypy.jit.metainterp.test.support import LLJitMixin
 from pypy.rlib.jit import JitDriver, dont_look_inside
 
 

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

diff --git a/pypy/jit/metainterp/test/test_list.py b/pypy/jit/metainterp/test/test_list.py
--- a/pypy/jit/metainterp/test/test_list.py
+++ b/pypy/jit/metainterp/test/test_list.py
@@ -1,6 +1,6 @@
 import py
 from pypy.rlib.jit import JitDriver
-from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
+from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
 
 
 class ListTests:

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


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

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

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

diff --git a/pypy/jit/metainterp/test/test_del.py b/pypy/jit/metainterp/test/test_del.py
--- a/pypy/jit/metainterp/test/test_del.py
+++ b/pypy/jit/metainterp/test/test_del.py
@@ -1,6 +1,6 @@
 import py
 from pypy.rlib.jit import JitDriver
-from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
+from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
 
 
 class DelTests:

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

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


diff --git a/pypy/module/cpyext/test/test_object.py b/pypy/module/cpyext/test/test_object.py
--- a/pypy/module/cpyext/test/test_object.py
+++ b/pypy/module/cpyext/test/test_object.py
@@ -174,6 +174,17 @@
         assert api.PyObject_Compare(space.wrap(72), space.wrap(42)) == 1
         assert api.PyObject_Compare(space.wrap("a"), space.wrap("a")) == 0
 
+    def test_cmp(self, space, api):
+        w = space.wrap
+        with lltype.scoped_alloc(rffi.INTP.TO, 1) as ptr:
+            assert api.PyObject_Cmp(w(42), w(72), ptr) == 0
+            assert ptr[0] == -1
+            assert api.PyObject_Cmp(w("a"), w("a"), ptr) == 0
+            assert ptr[0] == 0
+            assert api.PyObject_Cmp(w(u"\xe9"), w("\xe9"), ptr) < 0
+            assert api.PyErr_Occurred()
+            api.PyErr_Clear()
+
     def test_unicode(self, space, api):
         assert space.unwrap(api.PyObject_Unicode(space.wrap([]))) == u"[]"
         assert space.unwrap(api.PyObject_Unicode(space.wrap("e"))) == u"e"

diff --git a/pypy/rlib/rbigint.py b/pypy/rlib/rbigint.py
--- a/pypy/rlib/rbigint.py
+++ b/pypy/rlib/rbigint.py
@@ -3,7 +3,8 @@
 from pypy.rlib.rarithmetic import most_neg_value_of_same_type
 from pypy.rlib.rfloat import isinf, isnan
 from pypy.rlib.debug import make_sure_not_resized, check_regular_int
-from pypy.rlib.objectmodel import we_are_translated
+from pypy.rlib.objectmodel import we_are_translated, specialize
+from pypy.rlib import jit
 from pypy.rpython.lltypesystem import lltype, rffi
 from pypy.rpython import extregistry
 
@@ -122,7 +123,11 @@
     def numdigits(self):
         return len(self._digits)
 
+    @staticmethod
+    @jit.purefunction
     def fromint(intval):
+        # This function is marked as pure, so you must not call it and
+        # then modify the result.
         check_regular_int(intval)
         if intval < 0:
             sign = -1
@@ -149,20 +154,25 @@
             t >>= SHIFT
             p += 1
         return v
-    fromint = staticmethod(fromint)
 
+    @staticmethod
+    @jit.purefunction
     def frombool(b):
+        # This function is marked as pure, so you must not call it and
+        # then modify the result.
         if b:
             return rbigint([ONEDIGIT], 1)
         return rbigint()
-    frombool = staticmethod(frombool)
 
+    @staticmethod
     def fromlong(l):
+        "NOT_RPYTHON"
         return rbigint(*args_from_long(l))
-    fromlong = staticmethod(fromlong)
 
+    @staticmethod
     def fromfloat(dval):
         """ Create a new bigint object from a float """
+        # This function is not marked as pure because it can raise
         sign = 1
         if isinf(dval) or isnan(dval):
             raise OverflowError
@@ -183,16 +193,21 @@
             frac -= float(bits)
             frac = math.ldexp(frac, SHIFT)
         return v
-    fromfloat = staticmethod(fromfloat)
 
+    @staticmethod
+    @jit.purefunction
+    @specialize.argtype(0)
     def fromrarith_int(i):
+        # This function is marked as pure, so you must not call it and
+        # then modify the result.
         return rbigint(*args_from_rarith_int(i))
-    fromrarith_int._annspecialcase_ = "specialize:argtype(0)"
-    fromrarith_int = staticmethod(fromrarith_int)
 
+    @staticmethod
+    @jit.purefunction
     def fromdecimalstr(s):
+        # This function is marked as pure, so you must not call it and
+        # then modify the result.
         return _decimalstr_to_bigint(s)
-    fromdecimalstr = staticmethod(fromdecimalstr)
 
     def toint(self):
         """
@@ -1841,7 +1856,7 @@
     elif s[p] == '+':
         p += 1
 
-    a = rbigint.fromint(0)
+    a = rbigint()
     tens = 1
     dig = 0
     ord0 = ord('0')
@@ -1859,7 +1874,7 @@
 
 def parse_digit_string(parser):
     # helper for objspace.std.strutil
-    a = rbigint.fromint(0)
+    a = rbigint()
     base = parser.base
     digitmax = BASE_MAX[base]
     tens, dig = 1, 0

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

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

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

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

diff --git a/pypy/jit/metainterp/test/test_immutable.py b/pypy/jit/metainterp/test/test_immutable.py
--- a/pypy/jit/metainterp/test/test_immutable.py
+++ b/pypy/jit/metainterp/test/test_immutable.py
@@ -1,4 +1,4 @@
-from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
+from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
 
 
 class ImmutableFieldsTests:

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

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

diff --git a/pypy/tool/jitlogparser/parser.py b/pypy/tool/jitlogparser/parser.py
--- a/pypy/tool/jitlogparser/parser.py
+++ b/pypy/tool/jitlogparser/parser.py
@@ -107,7 +107,8 @@
                 self.bytecode_no = int(bytecode_no)
         self.operations = operations
         self.storage = storage
-        self.code = storage.disassemble_code(self.filename, self.startlineno)
+        self.code = storage.disassemble_code(self.filename, self.startlineno,
+                                             self.name)
 
     def repr(self):
         if self.filename is None:

diff --git a/pypy/annotation/model.py b/pypy/annotation/model.py
--- a/pypy/annotation/model.py
+++ b/pypy/annotation/model.py
@@ -641,6 +641,8 @@
     except TypeError:
         s = None    # unhashable T, e.g. a Ptr(GcForwardReference())
     if s is None:
+        if isinstance(T, lltype.Typedef):
+            return lltype_to_annotation(T.OF)
         if isinstance(T, lltype.Number):
             return SomeInteger(knowntype=T._type)
         if isinstance(T, (ootype.Instance, ootype.BuiltinType)):

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

diff --git a/pypy/jit/metainterp/test/test_jitprof.py b/pypy/jit/metainterp/test/test_jitprof.py
--- a/pypy/jit/metainterp/test/test_jitprof.py
+++ b/pypy/jit/metainterp/test/test_jitprof.py
@@ -1,7 +1,7 @@
 
 from pypy.jit.metainterp.warmspot import ll_meta_interp
 from pypy.rlib.jit import JitDriver, dont_look_inside, purefunction
-from pypy.jit.metainterp.test.test_basic import LLJitMixin
+from pypy.jit.metainterp.test.support import LLJitMixin
 from pypy.jit.metainterp import pyjitpl
 from pypy.jit.metainterp.jitprof import *
 

diff --git a/pypy/jit/metainterp/test/test_float.py b/pypy/jit/metainterp/test/test_float.py
--- a/pypy/jit/metainterp/test/test_float.py
+++ b/pypy/jit/metainterp/test/test_float.py
@@ -1,5 +1,5 @@
 import math
-from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
+from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
 
 
 class FloatTests:

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

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

diff --git a/pypy/rpython/lltypesystem/module/test/test_ll_math.py b/pypy/rpython/lltypesystem/module/test/test_ll_math.py
--- a/pypy/rpython/lltypesystem/module/test/test_ll_math.py
+++ b/pypy/rpython/lltypesystem/module/test/test_ll_math.py
@@ -3,6 +3,7 @@
 
 from pypy.rpython.lltypesystem.module import ll_math
 from pypy.module.math.test.test_direct import MathTests, get_tester
+from pypy.translator.c.test.test_genc import compile
 
 
 class TestMath(MathTests):
@@ -11,6 +12,7 @@
         nan = inf / inf
         assert not ll_math.ll_math_isinf(0)
         assert ll_math.ll_math_isinf(inf)
+        assert ll_math.ll_math_isinf(-inf)
         assert not ll_math.ll_math_isinf(nan)
 
     def test_isnan(self):
@@ -20,6 +22,13 @@
         assert ll_math.ll_math_isnan(nan)
         assert not ll_math.ll_math_isnan(inf)
 
+    def test_compiled_isinf(self):
+        def f(x):
+            return ll_math.ll_math_isinf(1. / x)
+        f = compile(f, [float], backendopt=False)
+        assert f(5.5e-309)
+
+
 def make_test_case((fnname, args, expected), dict):
     #
     def test_func(self):


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

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

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

diff --git a/pypy/module/cpyext/test/test_typeobject.py b/pypy/module/cpyext/test/test_typeobject.py
--- a/pypy/module/cpyext/test/test_typeobject.py
+++ b/pypy/module/cpyext/test/test_typeobject.py
@@ -201,6 +201,23 @@
         assert cmpr == 3
         assert cmpr != 42
 
+    def test_richcompare(self):
+        module = self.import_module("comparisons")
+        cmpr = module.CmpType()
+
+        # should not crash
+        cmpr < 4
+        cmpr <= 4
+        cmpr > 4
+        cmpr >= 4
+
+        assert cmpr.__le__(4) is NotImplemented
+
+    def test_tpcompare(self):
+        module = self.import_module("comparisons")
+        cmpr = module.OldCmpType()
+        assert cmpr < cmpr
+
     def test_hash(self):
         module = self.import_module("comparisons")
         cmpr = module.CmpType()

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

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


diff --git a/.hgignore b/.hgignore
--- a/.hgignore
+++ b/.hgignore
@@ -5,6 +5,8 @@
 syntax: regexp
 ^testresult$
 ^site-packages$
+^site-packages/.*$
+^site-packages/.*$
 ^bin$
 ^pypy/bin/pypy-c
 ^pypy/module/cpyext/src/.+\.o$
@@ -37,8 +39,6 @@
 ^pypy/translator/goal/.+\.dll$
 ^pypy/translator/goal/target.+-c$
 ^pypy/_cache$
-^site-packages/.+\.egg$
-^site-packages/.+\.pth$
 ^pypy/doc/statistic/.+\.html$
 ^pypy/doc/statistic/.+\.eps$
 ^pypy/doc/statistic/.+\.pdf$

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

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

diff --git a/pypy/jit/metainterp/test/test_exception.py b/pypy/jit/metainterp/test/test_exception.py
--- a/pypy/jit/metainterp/test/test_exception.py
+++ b/pypy/jit/metainterp/test/test_exception.py
@@ -1,5 +1,5 @@
 import py, sys
-from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
+from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
 from pypy.rlib.jit import JitDriver, dont_look_inside
 from pypy.rlib.rarithmetic import ovfcheck, LONG_BIT, intmask
 from pypy.jit.codewriter.policy import StopAtXPolicy

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

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

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

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


diff --git a/pypy/objspace/std/test/test_dictmultiobject.py b/pypy/objspace/std/test/test_dictmultiobject.py
--- a/pypy/objspace/std/test/test_dictmultiobject.py
+++ b/pypy/objspace/std/test/test_dictmultiobject.py
@@ -133,6 +133,8 @@
 
 
 class AppTest_DictObject:
+    def setup_class(cls):
+        cls.w_on_pypy = cls.space.wrap("__pypy__" in sys.builtin_module_names)
 
     def test_equality(self):
         d = {1:2} 
@@ -252,10 +254,17 @@
         k = Key()
         d = {}
         d.setdefault(k, [])
-        assert k.calls == 1
+        if self.on_pypy:
+            assert k.calls == 1
 
         d.setdefault(k, 1)
-        assert k.calls == 2
+        if self.on_pypy:
+            assert k.calls == 2
+
+        k = Key()
+        d.setdefault(k, 42)
+        if self.on_pypy:
+            assert k.calls == 1
 
     def test_update(self):
         d = {1:2, 3:4}

diff --git a/pypy/jit/metainterp/test/test_basic.py b/pypy/jit/metainterp/test/test_ajit.py
copy from pypy/jit/metainterp/test/test_basic.py
copy to pypy/jit/metainterp/test/test_ajit.py
--- a/pypy/jit/metainterp/test/test_basic.py
+++ b/pypy/jit/metainterp/test/test_ajit.py
@@ -4,269 +4,17 @@
 from pypy.rlib.jit import loop_invariant
 from pypy.rlib.jit import jit_debug, assert_green, AssertGreenFailed
 from pypy.rlib.jit import unroll_safe, current_trace_length
-from pypy.jit.metainterp.warmspot import ll_meta_interp, get_stats
-from pypy.jit.backend.llgraph import runner
 from pypy.jit.metainterp import pyjitpl, history
 from pypy.jit.metainterp.warmstate import set_future_value
+from pypy.jit.metainterp.warmspot import get_stats
 from pypy.jit.codewriter.policy import JitPolicy, StopAtXPolicy
-from pypy.jit.codewriter import longlong
 from pypy import conftest
 from pypy.rlib.rarithmetic import ovfcheck
 from pypy.jit.metainterp.typesystem import LLTypeHelper, OOTypeHelper
 from pypy.rpython.lltypesystem import lltype, llmemory
 from pypy.rpython.ootypesystem import ootype
 from pypy.jit.metainterp.optimizeopt import ALL_OPTS_DICT
-
-def _get_jitcodes(testself, CPUClass, func, values, type_system,
-                  supports_longlong=False, **kwds):
-    from pypy.jit.codewriter import support, codewriter
-
-    class FakeJitCell:
-        __compiled_merge_points = []
-        def get_compiled_merge_points(self):
-            return self.__compiled_merge_points[:]
-        def set_compiled_merge_points(self, lst):
-            self.__compiled_merge_points = lst
-
-    class FakeWarmRunnerState:
-        def attach_unoptimized_bridge_from_interp(self, greenkey, newloop):
-            pass
-
-        def jit_cell_at_key(self, greenkey):
-            assert greenkey == []
-            return self._cell
-        _cell = FakeJitCell()
-
-        trace_limit = sys.maxint
-        enable_opts = ALL_OPTS_DICT
-
-    func._jit_unroll_safe_ = True
-    rtyper = support.annotate(func, values, type_system=type_system)
-    graphs = rtyper.annotator.translator.graphs
-    result_kind = history.getkind(graphs[0].getreturnvar().concretetype)[0]
-
-    class FakeJitDriverSD:
-        num_green_args = 0
-        portal_graph = graphs[0]
-        virtualizable_info = None
-        greenfield_info = None
-        result_type = result_kind
-        portal_runner_ptr = "???"
-
-    stats = history.Stats()
-    cpu = CPUClass(rtyper, stats, None, False)
-    cw = codewriter.CodeWriter(cpu, [FakeJitDriverSD()])
-    testself.cw = cw
-    policy = JitPolicy()
-    policy.set_supports_longlong(supports_longlong)
-    cw.find_all_graphs(policy)
-    #
-    testself.warmrunnerstate = FakeWarmRunnerState()
-    testself.warmrunnerstate.cpu = cpu
-    FakeJitDriverSD.warmstate = testself.warmrunnerstate
-    if hasattr(testself, 'finish_setup_for_interp_operations'):
-        testself.finish_setup_for_interp_operations()
-    #
-    cw.make_jitcodes(verbose=True)
-
-def _run_with_blackhole(testself, args):
-    from pypy.jit.metainterp.blackhole import BlackholeInterpBuilder
-    cw = testself.cw
-    blackholeinterpbuilder = BlackholeInterpBuilder(cw)
-    blackholeinterp = blackholeinterpbuilder.acquire_interp()
-    count_i = count_r = count_f = 0
-    for value in args:
-        T = lltype.typeOf(value)
-        if T == lltype.Signed:
-            blackholeinterp.setarg_i(count_i, value)
-            count_i += 1
-        elif T == llmemory.GCREF:
-            blackholeinterp.setarg_r(count_r, value)
-            count_r += 1
-        elif T == lltype.Float:
-            value = longlong.getfloatstorage(value)
-            blackholeinterp.setarg_f(count_f, value)
-            count_f += 1
-        else:
-            raise TypeError(T)
-    [jitdriver_sd] = cw.callcontrol.jitdrivers_sd
-    blackholeinterp.setposition(jitdriver_sd.mainjitcode, 0)
-    blackholeinterp.run()
-    return blackholeinterp._final_result_anytype()
-
-def _run_with_pyjitpl(testself, args):
-
-    class DoneWithThisFrame(Exception):
-        pass
-
-    class DoneWithThisFrameRef(DoneWithThisFrame):
-        def __init__(self, cpu, *args):
-            DoneWithThisFrame.__init__(self, *args)
-
-    cw = testself.cw
-    opt = history.Options(listops=True)
-    metainterp_sd = pyjitpl.MetaInterpStaticData(cw.cpu, opt)
-    metainterp_sd.finish_setup(cw)
-    [jitdriver_sd] = metainterp_sd.jitdrivers_sd
-    metainterp = pyjitpl.MetaInterp(metainterp_sd, jitdriver_sd)
-    metainterp_sd.DoneWithThisFrameInt = DoneWithThisFrame
-    metainterp_sd.DoneWithThisFrameRef = DoneWithThisFrameRef
-    metainterp_sd.DoneWithThisFrameFloat = DoneWithThisFrame
-    testself.metainterp = metainterp
-    try:
-        metainterp.compile_and_run_once(jitdriver_sd, *args)
-    except DoneWithThisFrame, e:
-        #if conftest.option.view:
-        #    metainterp.stats.view()
-        return e.args[0]
-    else:
-        raise Exception("FAILED")
-
-def _run_with_machine_code(testself, args):
-    metainterp = testself.metainterp
-    num_green_args = metainterp.jitdriver_sd.num_green_args
-    loop_tokens = metainterp.get_compiled_merge_points(args[:num_green_args])
-    if len(loop_tokens) != 1:
-        return NotImplemented
-    # a loop was successfully created by _run_with_pyjitpl(); call it
-    cpu = metainterp.cpu
-    for i in range(len(args) - num_green_args):
-        x = args[num_green_args + i]
-        typecode = history.getkind(lltype.typeOf(x))
-        set_future_value(cpu, i, x, typecode)
-    faildescr = cpu.execute_token(loop_tokens[0])
-    assert faildescr.__class__.__name__.startswith('DoneWithThisFrameDescr')
-    if metainterp.jitdriver_sd.result_type == history.INT:
-        return cpu.get_latest_value_int(0)
-    elif metainterp.jitdriver_sd.result_type == history.REF:
-        return cpu.get_latest_value_ref(0)
-    elif metainterp.jitdriver_sd.result_type == history.FLOAT:
-        return cpu.get_latest_value_float(0)
-    else:
-        return None
-
-
-class JitMixin:
-    basic = True
-    def check_loops(self, expected=None, everywhere=False, **check):
-        get_stats().check_loops(expected=expected, everywhere=everywhere,
-                                **check)
-    def check_loop_count(self, count):
-        """NB. This is a hack; use check_tree_loop_count() or
-        check_enter_count() for the real thing.
-        This counts as 1 every bridge in addition to every loop; and it does
-        not count at all the entry bridges from interpreter, although they
-        are TreeLoops as well."""
-        assert get_stats().compiled_count == count
-    def check_tree_loop_count(self, count):
-        assert len(get_stats().loops) == count
-    def check_loop_count_at_most(self, count):
-        assert get_stats().compiled_count <= count
-    def check_enter_count(self, count):
-        assert get_stats().enter_count == count
-    def check_enter_count_at_most(self, count):
-        assert get_stats().enter_count <= count
-    def check_jumps(self, maxcount):
-        assert get_stats().exec_jumps <= maxcount
-    def check_aborted_count(self, count):
-        assert get_stats().aborted_count == count
-    def check_aborted_count_at_least(self, count):
-        assert get_stats().aborted_count >= count
-
-    def meta_interp(self, *args, **kwds):
-        kwds['CPUClass'] = self.CPUClass
-        kwds['type_system'] = self.type_system
-        if "backendopt" not in kwds:
-            kwds["backendopt"] = False
-        return ll_meta_interp(*args, **kwds)
-
-    def interp_operations(self, f, args, **kwds):
-        # get the JitCodes for the function f
-        _get_jitcodes(self, self.CPUClass, f, args, self.type_system, **kwds)
-        # try to run it with blackhole.py
-        result1 = _run_with_blackhole(self, args)
-        # try to run it with pyjitpl.py
-        result2 = _run_with_pyjitpl(self, args)
-        assert result1 == result2
-        # try to run it by running the code compiled just before
-        result3 = _run_with_machine_code(self, args)
-        assert result1 == result3 or result3 == NotImplemented
-        #
-        if (longlong.supports_longlong and
-            isinstance(result1, longlong.r_float_storage)):
-            result1 = longlong.getrealfloat(result1)
-        return result1
-
-    def check_history(self, expected=None, **isns):
-        # this can be used after calling meta_interp
-        get_stats().check_history(expected, **isns)
-
-    def check_operations_history(self, expected=None, **isns):
-        # this can be used after interp_operations
-        if expected is not None:
-            expected = dict(expected)
-            expected['jump'] = 1
-        self.metainterp.staticdata.stats.check_history(expected, **isns)
-
-
-class LLJitMixin(JitMixin):
-    type_system = 'lltype'
-    CPUClass = runner.LLtypeCPU
-
-    @staticmethod
-    def Ptr(T):
-        return lltype.Ptr(T)
-
-    @staticmethod
-    def GcStruct(name, *fields, **kwds):
-        S = lltype.GcStruct(name, *fields, **kwds)
-        return S
-
-    malloc = staticmethod(lltype.malloc)
-    nullptr = staticmethod(lltype.nullptr)
-
-    @staticmethod
-    def malloc_immortal(T):
-        return lltype.malloc(T, immortal=True)
-
-    def _get_NODE(self):
-        NODE = lltype.GcForwardReference()
-        NODE.become(lltype.GcStruct('NODE', ('value', lltype.Signed),
-                                            ('next', lltype.Ptr(NODE))))
-        return NODE
-    
-class OOJitMixin(JitMixin):
-    type_system = 'ootype'
-    #CPUClass = runner.OOtypeCPU
-
-    def setup_class(cls):
-        py.test.skip("ootype tests skipped for now")
-
-    @staticmethod
-    def Ptr(T):
-        return T
-
-    @staticmethod
-    def GcStruct(name, *fields, **kwds):
-        if 'hints' in kwds:
-            kwds['_hints'] = kwds['hints']
-            del kwds['hints']
-        I = ootype.Instance(name, ootype.ROOT, dict(fields), **kwds)
-        return I
-
-    malloc = staticmethod(ootype.new)
-    nullptr = staticmethod(ootype.null)
-
-    @staticmethod
-    def malloc_immortal(T):
-        return ootype.new(T)
-
-    def _get_NODE(self):
-        NODE = ootype.Instance('NODE', ootype.ROOT, {})
-        NODE._add_fields({'value': ootype.Signed,
-                          'next': NODE})
-        return NODE
-
+from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
 
 class BasicTests:    
 

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

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

diff --git a/pypy/jit/metainterp/test/test_virtualizable.py b/pypy/jit/metainterp/test/test_virtualizable.py
--- a/pypy/jit/metainterp/test/test_virtualizable.py
+++ b/pypy/jit/metainterp/test/test_virtualizable.py
@@ -6,7 +6,7 @@
 from pypy.jit.codewriter import heaptracker
 from pypy.rlib.jit import JitDriver, hint, dont_look_inside
 from pypy.rlib.rarithmetic import intmask
-from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
+from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
 from pypy.rpython.rclass import FieldListAccessor
 from pypy.jit.metainterp.warmspot import get_stats, get_translator
 from pypy.jit.metainterp import history

diff --git a/pypy/module/__builtin__/app_inspect.py b/pypy/module/__builtin__/app_inspect.py
--- a/pypy/module/__builtin__/app_inspect.py
+++ b/pypy/module/__builtin__/app_inspect.py
@@ -76,8 +76,8 @@
         result.sort()
         return result
 
-    elif hasattr(obj, '__dir__'):
-        result = obj.__dir__()
+    elif hasattr(type(obj), '__dir__'):
+        result = type(obj).__dir__(obj)
         if not isinstance(result, list):
             raise TypeError("__dir__() must return a list, not %r" % (
                 type(result),))
@@ -87,11 +87,14 @@
     else: #(regular item)
         Dict = {}
         try:
-            Dict.update(obj.__dict__)
-        except AttributeError: pass
+            if isinstance(obj.__dict__, dict):
+                Dict.update(obj.__dict__)
+        except AttributeError:
+            pass
         try:
             Dict.update(_classdir(obj.__class__))
-        except AttributeError: pass
+        except AttributeError:
+            pass
 
         ## Comment from object.c:
         ## /* Merge in __members__ and __methods__ (if any).
@@ -99,10 +102,14 @@
         ## XXX needed to get at im_self etc of method objects. */
         for attr in ['__members__','__methods__']:
             try:
-                for item in getattr(obj, attr):
+                l = getattr(obj, attr)
+                if not isinstance(l, list):
+                    continue
+                for item in l:
                     if isinstance(item, types.StringTypes):
                         Dict[item] = None
-            except (AttributeError, TypeError): pass
+            except (AttributeError, TypeError):
+                pass
 
         result = Dict.keys()
         result.sort()

diff --git a/pypy/rpython/lltypesystem/test/test_rffi.py b/pypy/rpython/lltypesystem/test/test_rffi.py
--- a/pypy/rpython/lltypesystem/test/test_rffi.py
+++ b/pypy/rpython/lltypesystem/test/test_rffi.py
@@ -728,6 +728,7 @@
     
         for ll, ctp in cache.items():
             assert sizeof(ll) == ctypes.sizeof(ctp)
+            assert sizeof(lltype.Typedef(ll, 'test')) == sizeof(ll)
         assert not size_and_sign(lltype.Signed)[1]
         assert not size_and_sign(lltype.Char)[1]
         assert not size_and_sign(lltype.UniChar)[1]

diff --git a/pypy/jit/metainterp/test/test_optimizeopt.py b/pypy/jit/metainterp/test/test_optimizeopt.py
--- a/pypy/jit/metainterp/test/test_optimizeopt.py
+++ b/pypy/jit/metainterp/test/test_optimizeopt.py
@@ -135,7 +135,7 @@
         return type(self) is type(other)      # xxx obscure
     def clone_if_mutable(self):
         res = Storage(self.metainterp_sd, self.original_greenkey)
-        self.copy_all_attrbutes_into(res)
+        self.copy_all_attributes_into(res)
         return res
 
 def _sortboxes(boxes):
@@ -2757,7 +2757,7 @@
         """
         self.optimize_loop(ops, expected)
 
-    def test_fold_partially_constant_ops(self):
+    def test_fold_partially_constant_add_sub(self):
         ops = """
         [i0]
         i1 = int_sub(i0, 0)
@@ -2791,7 +2791,7 @@
         """
         self.optimize_loop(ops, expected)
 
-    def test_fold_partially_constant_ops_ovf(self):
+    def test_fold_partially_constant_add_sub_ovf(self):
         ops = """
         [i0]
         i1 = int_sub_ovf(i0, 0)
@@ -2828,6 +2828,21 @@
         """
         self.optimize_loop(ops, expected)
 
+    def test_fold_partially_constant_shift(self):
+        ops = """
+        [i0]
+        i1 = int_lshift(i0, 0)
+        i2 = int_rshift(i1, 0)
+        i3 = int_eq(i2, i0)
+        guard_true(i3) []
+        jump(i2)
+        """
+        expected = """
+        [i0]
+        jump(i0)
+        """
+        self.optimize_loop(ops, expected)
+
     # ----------
 
 class TestLLtype(OptimizeOptTest, LLtypeMixin):
@@ -4960,6 +4975,58 @@
         p2 = new_with_vtable(ConstClass(node_vtable))
         setfield_gc(p2, i1, descr=nextdescr)
         """
+        py.test.skip("no test here")
+
+    def test_immutable_not(self):
+        ops = """
+        []
+        p0 = new_with_vtable(ConstClass(intobj_noimmut_vtable))
+        setfield_gc(p0, 42, descr=noimmut_intval)
+        escape(p0)
+        jump()
+        """
+        self.optimize_loop(ops, ops)
+
+    def test_immutable_variable(self):
+        ops = """
+        [i0]
+        p0 = new_with_vtable(ConstClass(intobj_immut_vtable))
+        setfield_gc(p0, i0, descr=immut_intval)
+        escape(p0)
+        jump(i0)
+        """
+        self.optimize_loop(ops, ops)
+
+    def test_immutable_incomplete(self):
+        ops = """
+        []
+        p0 = new_with_vtable(ConstClass(intobj_immut_vtable))
+        escape(p0)
+        jump()
+        """
+        self.optimize_loop(ops, ops)
+
+    def test_immutable_constantfold(self):
+        ops = """
+        []
+        p0 = new_with_vtable(ConstClass(intobj_immut_vtable))
+        setfield_gc(p0, 1242, descr=immut_intval)
+        escape(p0)
+        jump()
+        """
+        from pypy.rpython.lltypesystem import lltype, llmemory
+        class IntObj1242(object):
+            _TYPE = llmemory.GCREF.TO
+            def __eq__(self, other):
+                return other.container.intval == 1242
+        self.namespace['intobj1242'] = lltype._ptr(llmemory.GCREF,
+                                                   IntObj1242())
+        expected = """
+        []
+        escape(ConstPtr(intobj1242))
+        jump()
+        """
+        self.optimize_loop(ops, expected)
 
     # ----------
     def optimize_strunicode_loop(self, ops, optops, preamble=None):


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

diff --git a/pypy/jit/metainterp/optimizeopt/optimizer.py b/pypy/jit/metainterp/optimizeopt/optimizer.py
--- a/pypy/jit/metainterp/optimizeopt/optimizer.py
+++ b/pypy/jit/metainterp/optimizeopt/optimizer.py
@@ -514,12 +514,10 @@
                     break
             else:
                 # all constant arguments: constant-fold away
-                argboxes = [self.get_constant_box(op.getarg(i))
-                            for i in range(op.numargs())]
-                resbox = execute_nonspec(self.cpu, None,
-                                         op.getopnum(), argboxes, op.getdescr())
-                # FIXME: Don't we need to check for an overflow here?
-                self.make_constant(op.result, resbox.constbox())
+                resbox = self.constant_fold(op)
+                # note that INT_xxx_OVF is not done from here, and the
+                # overflows in the INT_xxx operations are ignored
+                self.make_constant(op.result, resbox)
                 return
 
             # did we do the exact same operation already?
@@ -538,6 +536,13 @@
         if nextop:
             self.emit_operation(nextop)
 
+    def constant_fold(self, op):
+        argboxes = [self.get_constant_box(op.getarg(i))
+                    for i in range(op.numargs())]
+        resbox = execute_nonspec(self.cpu, None,
+                                 op.getopnum(), argboxes, op.getdescr())
+        return resbox.constbox()
+
     #def optimize_GUARD_NO_OVERFLOW(self, op):
     #    # otherwise the default optimizer will clear fields, which is unwanted
     #    # in this case

diff --git a/pypy/jit/metainterp/test/test_jitdriver.py b/pypy/jit/metainterp/test/test_jitdriver.py
--- a/pypy/jit/metainterp/test/test_jitdriver.py
+++ b/pypy/jit/metainterp/test/test_jitdriver.py
@@ -1,6 +1,6 @@
 """Tests for multiple JitDrivers."""
 from pypy.rlib.jit import JitDriver, unroll_safe
-from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
+from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
 from pypy.jit.metainterp.warmspot import get_stats
 
 

diff --git a/pypy/jit/metainterp/test/test_basic.py b/pypy/jit/metainterp/test/test_basic.py
deleted file mode 100644
--- a/pypy/jit/metainterp/test/test_basic.py
+++ /dev/null
@@ -1,2411 +0,0 @@
-import py
-import sys
-from pypy.rlib.jit import JitDriver, we_are_jitted, hint, dont_look_inside
-from pypy.rlib.jit import loop_invariant
-from pypy.rlib.jit import jit_debug, assert_green, AssertGreenFailed
-from pypy.rlib.jit import unroll_safe, current_trace_length
-from pypy.jit.metainterp.warmspot import ll_meta_interp, get_stats
-from pypy.jit.backend.llgraph import runner
-from pypy.jit.metainterp import pyjitpl, history
-from pypy.jit.metainterp.warmstate import set_future_value
-from pypy.jit.codewriter.policy import JitPolicy, StopAtXPolicy
-from pypy.jit.codewriter import longlong
-from pypy import conftest
-from pypy.rlib.rarithmetic import ovfcheck
-from pypy.jit.metainterp.typesystem import LLTypeHelper, OOTypeHelper
-from pypy.rpython.lltypesystem import lltype, llmemory
-from pypy.rpython.ootypesystem import ootype
-from pypy.jit.metainterp.optimizeopt import ALL_OPTS_DICT
-
-def _get_jitcodes(testself, CPUClass, func, values, type_system,
-                  supports_longlong=False, **kwds):
-    from pypy.jit.codewriter import support, codewriter
-
-    class FakeJitCell:
-        __compiled_merge_points = []
-        def get_compiled_merge_points(self):
-            return self.__compiled_merge_points[:]
-        def set_compiled_merge_points(self, lst):
-            self.__compiled_merge_points = lst
-
-    class FakeWarmRunnerState:
-        def attach_unoptimized_bridge_from_interp(self, greenkey, newloop):
-            pass
-
-        def jit_cell_at_key(self, greenkey):
-            assert greenkey == []
-            return self._cell
-        _cell = FakeJitCell()
-
-        trace_limit = sys.maxint
-        enable_opts = ALL_OPTS_DICT
-
-    func._jit_unroll_safe_ = True
-    rtyper = support.annotate(func, values, type_system=type_system)
-    graphs = rtyper.annotator.translator.graphs
-    result_kind = history.getkind(graphs[0].getreturnvar().concretetype)[0]
-
-    class FakeJitDriverSD:
-        num_green_args = 0
-        portal_graph = graphs[0]
-        virtualizable_info = None
-        greenfield_info = None
-        result_type = result_kind
-        portal_runner_ptr = "???"
-
-    stats = history.Stats()
-    cpu = CPUClass(rtyper, stats, None, False)
-    cw = codewriter.CodeWriter(cpu, [FakeJitDriverSD()])
-    testself.cw = cw
-    policy = JitPolicy()
-    policy.set_supports_longlong(supports_longlong)
-    cw.find_all_graphs(policy)
-    #
-    testself.warmrunnerstate = FakeWarmRunnerState()
-    testself.warmrunnerstate.cpu = cpu
-    FakeJitDriverSD.warmstate = testself.warmrunnerstate
-    if hasattr(testself, 'finish_setup_for_interp_operations'):
-        testself.finish_setup_for_interp_operations()
-    #
-    cw.make_jitcodes(verbose=True)
-
-def _run_with_blackhole(testself, args):
-    from pypy.jit.metainterp.blackhole import BlackholeInterpBuilder
-    cw = testself.cw
-    blackholeinterpbuilder = BlackholeInterpBuilder(cw)
-    blackholeinterp = blackholeinterpbuilder.acquire_interp()
-    count_i = count_r = count_f = 0
-    for value in args:
-        T = lltype.typeOf(value)
-        if T == lltype.Signed:
-            blackholeinterp.setarg_i(count_i, value)
-            count_i += 1
-        elif T == llmemory.GCREF:
-            blackholeinterp.setarg_r(count_r, value)
-            count_r += 1
-        elif T == lltype.Float:
-            value = longlong.getfloatstorage(value)
-            blackholeinterp.setarg_f(count_f, value)
-            count_f += 1
-        else:
-            raise TypeError(T)
-    [jitdriver_sd] = cw.callcontrol.jitdrivers_sd
-    blackholeinterp.setposition(jitdriver_sd.mainjitcode, 0)
-    blackholeinterp.run()
-    return blackholeinterp._final_result_anytype()
-
-def _run_with_pyjitpl(testself, args):
-
-    class DoneWithThisFrame(Exception):
-        pass
-
-    class DoneWithThisFrameRef(DoneWithThisFrame):
-        def __init__(self, cpu, *args):
-            DoneWithThisFrame.__init__(self, *args)
-
-    cw = testself.cw
-    opt = history.Options(listops=True)
-    metainterp_sd = pyjitpl.MetaInterpStaticData(cw.cpu, opt)
-    metainterp_sd.finish_setup(cw)
-    [jitdriver_sd] = metainterp_sd.jitdrivers_sd
-    metainterp = pyjitpl.MetaInterp(metainterp_sd, jitdriver_sd)
-    metainterp_sd.DoneWithThisFrameInt = DoneWithThisFrame
-    metainterp_sd.DoneWithThisFrameRef = DoneWithThisFrameRef
-    metainterp_sd.DoneWithThisFrameFloat = DoneWithThisFrame
-    testself.metainterp = metainterp
-    try:
-        metainterp.compile_and_run_once(jitdriver_sd, *args)
-    except DoneWithThisFrame, e:
-        #if conftest.option.view:
-        #    metainterp.stats.view()
-        return e.args[0]
-    else:
-        raise Exception("FAILED")
-
-def _run_with_machine_code(testself, args):
-    metainterp = testself.metainterp
-    num_green_args = metainterp.jitdriver_sd.num_green_args
-    loop_tokens = metainterp.get_compiled_merge_points(args[:num_green_args])
-    if len(loop_tokens) != 1:
-        return NotImplemented
-    # a loop was successfully created by _run_with_pyjitpl(); call it
-    cpu = metainterp.cpu
-    for i in range(len(args) - num_green_args):
-        x = args[num_green_args + i]
-        typecode = history.getkind(lltype.typeOf(x))
-        set_future_value(cpu, i, x, typecode)
-    faildescr = cpu.execute_token(loop_tokens[0])
-    assert faildescr.__class__.__name__.startswith('DoneWithThisFrameDescr')
-    if metainterp.jitdriver_sd.result_type == history.INT:
-        return cpu.get_latest_value_int(0)
-    elif metainterp.jitdriver_sd.result_type == history.REF:
-        return cpu.get_latest_value_ref(0)
-    elif metainterp.jitdriver_sd.result_type == history.FLOAT:
-        return cpu.get_latest_value_float(0)
-    else:
-        return None
-
-
-class JitMixin:
-    basic = True
-    def check_loops(self, expected=None, everywhere=False, **check):
-        get_stats().check_loops(expected=expected, everywhere=everywhere,
-                                **check)
-    def check_loop_count(self, count):
-        """NB. This is a hack; use check_tree_loop_count() or
-        check_enter_count() for the real thing.
-        This counts as 1 every bridge in addition to every loop; and it does
-        not count at all the entry bridges from interpreter, although they
-        are TreeLoops as well."""
-        assert get_stats().compiled_count == count
-    def check_tree_loop_count(self, count):
-        assert len(get_stats().loops) == count
-    def check_loop_count_at_most(self, count):
-        assert get_stats().compiled_count <= count
-    def check_enter_count(self, count):
-        assert get_stats().enter_count == count
-    def check_enter_count_at_most(self, count):
-        assert get_stats().enter_count <= count
-    def check_jumps(self, maxcount):
-        assert get_stats().exec_jumps <= maxcount
-    def check_aborted_count(self, count):
-        assert get_stats().aborted_count == count
-    def check_aborted_count_at_least(self, count):
-        assert get_stats().aborted_count >= count
-
-    def meta_interp(self, *args, **kwds):
-        kwds['CPUClass'] = self.CPUClass
-        kwds['type_system'] = self.type_system
-        if "backendopt" not in kwds:
-            kwds["backendopt"] = False
-        return ll_meta_interp(*args, **kwds)
-
-    def interp_operations(self, f, args, **kwds):
-        # get the JitCodes for the function f
-        _get_jitcodes(self, self.CPUClass, f, args, self.type_system, **kwds)
-        # try to run it with blackhole.py
-        result1 = _run_with_blackhole(self, args)
-        # try to run it with pyjitpl.py
-        result2 = _run_with_pyjitpl(self, args)
-        assert result1 == result2
-        # try to run it by running the code compiled just before
-        result3 = _run_with_machine_code(self, args)
-        assert result1 == result3 or result3 == NotImplemented
-        #
-        if (longlong.supports_longlong and
-            isinstance(result1, longlong.r_float_storage)):
-            result1 = longlong.getrealfloat(result1)
-        return result1
-
-    def check_history(self, expected=None, **isns):
-        # this can be used after calling meta_interp
-        get_stats().check_history(expected, **isns)
-
-    def check_operations_history(self, expected=None, **isns):
-        # this can be used after interp_operations
-        if expected is not None:
-            expected = dict(expected)
-            expected['jump'] = 1
-        self.metainterp.staticdata.stats.check_history(expected, **isns)
-
-
-class LLJitMixin(JitMixin):
-    type_system = 'lltype'
-    CPUClass = runner.LLtypeCPU
-
-    @staticmethod
-    def Ptr(T):
-        return lltype.Ptr(T)
-
-    @staticmethod
-    def GcStruct(name, *fields, **kwds):
-        S = lltype.GcStruct(name, *fields, **kwds)
-        return S
-
-    malloc = staticmethod(lltype.malloc)
-    nullptr = staticmethod(lltype.nullptr)
-
-    @staticmethod
-    def malloc_immortal(T):
-        return lltype.malloc(T, immortal=True)
-
-    def _get_NODE(self):
-        NODE = lltype.GcForwardReference()
-        NODE.become(lltype.GcStruct('NODE', ('value', lltype.Signed),
-                                            ('next', lltype.Ptr(NODE))))
-        return NODE
-    
-class OOJitMixin(JitMixin):
-    type_system = 'ootype'
-    #CPUClass = runner.OOtypeCPU
-
-    def setup_class(cls):
-        py.test.skip("ootype tests skipped for now")
-
-    @staticmethod
-    def Ptr(T):
-        return T
-
-    @staticmethod
-    def GcStruct(name, *fields, **kwds):
-        if 'hints' in kwds:
-            kwds['_hints'] = kwds['hints']
-            del kwds['hints']
-        I = ootype.Instance(name, ootype.ROOT, dict(fields), **kwds)
-        return I
-
-    malloc = staticmethod(ootype.new)
-    nullptr = staticmethod(ootype.null)
-
-    @staticmethod
-    def malloc_immortal(T):
-        return ootype.new(T)
-
-    def _get_NODE(self):
-        NODE = ootype.Instance('NODE', ootype.ROOT, {})
-        NODE._add_fields({'value': ootype.Signed,
-                          'next': NODE})
-        return NODE
-
-
-class BasicTests:    
-
-    def test_basic(self):
-        def f(x, y):
-            return x + y
-        res = self.interp_operations(f, [40, 2])
-        assert res == 42
-
-    def test_basic_inst(self):
-        class A:
-            pass
-        def f(n):
-            a = A()
-            a.x = n
-            return a.x
-        res = self.interp_operations(f, [42])
-        assert res == 42
-
-    def test_uint_floordiv(self):
-        from pypy.rlib.rarithmetic import r_uint
-        
-        def f(a, b):
-            a = r_uint(a)
-            b = r_uint(b)
-            return a/b
-
-        res = self.interp_operations(f, [-4, 3])
-        assert res == long(r_uint(-4)) // 3
-
-    def test_direct_call(self):
-        def g(n):
-            return n + 2
-        def f(a, b):
-            return g(a) + g(b)
-        res = self.interp_operations(f, [8, 98])
-        assert res == 110
-
-    def test_direct_call_with_guard(self):
-        def g(n):
-            if n < 0:
-                return 0
-            return n + 2
-        def f(a, b):
-            return g(a) + g(b)
-        res = self.interp_operations(f, [8, 98])
-        assert res == 110
-
-    def test_loop(self):
-        myjitdriver = JitDriver(greens = [], reds = ['x', 'y', 'res'])
-        def f(x, y):
-            res = 0
-            while y > 0:
-                myjitdriver.can_enter_jit(x=x, y=y, res=res)
-                myjitdriver.jit_merge_point(x=x, y=y, res=res)
-                res += x
-                y -= 1
-            return res
-        res = self.meta_interp(f, [6, 7])
-        assert res == 42
-        self.check_loop_count(1)
-        self.check_loops({'guard_true': 1,
-                          'int_add': 1, 'int_sub': 1, 'int_gt': 1,
-                          'jump': 1})
-        if self.basic:
-            found = 0
-            for op in get_stats().loops[0]._all_operations():
-                if op.getopname() == 'guard_true':
-                    liveboxes = op.getfailargs()
-                    assert len(liveboxes) == 3
-                    for box in liveboxes:
-                        assert isinstance(box, history.BoxInt)
-                    found += 1
-            assert found == 1
-
-    def test_loop_invariant_mul1(self):
-        myjitdriver = JitDriver(greens = [], reds = ['y', 'res', 'x'])
-        def f(x, y):
-            res = 0
-            while y > 0:
-                myjitdriver.can_enter_jit(x=x, y=y, res=res)
-                myjitdriver.jit_merge_point(x=x, y=y, res=res)
-                res += x * x
-                y -= 1
-            return res
-        res = self.meta_interp(f, [6, 7])
-        assert res == 252
-        self.check_loop_count(1)
-        self.check_loops({'guard_true': 1,
-                          'int_add': 1, 'int_sub': 1, 'int_gt': 1,
-                          'jump': 1})
-
-    def test_loop_invariant_mul_ovf(self):
-        myjitdriver = JitDriver(greens = [], reds = ['y', 'res', 'x'])
-        def f(x, y):
-            res = 0
-            while y > 0:
-                myjitdriver.can_enter_jit(x=x, y=y, res=res)
-                myjitdriver.jit_merge_point(x=x, y=y, res=res)
-                b = y * 2
-                res += ovfcheck(x * x) + b
-                y -= 1
-            return res
-        res = self.meta_interp(f, [6, 7])
-        assert res == 308
-        self.check_loop_count(1)
-        self.check_loops({'guard_true': 1,
-                          'int_add': 2, 'int_sub': 1, 'int_gt': 1,
-                          'int_lshift': 1,
-                          'jump': 1})
-
-    def test_loop_invariant_mul_bridge1(self):
-        myjitdriver = JitDriver(greens = [], reds = ['y', 'res', 'x'])
-        def f(x, y):
-            res = 0
-            while y > 0:
-                myjitdriver.can_enter_jit(x=x, y=y, res=res)
-                myjitdriver.jit_merge_point(x=x, y=y, res=res)
-                res += x * x
-                if y<16:
-                    x += 1
-                y -= 1
-            return res
-        res = self.meta_interp(f, [6, 32])
-        assert res == 3427
-        self.check_loop_count(3)
-
-    def test_loop_invariant_mul_bridge_maintaining1(self):
-        myjitdriver = JitDriver(greens = [], reds = ['y', 'res', 'x'])
-        def f(x, y):
-            res = 0
-            while y > 0:
-                myjitdriver.can_enter_jit(x=x, y=y, res=res)
-                myjitdriver.jit_merge_point(x=x, y=y, res=res)
-                res += x * x
-                if y<16:
-                    res += 1
-                y -= 1
-            return res
-        res = self.meta_interp(f, [6, 32])
-        assert res == 1167
-        self.check_loop_count(3)
-        self.check_loops({'int_add': 3, 'int_lt': 2,
-                          'int_sub': 2, 'guard_false': 1,
-                          'jump': 2,
-                          'int_gt': 1, 'guard_true': 2})
-
-
-    def test_loop_invariant_mul_bridge_maintaining2(self):
-        myjitdriver = JitDriver(greens = [], reds = ['y', 'res', 'x'])
-        def f(x, y):
-            res = 0
-            while y > 0:
-                myjitdriver.can_enter_jit(x=x, y=y, res=res)
-                myjitdriver.jit_merge_point(x=x, y=y, res=res)
-                z = x * x
-                res += z
-                if y<16:
-                    res += z
-                y -= 1
-            return res
-        res = self.meta_interp(f, [6, 32])
-        assert res == 1692
-        self.check_loop_count(3)
-        self.check_loops({'int_add': 3, 'int_lt': 2,
-                          'int_sub': 2, 'guard_false': 1,
-                          'jump': 2,
-                          'int_gt': 1, 'guard_true': 2})
-
-    def test_loop_invariant_mul_bridge_maintaining3(self):
-        myjitdriver = JitDriver(greens = [], reds = ['y', 'res', 'x', 'm'])
-        def f(x, y, m):
-            res = 0
-            while y > 0:
-                myjitdriver.can_enter_jit(x=x, y=y, res=res, m=m)
-                myjitdriver.jit_merge_point(x=x, y=y, res=res, m=m)
-                z = x * x
-                res += z
-                if y<m:
-                    res += z
-                y -= 1
-            return res
-        res = self.meta_interp(f, [6, 32, 16])
-        assert res == 1692
-        self.check_loop_count(3)
-        self.check_loops({'int_add': 2, 'int_lt': 1,
-                          'int_sub': 2, 'guard_false': 1,
-                          'jump': 2, 'int_mul': 1,
-                          'int_gt': 2, 'guard_true': 2})
-
-    def test_loop_invariant_intbox(self):
-        myjitdriver = JitDriver(greens = [], reds = ['y', 'res', 'x'])
-        class I:
-            __slots__ = 'intval'
-            _immutable_ = True
-            def __init__(self, intval):
-                self.intval = intval
-        def f(i, y):
-            res = 0
-            x = I(i)
-            while y > 0:
-                myjitdriver.can_enter_jit(x=x, y=y, res=res)
-                myjitdriver.jit_merge_point(x=x, y=y, res=res)
-                res += x.intval * x.intval
-                y -= 1
-            return res
-        res = self.meta_interp(f, [6, 7])
-        assert res == 252
-        self.check_loop_count(1)
-        self.check_loops({'guard_true': 1,
-                          'int_add': 1, 'int_sub': 1, 'int_gt': 1,
-                          'jump': 1})
-
-    def test_loops_are_transient(self):
-        import gc, weakref
-        myjitdriver = JitDriver(greens = [], reds = ['x', 'y', 'res'])
-        def f(x, y):
-            res = 0
-            while y > 0:
-                myjitdriver.can_enter_jit(x=x, y=y, res=res)
-                myjitdriver.jit_merge_point(x=x, y=y, res=res)
-                res += x
-                if y%2:
-                    res *= 2
-                y -= 1
-            return res
-        wr_loops = []
-        old_init = history.TreeLoop.__init__.im_func
-        try:
-            def track_init(self, name):
-                old_init(self, name)
-                wr_loops.append(weakref.ref(self))
-            history.TreeLoop.__init__ = track_init
-            res = self.meta_interp(f, [6, 15], no_stats=True)
-        finally:
-            history.TreeLoop.__init__ = old_init
-            
-        assert res == f(6, 15)
-        gc.collect()
-
-        #assert not [wr for wr in wr_loops if wr()]
-        for loop in [wr for wr in wr_loops if wr()]:
-            assert loop().name == 'short preamble'
-
-    def test_string(self):
-        def f(n):
-            bytecode = 'adlfkj' + chr(n)
-            if n < len(bytecode):
-                return bytecode[n]
-            else:
-                return "?"
-        res = self.interp_operations(f, [1])
-        assert res == ord("d") # XXX should be "d"
-        res = self.interp_operations(f, [6])
-        assert res == 6
-        res = self.interp_operations(f, [42])
-        assert res == ord("?")
-
-    def test_chr2str(self):
-        def f(n):
-            s = chr(n)
-            return s[0]
-        res = self.interp_operations(f, [3])
-        assert res == 3
-
-    def test_unicode(self):
-        def f(n):
-            bytecode = u'adlfkj' + unichr(n)
-            if n < len(bytecode):
-                return bytecode[n]
-            else:
-                return u"?"
-        res = self.interp_operations(f, [1])
-        assert res == ord(u"d") # XXX should be "d"
-        res = self.interp_operations(f, [6])
-        assert res == 6
-        res = self.interp_operations(f, [42])
-        assert res == ord(u"?")
-
-    def test_residual_call(self):
-        @dont_look_inside
-        def externfn(x, y):
-            return x * y
-        def f(n):
-            return externfn(n, n+1)
-        res = self.interp_operations(f, [6])
-        assert res == 42
-        self.check_operations_history(int_add=1, int_mul=0, call=1, guard_no_exception=0)
-
-    def test_residual_call_pure(self):
-        def externfn(x, y):
-            return x * y
-        externfn._pure_function_ = True
-        def f(n):
-            n = hint(n, promote=True)
-            return externfn(n, n+1)
-        res = self.interp_operations(f, [6])
-        assert res == 42
-        # CALL_PURE is not recorded in the history if all-constant args
-        self.check_operations_history(int_add=0, int_mul=0,
-                                      call=0, call_pure=0)
-
-    def test_residual_call_pure_1(self):
-        def externfn(x, y):
-            return x * y
-        externfn._pure_function_ = True
-        def f(n):
-            return externfn(n, n+1)
-        res = self.interp_operations(f, [6])
-        assert res == 42
-        # CALL_PURE is recorded in the history if not-all-constant args
-        self.check_operations_history(int_add=1, int_mul=0,
-                                      call=0, call_pure=1)
-
-    def test_residual_call_pure_2(self):
-        myjitdriver = JitDriver(greens = [], reds = ['n'])
-        def externfn(x):
-            return x - 1
-        externfn._pure_function_ = True
-        def f(n):
-            while n > 0:
-                myjitdriver.can_enter_jit(n=n)
-                myjitdriver.jit_merge_point(n=n)
-                n = externfn(n)
-            return n
-        res = self.meta_interp(f, [7])
-        assert res == 0
-        # CALL_PURE is recorded in the history, but turned into a CALL
-        # by optimizeopt.py
-        self.check_loops(int_sub=0, call=1, call_pure=0)
-
-    def test_constfold_call_pure(self):
-        myjitdriver = JitDriver(greens = ['m'], reds = ['n'])
-        def externfn(x):
-            return x - 3
-        externfn._pure_function_ = True
-        def f(n, m):
-            while n > 0:
-                myjitdriver.can_enter_jit(n=n, m=m)
-                myjitdriver.jit_merge_point(n=n, m=m)
-                n -= externfn(m)
-            return n
-        res = self.meta_interp(f, [21, 5])
-        assert res == -1
-        # the CALL_PURE is constant-folded away by optimizeopt.py
-        self.check_loops(int_sub=1, call=0, call_pure=0)
-
-    def test_constfold_call_pure_2(self):
-        myjitdriver = JitDriver(greens = ['m'], reds = ['n'])
-        def externfn(x):
-            return x - 3
-        externfn._pure_function_ = True
-        class V:
-            def __init__(self, value):
-                self.value = value
-        def f(n, m):
-            while n > 0:
-                myjitdriver.can_enter_jit(n=n, m=m)
-                myjitdriver.jit_merge_point(n=n, m=m)
-                v = V(m)
-                n -= externfn(v.value)
-            return n
-        res = self.meta_interp(f, [21, 5])
-        assert res == -1
-        # the CALL_PURE is constant-folded away by optimizeopt.py
-        self.check_loops(int_sub=1, call=0, call_pure=0)
-
-    def test_pure_function_returning_object(self):
-        myjitdriver = JitDriver(greens = ['m'], reds = ['n'])
-        class V:
-            def __init__(self, x):
-                self.x = x
-        v1 = V(1)
-        v2 = V(2)
-        def externfn(x):
-            if x:
-                return v1
-            else:
-                return v2
-        externfn._pure_function_ = True
-        def f(n, m):
-            while n > 0:
-                myjitdriver.can_enter_jit(n=n, m=m)
-                myjitdriver.jit_merge_point(n=n, m=m)
-                m = V(m).x
-                n -= externfn(m).x + externfn(m + m - m).x
-            return n
-        res = self.meta_interp(f, [21, 5])
-        assert res == -1
-        # the CALL_PURE is constant-folded away by optimizeopt.py
-        self.check_loops(int_sub=1, call=0, call_pure=0, getfield_gc=0)
-
-    def test_constant_across_mp(self):
-        myjitdriver = JitDriver(greens = [], reds = ['n'])
-        class X(object):
-            pass
-        def f(n):
-            while n > -100:
-                myjitdriver.can_enter_jit(n=n)
-                myjitdriver.jit_merge_point(n=n)
-                x = X()
-                x.arg = 5
-                if n <= 0: break
-                n -= x.arg
-                x.arg = 6   # prevents 'x.arg' from being annotated as constant
-            return n
-        res = self.meta_interp(f, [31])
-        assert res == -4
-
-    def test_stopatxpolicy(self):
-        myjitdriver = JitDriver(greens = [], reds = ['y'])
-        def internfn(y):
-            return y * 3
-        def externfn(y):
-            return y % 4
-        def f(y):
-            while y >= 0:
-                myjitdriver.can_enter_jit(y=y)
-                myjitdriver.jit_merge_point(y=y)
-                if y & 7:
-                    f = internfn
-                else:
-                    f = externfn
-                f(y)
-                y -= 1
-            return 42
-        policy = StopAtXPolicy(externfn)
-        res = self.meta_interp(f, [31], policy=policy)
-        assert res == 42
-        self.check_loops(int_mul=1, int_mod=0)
-
-    def test_we_are_jitted(self):
-        myjitdriver = JitDriver(greens = [], reds = ['y'])
-        def f(y):
-            while y >= 0:
-                myjitdriver.can_enter_jit(y=y)
-                myjitdriver.jit_merge_point(y=y)
-                if we_are_jitted():
-                    x = 1
-                else:
-                    x = 10
-                y -= x
-            return y
-        assert f(55) == -5
-        res = self.meta_interp(f, [55])
-        assert res == -1
-
-    def test_confirm_enter_jit(self):
-        def confirm_enter_jit(x, y):
-            return x <= 5
-        myjitdriver = JitDriver(greens = ['x'], reds = ['y'],
-                                confirm_enter_jit = confirm_enter_jit)
-        def f(x, y):
-            while y >= 0:
-                myjitdriver.can_enter_jit(x=x, y=y)
-                myjitdriver.jit_merge_point(x=x, y=y)
-                y -= x
-            return y
-        #
-        res = self.meta_interp(f, [10, 84])
-        assert res == -6
-        self.check_loop_count(0)
-        #
-        res = self.meta_interp(f, [3, 19])
-        assert res == -2
-        self.check_loop_count(1)
-
-    def test_can_never_inline(self):
-        def can_never_inline(x):
-            return x > 50
-        myjitdriver = JitDriver(greens = ['x'], reds = ['y'],
-                                can_never_inline = can_never_inline)
-        @dont_look_inside
-        def marker():
-            pass
-        def f(x, y):
-            while y >= 0:
-                myjitdriver.can_enter_jit(x=x, y=y)
-                myjitdriver.jit_merge_point(x=x, y=y)
-                x += 1
-                if x == 4 or x == 61:
-                    marker()
-                y -= x
-            return y
-        #
-        res = self.meta_interp(f, [3, 6], repeat=7)
-        assert res == 6 - 4 - 5
-        self.check_history(call=0)   # because the trace starts in the middle
-        #
-        res = self.meta_interp(f, [60, 84], repeat=7)
-        assert res == 84 - 61 - 62
-        self.check_history(call=1)   # because the trace starts immediately
-
-    def test_format(self):
-        def f(n):
-            return len("<%d>" % n)
-        res = self.interp_operations(f, [421])
-        assert res == 5
-
-    def test_switch(self):
-        def f(n):
-            if n == -5:  return 12
-            elif n == 2: return 51
-            elif n == 7: return 1212
-            else:        return 42
-        res = self.interp_operations(f, [7])
-        assert res == 1212
-        res = self.interp_operations(f, [12311])
-        assert res == 42
-
-    def test_r_uint(self):
-        from pypy.rlib.rarithmetic import r_uint
-        myjitdriver = JitDriver(greens = [], reds = ['y'])
-        def f(y):
-            y = r_uint(y)
-            while y > 0:
-                myjitdriver.can_enter_jit(y=y)
-                myjitdriver.jit_merge_point(y=y)
-                y -= 1
-            return y
-        res = self.meta_interp(f, [10])
-        assert res == 0
-
-    def test_uint_operations(self):
-        from pypy.rlib.rarithmetic import r_uint
-        def f(n):
-            return ((r_uint(n) - 123) >> 1) <= r_uint(456)
-        res = self.interp_operations(f, [50])
-        assert res == False
-        self.check_operations_history(int_rshift=0, uint_rshift=1,
-                                      int_le=0, uint_le=1,
-                                      int_sub=1)
-
-    def test_uint_condition(self):
-        from pypy.rlib.rarithmetic import r_uint
-        def f(n):
-            if ((r_uint(n) - 123) >> 1) <= r_uint(456):
-                return 24
-            else:
-                return 12
-        res = self.interp_operations(f, [50])
-        assert res == 12
-        self.check_operations_history(int_rshift=0, uint_rshift=1,
-                                      int_le=0, uint_le=1,
-                                      int_sub=1)
-
-    def test_int_between(self):
-        #
-        def check(arg1, arg2, arg3, expect_result, **expect_operations):
-            from pypy.rpython.lltypesystem import lltype
-            from pypy.rpython.lltypesystem.lloperation import llop
-            loc = locals().copy()
-            exec py.code.Source("""
-                def f(n, m, p):
-                    arg1 = %(arg1)s
-                    arg2 = %(arg2)s
-                    arg3 = %(arg3)s
-                    return llop.int_between(lltype.Bool, arg1, arg2, arg3)
-            """ % locals()).compile() in loc
-            res = self.interp_operations(loc['f'], [5, 6, 7])
-            assert res == expect_result
-            self.check_operations_history(expect_operations)
-        #
-        check('n', 'm', 'p', True,  int_sub=2, uint_lt=1)
-        check('n', 'p', 'm', False, int_sub=2, uint_lt=1)
-        #
-        check('n', 'm', 6, False, int_sub=2, uint_lt=1)
-        #
-        check('n', 4, 'p', False, int_sub=2, uint_lt=1)
-        check('n', 5, 'p', True,  int_sub=2, uint_lt=1)
-        check('n', 8, 'p', False, int_sub=2, uint_lt=1)
-        #
-        check('n', 6, 7, True, int_sub=2, uint_lt=1)
-        #
-        check(-2, 'n', 'p', True,  int_sub=2, uint_lt=1)
-        check(-2, 'm', 'p', True,  int_sub=2, uint_lt=1)
-        check(-2, 'p', 'm', False, int_sub=2, uint_lt=1)
-        #check(0, 'n', 'p', True,  uint_lt=1)   xxx implement me
-        #check(0, 'm', 'p', True,  uint_lt=1)
-        #check(0, 'p', 'm', False, uint_lt=1)
-        #
-        check(2, 'n', 6, True,  int_sub=1, uint_lt=1)
-        check(2, 'm', 6, False, int_sub=1, uint_lt=1)
-        check(2, 'p', 6, False, int_sub=1, uint_lt=1)
-        check(5, 'n', 6, True,  int_eq=1)    # 6 == 5+1
-        check(5, 'm', 6, False, int_eq=1)    # 6 == 5+1
-        #
-        check(2, 6, 'm', False, int_sub=1, uint_lt=1)
-        check(2, 6, 'p', True,  int_sub=1, uint_lt=1)
-        #
-        check(2, 40, 6,  False)
-        check(2, 40, 60, True)
-
-    def test_getfield(self):
-        class A:
-            pass
-        a1 = A()
-        a1.foo = 5
-        a2 = A()
-        a2.foo = 8
-        def f(x):
-            if x > 5:
-                a = a1
-            else:
-                a = a2
-            return a.foo * x
-        res = self.interp_operations(f, [42])
-        assert res == 210
-        self.check_operations_history(getfield_gc=1)
-
-    def test_getfield_immutable(self):
-        class A:
-            _immutable_ = True
-        a1 = A()
-        a1.foo = 5
-        a2 = A()
-        a2.foo = 8
-        def f(x):
-            if x > 5:
-                a = a1
-            else:
-                a = a2
-            return a.foo * x
-        res = self.interp_operations(f, [42])
-        assert res == 210
-        self.check_operations_history(getfield_gc=0)
-
-    def test_setfield_bool(self):
-        class A:
-            def __init__(self):
-                self.flag = True
-        myjitdriver = JitDriver(greens = [], reds = ['n', 'obj'])
-        def f(n):
-            obj = A()
-            res = False
-            while n > 0:
-                myjitdriver.can_enter_jit(n=n, obj=obj)
-                myjitdriver.jit_merge_point(n=n, obj=obj)
-                obj.flag = False
-                n -= 1
-            return res
-        res = self.meta_interp(f, [7])
-        assert type(res) == bool
-        assert not res
-
-    def test_switch_dict(self):
-        def f(x):
-            if   x == 1: return 61
-            elif x == 2: return 511
-            elif x == 3: return -22
-            elif x == 4: return 81
-            elif x == 5: return 17
-            elif x == 6: return 54
-            elif x == 7: return 987
-            elif x == 8: return -12
-            elif x == 9: return 321
-            return -1
-        res = self.interp_operations(f, [5])
-        assert res == 17
-        res = self.interp_operations(f, [15])
-        assert res == -1
-
-    def test_int_add_ovf(self):
-        def f(x, y):
-            try:
-                return ovfcheck(x + y)
-            except OverflowError:
-                return -42
-        res = self.interp_operations(f, [-100, 2])
-        assert res == -98
-        res = self.interp_operations(f, [1, sys.maxint])
-        assert res == -42
-
-    def test_int_sub_ovf(self):
-        def f(x, y):
-            try:
-                return ovfcheck(x - y)
-            except OverflowError:
-                return -42
-        res = self.interp_operations(f, [-100, 2])
-        assert res == -102
-        res = self.interp_operations(f, [1, -sys.maxint])
-        assert res == -42
-
-    def test_int_mul_ovf(self):
-        def f(x, y):
-            try:
-                return ovfcheck(x * y)
-            except OverflowError:
-                return -42
-        res = self.interp_operations(f, [-100, 2])
-        assert res == -200
-        res = self.interp_operations(f, [-3, sys.maxint//2])
-        assert res == -42
-
-    def test_mod_ovf(self):
-        myjitdriver = JitDriver(greens = [], reds = ['n', 'x', 'y'])
-        def f(n, x, y):
-            while n > 0:
-                myjitdriver.can_enter_jit(x=x, y=y, n=n)
-                myjitdriver.jit_merge_point(x=x, y=y, n=n)
-                n -= ovfcheck(x % y)
-            return n
-        res = self.meta_interp(f, [20, 1, 2])
-        assert res == 0
-        self.check_loops(call=0)
-
-    def test_abs(self):
-        myjitdriver = JitDriver(greens = [], reds = ['i', 't'])
-        def f(i):
-            t = 0
-            while i < 10:
-                myjitdriver.can_enter_jit(i=i, t=t)
-                myjitdriver.jit_merge_point(i=i, t=t)
-                t += abs(i)
-                i += 1
-            return t
-        res = self.meta_interp(f, [-5])
-        assert res == 5+4+3+2+1+0+1+2+3+4+5+6+7+8+9
-
-    def test_float(self):
-        myjitdriver = JitDriver(greens = [], reds = ['x', 'y', 'res'])
-        def f(x, y):
-            x = float(x)
-            y = float(y)
-            res = 0.0
-            while y > 0.0:
-                myjitdriver.can_enter_jit(x=x, y=y, res=res)
-                myjitdriver.jit_merge_point(x=x, y=y, res=res)
-                res += x
-                y -= 1.0
-            return res
-        res = self.meta_interp(f, [6, 7])
-        assert res == 42.0
-        self.check_loop_count(1)
-        self.check_loops({'guard_true': 1,
-                          'float_add': 1, 'float_sub': 1, 'float_gt': 1,
-                          'jump': 1})
-
-    def test_print(self):
-        myjitdriver = JitDriver(greens = [], reds = ['n'])
-        def f(n):
-            while n > 0:
-                myjitdriver.can_enter_jit(n=n)
-                myjitdriver.jit_merge_point(n=n)
-                print n
-                n -= 1
-            return n
-        res = self.meta_interp(f, [7])
-        assert res == 0
-
-    def test_bridge_from_interpreter(self):
-        mydriver = JitDriver(reds = ['n'], greens = [])
-
-        def f(n):
-            while n > 0:
-                mydriver.can_enter_jit(n=n)
-                mydriver.jit_merge_point(n=n)
-                n -= 1
-
-        self.meta_interp(f, [20], repeat=7)
-        self.check_tree_loop_count(2)      # the loop and the entry path
-        # we get:
-        #    ENTER             - compile the new loop and the entry bridge
-        #    ENTER             - compile the leaving path
-        self.check_enter_count(2)
-
-    def test_bridge_from_interpreter_2(self):
-        # one case for backend - computing of framesize on guard failure
-        mydriver = JitDriver(reds = ['n'], greens = [])
-        glob = [1]
-
-        def f(n):
-            while n > 0:
-                mydriver.can_enter_jit(n=n)
-                mydriver.jit_merge_point(n=n)
-                if n == 17 and glob[0]:
-                    glob[0] = 0
-                    x = n + 1
-                    y = n + 2
-                    z = n + 3
-                    k = n + 4
-                    n -= 1
-                    n += x + y + z + k
-                    n -= x + y + z + k
-                n -= 1
-
-        self.meta_interp(f, [20], repeat=7)
-
-    def test_bridge_from_interpreter_3(self):
-        # one case for backend - computing of framesize on guard failure
-        mydriver = JitDriver(reds = ['n', 'x', 'y', 'z', 'k'], greens = [])
-        class Global:
-            pass
-        glob = Global()
-
-        def f(n):
-            glob.x = 1
-            x = 0
-            y = 0
-            z = 0
-            k = 0
-            while n > 0:
-                mydriver.can_enter_jit(n=n, x=x, y=y, z=z, k=k)
-                mydriver.jit_merge_point(n=n, x=x, y=y, z=z, k=k)
-                x += 10
-                y += 3
-                z -= 15
-                k += 4
-                if n == 17 and glob.x:
-                    glob.x = 0
-                    x += n + 1
-                    y += n + 2
-                    z += n + 3
-                    k += n + 4
-                    n -= 1
-                n -= 1
-            return x + 2*y + 3*z + 5*k + 13*n
-
-        res = self.meta_interp(f, [20], repeat=7)
-        assert res == f(20)
-
-    def test_bridge_from_interpreter_4(self):
-        jitdriver = JitDriver(reds = ['n', 'k'], greens = [])
-        
-        def f(n, k):
-            while n > 0:
-                jitdriver.can_enter_jit(n=n, k=k)
-                jitdriver.jit_merge_point(n=n, k=k)
-                if k:
-                    n -= 2
-                else:
-                    n -= 1
-            return n + k
-
-        from pypy.rpython.test.test_llinterp import get_interpreter, clear_tcache
-        from pypy.jit.metainterp.warmspot import WarmRunnerDesc
-        
-        interp, graph = get_interpreter(f, [0, 0], backendopt=False,
-                                        inline_threshold=0, type_system=self.type_system)
-        clear_tcache()
-        translator = interp.typer.annotator.translator
-        translator.config.translation.gc = "boehm"
-        warmrunnerdesc = WarmRunnerDesc(translator,
-                                        CPUClass=self.CPUClass)
-        state = warmrunnerdesc.jitdrivers_sd[0].warmstate
-        state.set_param_threshold(3)          # for tests
-        state.set_param_trace_eagerness(0)    # for tests
-        warmrunnerdesc.finish()
-        for n, k in [(20, 0), (20, 1)]:
-            interp.eval_graph(graph, [n, k])
-
-    def test_bridge_leaving_interpreter_5(self):
-        mydriver = JitDriver(reds = ['n', 'x'], greens = [])
-        class Global:
-            pass
-        glob = Global()
-
-        def f(n):
-            x = 0
-            glob.x = 1
-            while n > 0:
-                mydriver.can_enter_jit(n=n, x=x)
-                mydriver.jit_merge_point(n=n, x=x)
-                glob.x += 1
-                x += 3
-                n -= 1
-            glob.x += 100
-            return glob.x + x
-        res = self.meta_interp(f, [20], repeat=7)
-        assert res == f(20)
-
-    def test_instantiate_classes(self):
-        class Base: pass
-        class A(Base): foo = 72
-        class B(Base): foo = 8
-        def f(n):
-            if n > 5:
-                cls = A
-            else:
-                cls = B
-            return cls().foo
-        res = self.interp_operations(f, [3])
-        assert res == 8
-        res = self.interp_operations(f, [13])
-        assert res == 72
-
-    def test_instantiate_does_not_call(self):
-        mydriver = JitDriver(reds = ['n', 'x'], greens = [])
-        class Base: pass
-        class A(Base): foo = 72
-        class B(Base): foo = 8
-
-        def f(n):
-            x = 0
-            while n > 0:
-                mydriver.can_enter_jit(n=n, x=x)
-                mydriver.jit_merge_point(n=n, x=x)
-                if n % 2 == 0:
-                    cls = A
-                else:
-                    cls = B
-                inst = cls()
-                x += inst.foo
-                n -= 1
-            return x
-        res = self.meta_interp(f, [20], enable_opts='')
-        assert res == f(20)
-        self.check_loops(call=0)
-
-    def test_zerodivisionerror(self):
-        # test the case of exception-raising operation that is not delegated
-        # to the backend at all: ZeroDivisionError
-        #
-        def f(n):
-            assert n >= 0
-            try:
-                return ovfcheck(5 % n)
-            except ZeroDivisionError:
-                return -666
-            except OverflowError:
-                return -777
-        res = self.interp_operations(f, [0])
-        assert res == -666
-        #
-        def f(n):
-            assert n >= 0
-            try:
-                return ovfcheck(6 // n)
-            except ZeroDivisionError:
-                return -667
-            except OverflowError:
-                return -778
-        res = self.interp_operations(f, [0])
-        assert res == -667
-
-    def test_div_overflow(self):
-        import sys
-        from pypy.rpython.lltypesystem.lloperation import llop
-        myjitdriver = JitDriver(greens = [], reds = ['x', 'y', 'res'])
-        def f(x, y):
-            res = 0
-            while y > 0:
-                myjitdriver.can_enter_jit(x=x, y=y, res=res)
-                myjitdriver.jit_merge_point(x=x, y=y, res=res)
-                try:
-                    res += llop.int_floordiv_ovf(lltype.Signed,
-                                                 -sys.maxint-1, x)
-                    x += 5
-                except OverflowError:
-                    res += 100
-                y -= 1
-            return res
-        res = self.meta_interp(f, [-41, 16])
-        assert res == ((-sys.maxint-1) // (-41) +
-                       (-sys.maxint-1) // (-36) +
-                       (-sys.maxint-1) // (-31) +
-                       (-sys.maxint-1) // (-26) +
-                       (-sys.maxint-1) // (-21) +
-                       (-sys.maxint-1) // (-16) +
-                       (-sys.maxint-1) // (-11) +
-                       (-sys.maxint-1) // (-6) +
-                       100 * 8)
-
-    def test_isinstance(self):
-        class A:
-            pass
-        class B(A):
-            pass
-        def fn(n):
-            if n:
-                obj = A()
-            else:
-                obj = B()
-            return isinstance(obj, B)
-        res = self.interp_operations(fn, [0])
-        assert res
-        self.check_operations_history(guard_class=1)
-        res = self.interp_operations(fn, [1])
-        assert not res
-
-    def test_isinstance_2(self):
-        driver = JitDriver(greens = [], reds = ['n', 'sum', 'x'])
-        class A:
-            pass
-        class B(A):
-            pass
-        class C(B):
-            pass
-
-        def main():
-            return f(5, B()) * 10 + f(5, C()) + f(5, A()) * 100
-
-        def f(n, x):
-            sum = 0
-            while n > 0:
-                driver.can_enter_jit(x=x, n=n, sum=sum)
-                driver.jit_merge_point(x=x, n=n, sum=sum)
-                if isinstance(x, B):
-                    sum += 1
-                n -= 1
-            return sum
-
-        res = self.meta_interp(main, [])
-        assert res == 55
-
-    def test_assert_isinstance(self):
-        class A:
-            pass
-        class B(A):
-            pass
-        def fn(n):
-            # this should only be called with n != 0
-            if n:
-                obj = B()
-                obj.a = n
-            else:
-                obj = A()
-                obj.a = 17
-            assert isinstance(obj, B)
-            return obj.a
-        res = self.interp_operations(fn, [1])
-        assert res == 1
-        self.check_operations_history(guard_class=0)
-        if self.type_system == 'ootype':
-            self.check_operations_history(instanceof=0)
-
-    def test_r_dict(self):
-        from pypy.rlib.objectmodel import r_dict
-        class FooError(Exception):
-            pass
-        def myeq(n, m):
-            return n == m
-        def myhash(n):
-            if n < 0:
-                raise FooError
-            return -n
-        def f(n):
-            d = r_dict(myeq, myhash)
-            for i in range(10):
-                d[i] = i*i
-            try:
-                return d[n]
-            except FooError:
-                return 99
-        res = self.interp_operations(f, [5])
-        assert res == f(5)
-
-    def test_free_object(self):
-        import weakref
-        from pypy.rlib import rgc
-        from pypy.rpython.lltypesystem.lloperation import llop
-        myjitdriver = JitDriver(greens = [], reds = ['n', 'x'])
-        class X(object):
-            pass
-        def main(n, x):
-            while n > 0:
-                myjitdriver.can_enter_jit(n=n, x=x)
-                myjitdriver.jit_merge_point(n=n, x=x)
-                n -= x.foo
-        def g(n):
-            x = X()
-            x.foo = 2
-            main(n, x)
-            x.foo = 5
-            return weakref.ref(x)
-        def f(n):
-            r = g(n)
-            rgc.collect(); rgc.collect(); rgc.collect()
-            return r() is None
-        #
-        assert f(30) == 1
-        res = self.meta_interp(f, [30], no_stats=True)
-        assert res == 1
-
-    def test_pass_around(self):
-        myjitdriver = JitDriver(greens = [], reds = ['n', 'x'])
-
-        def call():
-            pass
-
-        def f(n, x):
-            while n > 0:
-                myjitdriver.can_enter_jit(n=n, x=x)
-                myjitdriver.jit_merge_point(n=n, x=x)
-                if n % 2:
-                    call()
-                    if n == 8:
-                        return x
-                    x = 3
-                else:
-                    x = 5
-                n -= 1
-            return 0
-
-        self.meta_interp(f, [40, 0])
-
-    def test_const_inputargs(self):
-        myjitdriver = JitDriver(greens = ['m'], reds = ['n', 'x'])
-        def f(n, x):
-            m = 0x7FFFFFFF
-            while n > 0:
-                myjitdriver.can_enter_jit(m=m, n=n, x=x)
-                myjitdriver.jit_merge_point(m=m, n=n, x=x)
-                x = 42
-                n -= 1
-                m = m >> 1
-            return x
-
-        res = self.meta_interp(f, [50, 1], enable_opts='')
-        assert res == 42
-
-    def test_set_param(self):
-        myjitdriver = JitDriver(greens = [], reds = ['n', 'x'])
-        def g(n):
-            x = 0
-            while n > 0:
-                myjitdriver.can_enter_jit(n=n, x=x)
-                myjitdriver.jit_merge_point(n=n, x=x)
-                n -= 1
-                x += n
-            return x
-        def f(n, threshold):
-            myjitdriver.set_param('threshold', threshold)
-            return g(n)
-
-        res = self.meta_interp(f, [10, 3])
-        assert res == 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + 0
-        self.check_tree_loop_count(2)
-
-        res = self.meta_interp(f, [10, 13])
-        assert res == 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + 0
-        self.check_tree_loop_count(0)
-
-    def test_dont_look_inside(self):
-        @dont_look_inside
-        def g(a, b):
-            return a + b
-        def f(a, b):
-            return g(a, b)
-        res = self.interp_operations(f, [3, 5])
-        assert res == 8
-        self.check_operations_history(int_add=0, call=1)
-
-    def test_listcomp(self):
-        myjitdriver = JitDriver(greens = [], reds = ['x', 'y', 'lst'])
-        def f(x, y):
-            lst = [0, 0, 0]
-            while y > 0:
-                myjitdriver.can_enter_jit(x=x, y=y, lst=lst)
-                myjitdriver.jit_merge_point(x=x, y=y, lst=lst)
-                lst = [i+x for i in lst if i >=0]
-                y -= 1
-            return lst[0]
-        res = self.meta_interp(f, [6, 7], listcomp=True, backendopt=True, listops=True)
-        # XXX: the loop looks inefficient
-        assert res == 42
-
-    def test_tuple_immutable(self):
-        def new(a, b):
-            return a, b
-        def f(a, b):
-            tup = new(a, b)
-            return tup[1]
-        res = self.interp_operations(f, [3, 5])
-        assert res == 5
-        self.check_operations_history(setfield_gc=2, getfield_gc_pure=1)
-
-    def test_oosend_look_inside_only_one(self):
-        class A:
-            pass
-        class B(A):
-            def g(self):
-                return 123
-        class C(A):
-            @dont_look_inside
-            def g(self):
-                return 456
-        def f(n):
-            if n > 3:
-                x = B()
-            else:
-                x = C()
-            return x.g() + x.g()
-        res = self.interp_operations(f, [10])
-        assert res == 123 * 2
-        res = self.interp_operations(f, [-10])
-        assert res == 456 * 2
-
-    def test_residual_external_call(self):
-        import math
-        myjitdriver = JitDriver(greens = [], reds = ['y', 'x', 'res'])
-        def f(x, y):
-            x = float(x)
-            res = 0.0
-            while y > 0:
-                myjitdriver.can_enter_jit(x=x, y=y, res=res)
-                myjitdriver.jit_merge_point(x=x, y=y, res=res)
-                # this is an external call that the default policy ignores
-                rpart, ipart = math.modf(x)
-                res += ipart
-                y -= 1
-            return res
-        res = self.meta_interp(f, [6, 7])
-        assert res == 42
-        self.check_loop_count(1)
-        self.check_loops(call=1)
-
-    def test_merge_guardclass_guardvalue(self):
-        from pypy.rlib.objectmodel import instantiate
-        myjitdriver = JitDriver(greens = [], reds = ['x', 'l'])
-
-        class A(object):
-            def g(self, x):
-                return x - 5
-        class B(A):
-            def g(self, y):
-                return y - 3
-
-        a1 = A()
-        a2 = A()
-        b = B()
-        def f(x):
-            l = [a1] * 100 + [a2] * 100 + [b] * 100
-            while x > 0:
-                myjitdriver.can_enter_jit(x=x, l=l)
-                myjitdriver.jit_merge_point(x=x, l=l)
-                a = l[x]
-                x = a.g(x)
-                hint(a, promote=True)
-            return x
-        res = self.meta_interp(f, [299], listops=True)
-        assert res == f(299)
-        self.check_loops(guard_class=0, guard_value=2)        
-        self.check_loops(guard_class=0, guard_value=5, everywhere=True)
-
-    def test_merge_guardnonnull_guardclass(self):
-        from pypy.rlib.objectmodel import instantiate
-        myjitdriver = JitDriver(greens = [], reds = ['x', 'l'])
-
-        class A(object):
-            def g(self, x):
-                return x - 3
-        class B(A):
-            def g(self, y):
-                return y - 5
-
-        a1 = A()
-        b1 = B()
-        def f(x):
-            l = [None] * 100 + [b1] * 100 + [a1] * 100
-            while x > 0:
-                myjitdriver.can_enter_jit(x=x, l=l)
-                myjitdriver.jit_merge_point(x=x, l=l)
-                a = l[x]
-                if a:
-                    x = a.g(x)
-                else:
-                    x -= 7
-            return x
-        res = self.meta_interp(f, [299], listops=True)
-        assert res == f(299)
-        self.check_loops(guard_class=0, guard_nonnull=0,
-                         guard_nonnull_class=2, guard_isnull=0)
-        self.check_loops(guard_class=0, guard_nonnull=0,
-                         guard_nonnull_class=4, guard_isnull=1,
-                         everywhere=True)
-
-    def test_merge_guardnonnull_guardvalue(self):
-        from pypy.rlib.objectmodel import instantiate
-        myjitdriver = JitDriver(greens = [], reds = ['x', 'l'])
-
-        class A(object):
-            pass
-        class B(A):
-            pass
-
-        a1 = A()
-        b1 = B()
-        def f(x):
-            l = [b1] * 100 + [None] * 100 + [a1] * 100
-            while x > 0:
-                myjitdriver.can_enter_jit(x=x, l=l)
-                myjitdriver.jit_merge_point(x=x, l=l)
-                a = l[x]
-                if a:
-                    x -= 5
-                else:
-                    x -= 7
-                hint(a, promote=True)
-            return x
-        res = self.meta_interp(f, [299], listops=True)
-        assert res == f(299)
-        self.check_loops(guard_class=0, guard_nonnull=0, guard_value=1,
-                         guard_nonnull_class=0, guard_isnull=1)
-        self.check_loops(guard_class=0, guard_nonnull=0, guard_value=3,
-                         guard_nonnull_class=0, guard_isnull=2,
-                         everywhere=True)
-
-    def test_merge_guardnonnull_guardvalue_2(self):
-        from pypy.rlib.objectmodel import instantiate
-        myjitdriver = JitDriver(greens = [], reds = ['x', 'l'])
-
-        class A(object):
-            pass
-        class B(A):
-            pass
-
-        a1 = A()
-        b1 = B()
-        def f(x):
-            l = [None] * 100 + [b1] * 100 + [a1] * 100
-            while x > 0:
-                myjitdriver.can_enter_jit(x=x, l=l)
-                myjitdriver.jit_merge_point(x=x, l=l)
-                a = l[x]
-                if a:
-                    x -= 5
-                else:
-                    x -= 7
-                hint(a, promote=True)
-            return x
-        res = self.meta_interp(f, [299], listops=True)
-        assert res == f(299)
-        self.check_loops(guard_class=0, guard_nonnull=0, guard_value=2,
-                         guard_nonnull_class=0, guard_isnull=0)
-        self.check_loops(guard_class=0, guard_nonnull=0, guard_value=4,
-                         guard_nonnull_class=0, guard_isnull=1,
-                         everywhere=True)
-
-    def test_merge_guardnonnull_guardclass_guardvalue(self):
-        from pypy.rlib.objectmodel import instantiate
-        myjitdriver = JitDriver(greens = [], reds = ['x', 'l'])
-
-        class A(object):
-            def g(self, x):
-                return x - 3
-        class B(A):
-            def g(self, y):
-                return y - 5
-
-        a1 = A()
-        a2 = A()
-        b1 = B()
-        def f(x):
-            l = [a2] * 100 + [None] * 100 + [b1] * 100 + [a1] * 100
-            while x > 0:
-                myjitdriver.can_enter_jit(x=x, l=l)
-                myjitdriver.jit_merge_point(x=x, l=l)
-                a = l[x]
-                if a:
-                    x = a.g(x)
-                else:
-                    x -= 7
-                hint(a, promote=True)
-            return x
-        res = self.meta_interp(f, [399], listops=True)
-        assert res == f(399)
-        self.check_loops(guard_class=0, guard_nonnull=0, guard_value=2,
-                         guard_nonnull_class=0, guard_isnull=0)
-        self.check_loops(guard_class=0, guard_nonnull=0, guard_value=5,
-                         guard_nonnull_class=0, guard_isnull=1,
-                         everywhere=True)
-
-    def test_residual_call_doesnt_lose_info(self):
-        myjitdriver = JitDriver(greens = [], reds = ['x', 'y', 'l'])
-
-        class A(object):
-            pass
-
-        globall = [""]
-        @dont_look_inside
-        def g(x):
-            globall[0] = str(x)
-            return x
-
-        def f(x):
-            y = A()
-            y.v = x
-            l = [0]
-            while y.v > 0:
-                myjitdriver.can_enter_jit(x=x, y=y, l=l)
-                myjitdriver.jit_merge_point(x=x, y=y, l=l)
-                l[0] = y.v
-                lc = l[0]
-                y.v = g(y.v) - y.v/y.v + lc/l[0] - 1
-            return y.v
-        res = self.meta_interp(f, [20], listops=True)
-        self.check_loops(getfield_gc=0, getarrayitem_gc=0)
-        self.check_loops(getfield_gc=1, getarrayitem_gc=0, everywhere=True)
-
-    def test_guard_isnull_nonnull(self):
-        myjitdriver = JitDriver(greens = [], reds = ['x', 'res'])
-        class A(object):
-            pass
-
-        @dont_look_inside
-        def create(x):
-            if x >= -40:
-                return A()
-            return None
-
-        def f(x):
-            res = 0
-            while x > 0:
-                myjitdriver.can_enter_jit(x=x, res=res)
-                myjitdriver.jit_merge_point(x=x, res=res)
-                obj = create(x-1)
-                if obj is not None:
-                    res += 1
-                obj2 = create(x-1000)
-                if obj2 is None:
-                    res += 1
-                x -= 1
-            return res
-        res = self.meta_interp(f, [21])
-        assert res == 42
-        self.check_loops(guard_nonnull=1, guard_isnull=1)
-
-    def test_loop_invariant1(self):
-        myjitdriver = JitDriver(greens = [], reds = ['x', 'res'])
-        class A(object):
-            pass
-        a = A()
-        a.current_a = A()
-        a.current_a.x = 1
-        @loop_invariant
-        def f():
-            return a.current_a
-
-        def g(x):
-            res = 0
-            while x > 0:
-                myjitdriver.can_enter_jit(x=x, res=res)
-                myjitdriver.jit_merge_point(x=x, res=res)
-                res += f().x
-                res += f().x
-                res += f().x
-                x -= 1
-            a.current_a = A()
-            a.current_a.x = 2
-            return res
-        res = self.meta_interp(g, [21])
-        assert res == 3 * 21
-        self.check_loops(call=0)
-        self.check_loops(call=1, everywhere=True)
-
-    def test_bug_optimizeopt_mutates_ops(self):
-        myjitdriver = JitDriver(greens = [], reds = ['x', 'res', 'const', 'a'])
-        class A(object):
-            pass
-        class B(A):
-            pass
-
-        glob = A()
-        glob.a = None
-        def f(x):
-            res = 0
-            a = A()
-            a.x = 0
-            glob.a = A()
-            const = 2
-            while x > 0:
-                myjitdriver.can_enter_jit(x=x, res=res, a=a, const=const)
-                myjitdriver.jit_merge_point(x=x, res=res, a=a, const=const)
-                if type(glob.a) is B:
-                    res += 1
-                if a is None:
-                    a = A()
-                    a.x = x
-                    glob.a = B()
-                    const = 2
-                else:
-                    const = hint(const, promote=True)
-                    x -= const
-                    res += a.x
-                    a = None
-                    glob.a = A()
-                    const = 1
-            return res
-        res = self.meta_interp(f, [21])
-        assert res == f(21)
-
-    def test_getitem_indexerror(self):
-        lst = [10, 4, 9, 16]
-        def f(n):
-            try:
-                return lst[n]
-            except IndexError:
-                return -2
-        res = self.interp_operations(f, [2])
-        assert res == 9
-        res = self.interp_operations(f, [4])
-        assert res == -2
-        res = self.interp_operations(f, [-4])
-        assert res == 10
-        res = self.interp_operations(f, [-5])
-        assert res == -2
-
-    def test_guard_always_changing_value(self):
-        myjitdriver = JitDriver(greens = [], reds = ['x'])
-        class A:
-            pass
-        def f(x):
-            while x > 0:
-                myjitdriver.can_enter_jit(x=x)
-                myjitdriver.jit_merge_point(x=x)
-                a = A()
-                hint(a, promote=True)
-                x -= 1
-        self.meta_interp(f, [50])
-        self.check_loop_count(1)
-        # this checks that the logic triggered by make_a_counter_per_value()
-        # works and prevents generating tons of bridges
-
-    def test_swap_values(self):
-        def f(x, y):
-            if x > 5:
-                x, y = y, x
-            return x - y
-        res = self.interp_operations(f, [10, 2])
-        assert res == -8
-        res = self.interp_operations(f, [3, 2])
-        assert res == 1
-
-    def test_raw_malloc_and_access(self):
-        from pypy.rpython.lltypesystem import rffi
-        
-        TP = rffi.CArray(lltype.Signed)
-        
-        def f(n):
-            a = lltype.malloc(TP, n, flavor='raw')
-            a[0] = n
-            res = a[0]
-            lltype.free(a, flavor='raw')
-            return res
-
-        res = self.interp_operations(f, [10])
-        assert res == 10
-
-    def test_raw_malloc_and_access_float(self):
-        from pypy.rpython.lltypesystem import rffi
-        
-        TP = rffi.CArray(lltype.Float)
-        
-        def f(n, f):
-            a = lltype.malloc(TP, n, flavor='raw')
-            a[0] = f
-            res = a[0]
-            lltype.free(a, flavor='raw')
-            return res
-
-        res = self.interp_operations(f, [10, 3.5])
-        assert res == 3.5
-
-    def test_jit_debug(self):
-        myjitdriver = JitDriver(greens = [], reds = ['x'])
-        class A:
-            pass
-        def f(x):
-            while x > 0:
-                myjitdriver.can_enter_jit(x=x)
-                myjitdriver.jit_merge_point(x=x)
-                jit_debug("hi there:", x)
-                jit_debug("foobar")
-                x -= 1
-            return x
-        res = self.meta_interp(f, [8])
-        assert res == 0
-        self.check_loops(jit_debug=2)
-
-    def test_assert_green(self):
-        def f(x, promote):
-            if promote:
-                x = hint(x, promote=True)
-            assert_green(x)
-            return x
-        res = self.interp_operations(f, [8, 1])
-        assert res == 8
-        py.test.raises(AssertGreenFailed, self.interp_operations, f, [8, 0])
-
-    def test_multiple_specialied_versions1(self):
-        myjitdriver = JitDriver(greens = [], reds = ['y', 'x', 'res'])
-        class Base:
-            def __init__(self, val):
-                self.val = val
-        class A(Base):
-            def binop(self, other):
-                return A(self.val + other.val)
-        class B(Base):
-            def binop(self, other):
-                return B(self.val * other.val)
-        def f(x, y):
-            res = x
-            while y > 0:
-                myjitdriver.can_enter_jit(y=y, x=x, res=res)
-                myjitdriver.jit_merge_point(y=y, x=x, res=res)
-                res = res.binop(x)
-                y -= 1
-            return res
-        def g(x, y):
-            a1 = f(A(x), y)
-            a2 = f(A(x), y)
-            b1 = f(B(x), y)
-            b2 = f(B(x), y)
-            assert a1.val == a2.val
-            assert b1.val == b2.val
-            return a1.val + b1.val
-        res = self.meta_interp(g, [6, 7])
-        assert res == 6*8 + 6**8
-        self.check_loop_count(5)
-        self.check_loops({'guard_true': 2,
-                          'int_add': 1, 'int_mul': 1, 'int_sub': 2,
-                          'int_gt': 2, 'jump': 2})
-
-    def test_multiple_specialied_versions_array(self):
-        myjitdriver = JitDriver(greens = [], reds = ['idx', 'y', 'x', 'res',
-                                                     'array'])
-        class Base:
-            def __init__(self, val):
-                self.val = val
-        class A(Base):
-            def binop(self, other):
-                return A(self.val + other.val)
-        class B(Base):
-            def binop(self, other):
-                return B(self.val - other.val)
-        def f(x, y):
-            res = x
-            array = [1, 2, 3]
-            array[1] = 7
-            idx = 0
-            while y > 0:
-                myjitdriver.can_enter_jit(idx=idx, y=y, x=x, res=res,
-                                          array=array)
-                myjitdriver.jit_merge_point(idx=idx, y=y, x=x, res=res,
-                                            array=array)
-                res = res.binop(x)
-                res.val += array[idx] + array[1]
-                if y < 7:
-                    idx = 2
-                y -= 1
-            return res
-        def g(x, y):
-            a1 = f(A(x), y)
-            a2 = f(A(x), y)
-            b1 = f(B(x), y)
-            b2 = f(B(x), y)
-            assert a1.val == a2.val
-            assert b1.val == b2.val
-            return a1.val + b1.val
-        res = self.meta_interp(g, [6, 14])
-        assert res == g(6, 14)
-        self.check_loop_count(9)
-        self.check_loops(getarrayitem_gc=6, everywhere=True)
-
-    def test_multiple_specialied_versions_bridge(self):
-        myjitdriver = JitDriver(greens = [], reds = ['y', 'x', 'z', 'res'])
-        class Base:
-            def __init__(self, val):
-                self.val = val
-            def getval(self):
-                return self.val
-        class A(Base):
-            def binop(self, other):
-                return A(self.getval() + other.getval())
-        class B(Base):
-            def binop(self, other):
-                return B(self.getval() * other.getval())
-        def f(x, y, z):
-            res = x
-            while y > 0:
-                myjitdriver.can_enter_jit(y=y, x=x, z=z, res=res)
-                myjitdriver.jit_merge_point(y=y, x=x, z=z, res=res)
-                res = res.binop(x)
-                y -= 1
-                if y < 7:
-                    x = z
-            return res
-        def g(x, y):
-            a1 = f(A(x), y, A(x))
-            a2 = f(A(x), y, A(x))
-            assert a1.val == a2.val
-            b1 = f(B(x), y, B(x))
-            b2 = f(B(x), y, B(x))
-            assert b1.val == b2.val
-            c1 = f(B(x), y, A(x))
-            c2 = f(B(x), y, A(x))
-            assert c1.val == c2.val
-            d1 = f(A(x), y, B(x))
-            d2 = f(A(x), y, B(x))
-            assert d1.val == d2.val
-            return a1.val + b1.val + c1.val + d1.val
-        res = self.meta_interp(g, [3, 14])
-        assert res == g(3, 14)
-
-    def test_failing_inlined_guard(self):
-        myjitdriver = JitDriver(greens = [], reds = ['y', 'x', 'z', 'res'])
-        class Base:
-            def __init__(self, val):
-                self.val = val
-            def getval(self):
-                return self.val
-        class A(Base):
-            def binop(self, other):
-                return A(self.getval() + other.getval())
-        class B(Base):
-            def binop(self, other):
-                return B(self.getval() * other.getval())
-        def f(x, y, z):
-            res = x
-            while y > 0:
-                myjitdriver.can_enter_jit(y=y, x=x, z=z, res=res)
-                myjitdriver.jit_merge_point(y=y, x=x, z=z, res=res)
-                res = res.binop(x)
-                y -= 1
-                if y < 8:
-                    x = z
-            return res
-        def g(x, y):
-            c1 = f(A(x), y, B(x))
-            c2 = f(A(x), y, B(x))
-            assert c1.val == c2.val
-            return c1.val
-        res = self.meta_interp(g, [3, 16])
-        assert res == g(3, 16)
-
-    def test_inlined_guard_in_short_preamble(self):
-        myjitdriver = JitDriver(greens = [], reds = ['y', 'x', 'z', 'res'])
-        class A:
-            def __init__(self, val):
-                self.val = val
-            def getval(self):
-                return self.val
-            def binop(self, other):
-                return A(self.getval() + other.getval())
-        def f(x, y, z):
-            res = x
-            while y > 0:
-                myjitdriver.can_enter_jit(y=y, x=x, z=z, res=res)
-                myjitdriver.jit_merge_point(y=y, x=x, z=z, res=res)
-                res = res.binop(x)
-                y -= 1
-                if y < 7:
-                    x = z
-            return res
-        def g(x, y):
-            a1 = f(A(x), y, A(x))
-            a2 = f(A(x), y, A(x))
-            assert a1.val == a2.val
-            return a1.val
-        res = self.meta_interp(g, [3, 14])
-        assert res == g(3, 14)
-
-    def test_specialied_bridge(self):
-        myjitdriver = JitDriver(greens = [], reds = ['y', 'x', 'res'])
-        class A:
-            def __init__(self, val):
-                self.val = val
-            def binop(self, other):
-                return A(self.val + other.val)
-        def f(x, y):
-            res = A(0)
-            while y > 0:
-                myjitdriver.can_enter_jit(y=y, x=x, res=res)
-                myjitdriver.jit_merge_point(y=y, x=x, res=res)
-                res = res.binop(A(y))
-                if y<7:
-                    res = x
-                y -= 1
-            return res
-        def g(x, y):
-            a1 = f(A(x), y)
-            a2 = f(A(x), y)
-            assert a1.val == a2.val
-            return a1.val
-        res = self.meta_interp(g, [6, 14])
-        assert res == g(6, 14)
-
-    def test_specialied_bridge_const(self):
-        myjitdriver = JitDriver(greens = [], reds = ['y', 'const', 'x', 'res'])
-        class A:
-            def __init__(self, val):
-                self.val = val
-            def binop(self, other):
-                return A(self.val + other.val)
-        def f(x, y):
-            res = A(0)
-            const = 7
-            while y > 0:
-                myjitdriver.can_enter_jit(y=y, x=x, res=res, const=const)
-                myjitdriver.jit_merge_point(y=y, x=x, res=res, const=const)
-                const = hint(const, promote=True)
-                res = res.binop(A(const))
-                if y<7:
-                    res = x
-                y -= 1
-            return res
-        def g(x, y):
-            a1 = f(A(x), y)
-            a2 = f(A(x), y)
-            assert a1.val == a2.val
-            return a1.val
-        res = self.meta_interp(g, [6, 14])
-        assert res == g(6, 14)
-
-    def test_multiple_specialied_zigzag(self):
-        myjitdriver = JitDriver(greens = [], reds = ['y', 'x', 'res'])
-        class Base:
-            def __init__(self, val):
-                self.val = val
-        class A(Base):
-            def binop(self, other):
-                return A(self.val + other.val)
-            def switch(self):
-                return B(self.val)
-        class B(Base):
-            def binop(self, other):
-                return B(self.val * other.val)
-            def switch(self):
-                return A(self.val)
-        def f(x, y):
-            res = x
-            while y > 0:
-                myjitdriver.can_enter_jit(y=y, x=x, res=res)
-                myjitdriver.jit_merge_point(y=y, x=x, res=res)
-                if y % 4 == 0:
-                    res = res.switch()
-                res = res.binop(x)
-                y -= 1
-            return res
-        def g(x, y):
-            a1 = f(A(x), y)
-            a2 = f(A(x), y)
-            b1 = f(B(x), y)
-            b2 = f(B(x), y)
-            assert a1.val == a2.val
-            assert b1.val == b2.val
-            return a1.val + b1.val
-        res = self.meta_interp(g, [3, 23])
-        assert res == 7068153
-        self.check_loop_count(6)
-        self.check_loops(guard_true=4, guard_class=0, int_add=2, int_mul=2,
-                         guard_false=2)
-
-    def test_dont_trace_every_iteration(self):
-        myjitdriver = JitDriver(greens = [], reds = ['a', 'b', 'i', 'sa'])
-        
-        def main(a, b):
-            i = sa = 0
-            #while i < 200:
-            while i < 200:
-                myjitdriver.can_enter_jit(a=a, b=b, i=i, sa=sa)
-                myjitdriver.jit_merge_point(a=a, b=b, i=i, sa=sa)
-                if a > 0: pass
-                if b < 2: pass
-                sa += a % b
-                i += 1
-            return sa
-        def g():
-            return main(10, 20) + main(-10, -20)
-        res = self.meta_interp(g, [])
-        assert res == g()
-        self.check_enter_count(2)
-
-    def test_current_trace_length(self):
-        myjitdriver = JitDriver(greens = ['g'], reds = ['x'])
-        @dont_look_inside
-        def residual():
-            print "hi there"
-        @unroll_safe
-        def loop(g):
-            y = 0
-            while y < g:
-                residual()
-                y += 1
-        def f(x, g):
-            n = 0
-            while x > 0:
-                myjitdriver.can_enter_jit(x=x, g=g)
-                myjitdriver.jit_merge_point(x=x, g=g)
-                loop(g)
-                x -= 1
-                n = current_trace_length()
-            return n
-        res = self.meta_interp(f, [5, 8])
-        assert 14 < res < 42
-        res = self.meta_interp(f, [5, 2])
-        assert 4 < res < 14
-
-    def test_compute_identity_hash(self):
-        from pypy.rlib.objectmodel import compute_identity_hash
-        class A(object):
-            pass
-        def f():
-            a = A()
-            return compute_identity_hash(a) == compute_identity_hash(a)
-        res = self.interp_operations(f, [])
-        assert res
-        # a "did not crash" kind of test
-
-    def test_compute_unique_id(self):
-        from pypy.rlib.objectmodel import compute_unique_id
-        class A(object):
-            pass
-        def f():
-            a1 = A()
-            a2 = A()
-            return (compute_unique_id(a1) == compute_unique_id(a1) and
-                    compute_unique_id(a1) != compute_unique_id(a2))
-        res = self.interp_operations(f, [])
-        assert res
-
-    def test_wrap_around_add(self):
-        myjitdriver = JitDriver(greens = [], reds = ['x', 'n'])
-        class A:
-            pass
-        def f(x):
-            n = 0
-            while x > 0:
-                myjitdriver.can_enter_jit(x=x, n=n)
-                myjitdriver.jit_merge_point(x=x, n=n)
-                x += 1
-                n += 1
-            return n
-        res = self.meta_interp(f, [sys.maxint-10])
-        assert res == 11
-        self.check_tree_loop_count(2)
-
-    def test_wrap_around_mul(self):
-        myjitdriver = JitDriver(greens = [], reds = ['x', 'n'])
-        class A:
-            pass
-        def f(x):
-            n = 0
-            while x > 0:
-                myjitdriver.can_enter_jit(x=x, n=n)
-                myjitdriver.jit_merge_point(x=x, n=n)
-                x *= 2
-                n += 1
-            return n
-        res = self.meta_interp(f, [sys.maxint>>10])
-        assert res == 11
-        self.check_tree_loop_count(2)        
-
-    def test_wrap_around_sub(self):
-        myjitdriver = JitDriver(greens = [], reds = ['x', 'n'])
-        class A:
-            pass
-        def f(x):
-            n = 0
-            while x < 0:
-                myjitdriver.can_enter_jit(x=x, n=n)
-                myjitdriver.jit_merge_point(x=x, n=n)
-                x -= 1
-                n += 1
-            return n
-        res = self.meta_interp(f, [10-sys.maxint])
-        assert res == 12
-        self.check_tree_loop_count(2)        
-
-
-
-class TestOOtype(BasicTests, OOJitMixin):
-
-    def test_oohash(self):
-        def f(n):
-            s = ootype.oostring(n, -1)
-            return s.ll_hash()
-        res = self.interp_operations(f, [5])
-        assert res == ootype.oostring(5, -1).ll_hash()
-
-    def test_identityhash(self):
-        A = ootype.Instance("A", ootype.ROOT)
-        def f():
-            obj1 = ootype.new(A)
-            obj2 = ootype.new(A)
-            return ootype.identityhash(obj1) == ootype.identityhash(obj2)
-        assert not f()
-        res = self.interp_operations(f, [])
-        assert not res
-
-    def test_oois(self):
-        A = ootype.Instance("A", ootype.ROOT)
-        def f(n):
-            obj1 = ootype.new(A)
-            if n:
-                obj2 = obj1
-            else:
-                obj2 = ootype.new(A)
-            return obj1 is obj2
-        res = self.interp_operations(f, [0])
-        assert not res
-        res = self.interp_operations(f, [1])
-        assert res
-
-    def test_oostring_instance(self):
-        A = ootype.Instance("A", ootype.ROOT)
-        B = ootype.Instance("B", ootype.ROOT)
-        def f(n):
-            obj1 = ootype.new(A)
-            obj2 = ootype.new(B)
-            s1 = ootype.oostring(obj1, -1)
-            s2 = ootype.oostring(obj2, -1)
-            ch1 = s1.ll_stritem_nonneg(1)
-            ch2 = s2.ll_stritem_nonneg(1)
-            return ord(ch1) + ord(ch2)
-        res = self.interp_operations(f, [0])
-        assert res == ord('A') + ord('B')
-
-    def test_subclassof(self):
-        A = ootype.Instance("A", ootype.ROOT)
-        B = ootype.Instance("B", A)
-        clsA = ootype.runtimeClass(A)
-        clsB = ootype.runtimeClass(B)
-        myjitdriver = JitDriver(greens = [], reds = ['n', 'flag', 'res'])
-
-        def getcls(flag):
-            if flag:
-                return clsA
-            else:
-                return clsB
-
-        def f(flag, n):
-            res = True
-            while n > -100:
-                myjitdriver.can_enter_jit(n=n, flag=flag, res=res)
-                myjitdriver.jit_merge_point(n=n, flag=flag, res=res)
-                cls = getcls(flag)
-                n -= 1
-                res = ootype.subclassof(cls, clsB)
-            return res
-
-        res = self.meta_interp(f, [1, 100],
-                               policy=StopAtXPolicy(getcls),
-                               enable_opts='')
-        assert not res
-        
-        res = self.meta_interp(f, [0, 100],
-                               policy=StopAtXPolicy(getcls),
-                               enable_opts='')
-        assert res
-
-class BaseLLtypeTests(BasicTests):
-
-    def test_identityhash(self):
-        A = lltype.GcStruct("A")
-        def f():
-            obj1 = lltype.malloc(A)
-            obj2 = lltype.malloc(A)
-            return lltype.identityhash(obj1) == lltype.identityhash(obj2)
-        assert not f()
-        res = self.interp_operations(f, [])
-        assert not res
-
-    def test_oops_on_nongc(self):
-        from pypy.rpython.lltypesystem import lltype
-        
-        TP = lltype.Struct('x')
-        def f(i1, i2):
-            p1 = prebuilt[i1]
-            p2 = prebuilt[i2]
-            a = p1 is p2
-            b = p1 is not p2
-            c = bool(p1)
-            d = not bool(p2)
-            return 1000*a + 100*b + 10*c + d
-        prebuilt = [lltype.malloc(TP, flavor='raw', immortal=True)] * 2
-        expected = f(0, 1)
-        assert self.interp_operations(f, [0, 1]) == expected
-
-    def test_casts(self):
-        py.test.skip("xxx fix or kill")
-        if not self.basic:
-            py.test.skip("test written in a style that "
-                         "means it's frontend only")
-        from pypy.rpython.lltypesystem import lltype, llmemory, rffi
-
-        TP = lltype.GcStruct('S1')
-        def f(p):
-            n = lltype.cast_ptr_to_int(p)
-            return n
-        x = lltype.malloc(TP)
-        xref = lltype.cast_opaque_ptr(llmemory.GCREF, x)
-        res = self.interp_operations(f, [xref])
-        y = llmemory.cast_ptr_to_adr(x)
-        y = llmemory.cast_adr_to_int(y)
-        assert rffi.get_real_int(res) == rffi.get_real_int(y)
-        #
-        TP = lltype.Struct('S2')
-        prebuilt = [lltype.malloc(TP, immortal=True),
-                    lltype.malloc(TP, immortal=True)]
-        def f(x):
-            p = prebuilt[x]
-            n = lltype.cast_ptr_to_int(p)
-            return n
-        res = self.interp_operations(f, [1])
-        y = llmemory.cast_ptr_to_adr(prebuilt[1])
-        y = llmemory.cast_adr_to_int(y)
-        assert rffi.get_real_int(res) == rffi.get_real_int(y)
-
-    def test_collapsing_ptr_eq(self):
-        S = lltype.GcStruct('S')
-        p = lltype.malloc(S)
-        driver = JitDriver(greens = [], reds = ['n', 'x'])
-
-        def f(n, x):
-            while n > 0:
-                driver.can_enter_jit(n=n, x=x)
-                driver.jit_merge_point(n=n, x=x)
-                if x:
-                    n -= 1
-                n -= 1
-
-        def main():
-            f(10, p)
-            f(10, lltype.nullptr(S))
-
-        self.meta_interp(main, [])
-
-    def test_enable_opts(self):
-        jitdriver = JitDriver(greens = [], reds = ['a'])
-
-        class A(object):
-            def __init__(self, i):
-                self.i = i
-
-        def f():
-            a = A(0)
-            
-            while a.i < 10:
-                jitdriver.jit_merge_point(a=a)
-                jitdriver.can_enter_jit(a=a)
-                a = A(a.i + 1)
-
-        self.meta_interp(f, [])
-        self.check_loops(new_with_vtable=0)
-        self.meta_interp(f, [], enable_opts='')
-        self.check_loops(new_with_vtable=1)
-
-class TestLLtype(BaseLLtypeTests, LLJitMixin):
-    pass

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

diff --git a/lib_pypy/pypy_test/test_os_wait3.py b/lib_pypy/pypy_test/test_os_wait3.py
deleted file mode 100644
--- a/lib_pypy/pypy_test/test_os_wait3.py
+++ /dev/null
@@ -1,19 +0,0 @@
-import os
-
-if hasattr(os, 'wait3'):
-    def test_os_wait3():
-        exit_status = 0x33
-
-        if not hasattr(os, "fork"):
-            skip("Need fork() to test wait3()")
-
-        child = os.fork()
-        if child == 0: # in child
-            os._exit(exit_status)
-        else:
-            pid, status, rusage = os.wait3(0)
-            assert child == pid
-            assert os.WIFEXITED(status)
-            assert os.WEXITSTATUS(status) == exit_status
-            assert isinstance(rusage.ru_utime, float)
-            assert isinstance(rusage.ru_maxrss, int)

diff --git a/pypy/translator/c/database.py b/pypy/translator/c/database.py
--- a/pypy/translator/c/database.py
+++ b/pypy/translator/c/database.py
@@ -1,7 +1,7 @@
-from pypy.rpython.lltypesystem.lltype import \
-     Primitive, Ptr, typeOf, RuntimeTypeInfo, \
-     Struct, Array, FuncType, PyObject, Void, \
-     ContainerType, OpaqueType, FixedSizeArray, _uninitialized
+
+from pypy.rpython.lltypesystem.lltype import (
+    Primitive, Ptr, typeOf, RuntimeTypeInfo, Struct, Array, FuncType, PyObject,
+    Void, ContainerType, OpaqueType, FixedSizeArray, _uninitialized, Typedef)
 from pypy.rpython.lltypesystem import lltype, rffi
 from pypy.rpython.lltypesystem.llmemory import WeakRef, _WeakRefType, GCREF
 from pypy.rpython.lltypesystem.rffi import CConstant
@@ -100,6 +100,8 @@
     def gettype(self, T, varlength=1, who_asks=None, argnames=[]):
         if isinstance(T, Primitive) or T == GCREF:
             return PrimitiveType[T]
+        elif isinstance(T, Typedef):
+            return '%s @' % T.c_name
         elif isinstance(T, Ptr):
             if (isinstance(T.TO, OpaqueType) and
                 T.TO.hints.get('c_pointer_typedef') is not None):

diff --git a/pypy/rpython/lltypesystem/module/ll_math.py b/pypy/rpython/lltypesystem/module/ll_math.py
--- a/pypy/rpython/lltypesystem/module/ll_math.py
+++ b/pypy/rpython/lltypesystem/module/ll_math.py
@@ -20,8 +20,7 @@
         separate_module_files=[cdir.join('src', 'll_math.c')],
         export_symbols=['_pypy_math_acosh', '_pypy_math_asinh',
                         '_pypy_math_atanh',
-                        '_pypy_math_expm1', '_pypy_math_log1p',
-                        '_pypy_math_isinf', '_pypy_math_isnan'],
+                        '_pypy_math_expm1', '_pypy_math_log1p'],
         )
     math_prefix = '_pypy_math_'
 else:
@@ -58,7 +57,6 @@
 math_hypot = llexternal(underscore + 'hypot',
                         [rffi.DOUBLE, rffi.DOUBLE], rffi.DOUBLE)
 math_isinf = math_llexternal('isinf', [rffi.DOUBLE], rffi.INT)
-math_isnan = math_llexternal('isnan', [rffi.DOUBLE], rffi.INT)
 
 # ____________________________________________________________
 #
@@ -91,13 +89,14 @@
 #
 # Custom implementations
 
- at jit.purefunction
 def ll_math_isnan(y):
-    return bool(math_isnan(y))
+    # By not calling into the extenal function the JIT can inline this.  Floats
+    # are awesome.
+    return y != y
 
- at jit.purefunction
 def ll_math_isinf(y):
-    return bool(math_isinf(y))
+    # Use a bitwise OR so the JIT doesn't produce 2 different guards.
+    return (y == INFINITY) | (y == -INFINITY)
 
 
 ll_math_copysign = math_copysign

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

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

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

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

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

diff --git a/pypy/module/cpyext/__init__.py b/pypy/module/cpyext/__init__.py
--- a/pypy/module/cpyext/__init__.py
+++ b/pypy/module/cpyext/__init__.py
@@ -46,6 +46,7 @@
 import pypy.module.cpyext.complexobject
 import pypy.module.cpyext.weakrefobject
 import pypy.module.cpyext.funcobject
+import pypy.module.cpyext.frameobject
 import pypy.module.cpyext.classobject
 import pypy.module.cpyext.pypyintf
 import pypy.module.cpyext.memoryobject

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

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

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


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

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

diff --git a/pypy/rpython/lltypesystem/rffi.py b/pypy/rpython/lltypesystem/rffi.py
--- a/pypy/rpython/lltypesystem/rffi.py
+++ b/pypy/rpython/lltypesystem/rffi.py
@@ -746,6 +746,7 @@
     def charpsize2str(cp, size):
         l = [cp[i] for i in range(size)]
         return emptystr.join(l)
+    charpsize2str._annenforceargs_ = [None, int]
 
     return (str2charp, free_charp, charp2str,
             get_nonmovingbuffer, free_nonmovingbuffer,
@@ -817,6 +818,8 @@
     """Similar to llmemory.sizeof() but tries hard to return a integer
     instead of a symbolic value.
     """
+    if isinstance(tp, lltype.Typedef):
+        tp = tp.OF
     if isinstance(tp, lltype.FixedSizeArray):
         return sizeof(tp.OF) * tp.length
     if isinstance(tp, lltype.Struct):

diff --git a/pypy/module/cpyext/include/Python.h b/pypy/module/cpyext/include/Python.h
--- a/pypy/module/cpyext/include/Python.h
+++ b/pypy/module/cpyext/include/Python.h
@@ -110,6 +110,8 @@
 #include "intobject.h"
 #include "listobject.h"
 #include "unicodeobject.h"
+#include "compile.h"
+#include "frameobject.h"
 #include "eval.h"
 #include "pymem.h"
 #include "pycobject.h"

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

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

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

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

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

diff --git a/pypy/module/imp/test/test_app.py b/pypy/module/imp/test/test_app.py
--- a/pypy/module/imp/test/test_app.py
+++ b/pypy/module/imp/test/test_app.py
@@ -35,7 +35,8 @@
 
     def test_load_dynamic(self):
         raises(ImportError, self.imp.load_dynamic, 'foo', 'bar')
-        raises(ImportError, self.imp.load_dynamic, 'foo', 'bar', 'baz.so')
+        raises(ImportError, self.imp.load_dynamic, 'foo', 'bar',
+               open(self.file_module))
 
     def test_suffixes(self):
         for suffix, mode, type in self.imp.get_suffixes():

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

diff --git a/pypy/module/cpyext/test/test_pystate.py b/pypy/module/cpyext/test/test_pystate.py
--- a/pypy/module/cpyext/test/test_pystate.py
+++ b/pypy/module/cpyext/test/test_pystate.py
@@ -29,20 +29,14 @@
         state = api.PyInterpreterState_Head()
         assert nullptr(PyInterpreterState.TO) == api.PyInterpreterState_Next(state)
 
-def clear_threadstate(space):
-    # XXX: this should collect the ThreadState memory
-    del space.getexecutioncontext().cpyext_threadstate
-
 class TestThreadState(BaseApiTest):
     def test_thread_state_get(self, space, api):
         ts = api.PyThreadState_Get()
         assert ts != nullptr(PyThreadState.TO)
-        clear_threadstate(space)
 
     def test_thread_state_interp(self, space, api):
         ts = api.PyThreadState_Get()
         assert ts.c_interp == api.PyInterpreterState_Head()
-        clear_threadstate(space)
 
     def test_basic_threadstate_dance(self, space, api):
         # Let extension modules call these functions,
@@ -54,5 +48,3 @@
 
         api.PyEval_AcquireThread(tstate)
         api.PyEval_ReleaseThread(tstate)
-
-        clear_threadstate(space)

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
@@ -91,9 +91,10 @@
 else:
     # XXX that's slow
     def case_ok(filename):
-        index1 = filename.rfind(os.sep)
-        index2 = filename.rfind(os.altsep)
-        index = max(index1, index2)
+        index = filename.rfind(os.sep)
+        if os.altsep is not None:
+            index2 = filename.rfind(os.altsep)
+            index = max(index, index2)
         if index < 0:
             directory = os.curdir
         else:

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


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

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

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


diff --git a/pypy/jit/backend/llsupport/descr.py b/pypy/jit/backend/llsupport/descr.py
--- a/pypy/jit/backend/llsupport/descr.py
+++ b/pypy/jit/backend/llsupport/descr.py
@@ -43,9 +43,14 @@
 
 class SizeDescr(AbstractDescr):
     size = 0      # help translation
+    is_immutable = False
 
-    def __init__(self, size):
+    def __init__(self, size, count_fields_if_immut=-1):
         self.size = size
+        self.count_fields_if_immut = count_fields_if_immut
+
+    def count_fields_if_immutable(self):
+        return self.count_fields_if_immut
 
     def repr_of_descr(self):
         return '<SizeDescr %s>' % self.size
@@ -62,15 +67,15 @@
         return cache[STRUCT]
     except KeyError:
         size = symbolic.get_size(STRUCT, gccache.translate_support_code)
+        count_fields_if_immut = heaptracker.count_fields_if_immutable(STRUCT)
         if heaptracker.has_gcstruct_a_vtable(STRUCT):
-            sizedescr = SizeDescrWithVTable(size)
+            sizedescr = SizeDescrWithVTable(size, count_fields_if_immut)
         else:
-            sizedescr = SizeDescr(size)
+            sizedescr = SizeDescr(size, count_fields_if_immut)
         gccache.init_size_descr(STRUCT, sizedescr)
         cache[STRUCT] = sizedescr
         return sizedescr
 
-
 # ____________________________________________________________
 # FieldDescrs
 

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

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

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

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

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

diff --git a/pypy/rpython/lltypesystem/test/test_lltype.py b/pypy/rpython/lltypesystem/test/test_lltype.py
--- a/pypy/rpython/lltypesystem/test/test_lltype.py
+++ b/pypy/rpython/lltypesystem/test/test_lltype.py
@@ -804,6 +804,21 @@
                  hints={'immutable_fields': FieldListAccessor({'x':'[*]'})})
     assert S._immutable_field('x') == '[*]'
 
+def test_typedef():
+    T = Typedef(Signed, 'T')
+    assert T == Signed
+    assert Signed == T
+    T2 = Typedef(T, 'T2')
+    assert T2 == T
+    assert T2.OF is Signed
+    py.test.raises(TypeError, Ptr, T)
+    assert rffi.CArrayPtr(T) == rffi.CArrayPtr(Signed)
+    assert rffi.CArrayPtr(Signed) == rffi.CArrayPtr(T)
+
+    F = FuncType((T,), T)
+    assert F.RESULT == Signed
+    assert F.ARGS == (Signed,)
+
 
 class TestTrackAllocation:
     def test_automatic_tracking(self):

diff --git a/pypy/module/pypyjit/test_pypy_c/model.py b/pypy/module/pypyjit/test_pypy_c/model.py
--- a/pypy/module/pypyjit/test_pypy_c/model.py
+++ b/pypy/module/pypyjit/test_pypy_c/model.py
@@ -153,10 +153,10 @@
                 for op in self._ops_for_chunk(chunk, include_debug_merge_points):
                     yield op
 
-    def match(self, expected_src):
+    def match(self, expected_src, **kwds):
         ops = list(self.allops())
         matcher = OpMatcher(ops, src=self.format_ops())
-        return matcher.match(expected_src)
+        return matcher.match(expected_src, **kwds)
 
     def match_by_id(self, id, expected_src, **kwds):
         ops = list(self.ops_by_id(id, **kwds))
@@ -250,7 +250,6 @@
         # this is the ticker check generated in PyFrame.handle_operation_error
         exc_ticker_check = """
             ticker2 = getfield_raw(ticker_address, descr=<SignedFieldDescr pypysig_long_struct.c_value .*>)
-            setfield_gc(_, _, descr=<GcPtrFieldDescr pypy.interpreter.pyframe.PyFrame.inst_w_f_trace .*>)
             ticker_cond1 = int_lt(ticker2, 0)
             guard_false(ticker_cond1, descr=...)
         """
@@ -266,7 +265,7 @@
         if exp_v2 == '_':
             return True
         if self.is_const(v1) or self.is_const(exp_v2):
-            return v1 == exp_v2
+            return v1[:-1].startswith(exp_v2[:-1])
         if v1 not in self.alpha_map:
             self.alpha_map[v1] = exp_v2
         return self.alpha_map[v1] == exp_v2
@@ -315,7 +314,7 @@
                 # it matched! The '...' operator ends here
                 return op
 
-    def match_loop(self, expected_ops):
+    def match_loop(self, expected_ops, ignore_ops):
         """
         A note about partial matching: the '...' operator is non-greedy,
         i.e. it matches all the operations until it finds one that matches
@@ -334,13 +333,16 @@
                     return
                 op = self.match_until(exp_op, iter_ops)
             else:
-                op = self._next_op(iter_ops)
+                while True:
+                    op = self._next_op(iter_ops)
+                    if op.name not in ignore_ops:
+                        break
             self.match_op(op, exp_op)
         #
         # make sure we exhausted iter_ops
         self._next_op(iter_ops, assert_raises=True)
 
-    def match(self, expected_src):
+    def match(self, expected_src, ignore_ops=[]):
         def format(src):
             if src is None:
                 return ''
@@ -349,7 +351,7 @@
         expected_src = self.preprocess_expected_src(expected_src)
         expected_ops = self.parse_ops(expected_src)
         try:
-            self.match_loop(expected_ops)
+            self.match_loop(expected_ops, ignore_ops)
         except InvalidMatch, e:
             #raise # uncomment this and use py.test --pdb for better debugging
             print '@' * 40
@@ -358,6 +360,7 @@
             print e.args
             print e.msg
             print
+            print "Ignore ops:", ignore_ops
             print "Got:"
             print format(self.src)
             print

diff --git a/pypy/translator/c/test/test_database.py b/pypy/translator/c/test/test_database.py
--- a/pypy/translator/c/test/test_database.py
+++ b/pypy/translator/c/test/test_database.py
@@ -5,7 +5,7 @@
 from pypy.objspace.flow.model import Constant, Variable, SpaceOperation
 from pypy.objspace.flow.model import Block, Link, FunctionGraph
 from pypy.rpython.typesystem import getfunctionptr
-from pypy.rpython.lltypesystem.rffi import VOIDP, INT_real, INT
+from pypy.rpython.lltypesystem.rffi import VOIDP, INT_real, INT, CArrayPtr
 
 
 def dump_on_stdout(database):
@@ -244,3 +244,15 @@
     db.get(p)
     db.complete()
     dump_on_stdout(db)
+
+def test_typedef():
+    A = Typedef(Signed, 'test4')
+    db = LowLevelDatabase()
+    assert db.gettype(A) == "test4 @"
+
+    PA = CArrayPtr(A)
+    assert db.gettype(PA) == "test4 *@"
+
+    F = FuncType((A,), A)
+    assert db.gettype(F) == "test4 (@)(test4)"
+

diff --git a/pypy/jit/backend/llsupport/regalloc.py b/pypy/jit/backend/llsupport/regalloc.py
--- a/pypy/jit/backend/llsupport/regalloc.py
+++ b/pypy/jit/backend/llsupport/regalloc.py
@@ -1,5 +1,5 @@
 
-from pypy.jit.metainterp.history import Const, Box
+from pypy.jit.metainterp.history import Const, Box, REF
 from pypy.rlib.objectmodel import we_are_translated
 
 class TempBox(Box):
@@ -313,11 +313,12 @@
             self.assembler.regalloc_mov(reg, to)
         # otherwise it's clean
 
-    def before_call(self, force_store=[], save_all_regs=False):
+    def before_call(self, force_store=[], save_all_regs=0):
         """ Spill registers before a call, as described by
         'self.save_around_call_regs'.  Registers are not spilled if
         they don't survive past the current operation, unless they
-        are listed in 'force_store'.
+        are listed in 'force_store'.  'save_all_regs' can be 0 (default),
+        1 (save all), or 2 (save default+PTRs).
         """
         for v, reg in self.reg_bindings.items():
             if v not in force_store and self.longevity[v][1] <= self.position:
@@ -325,9 +326,11 @@
                 del self.reg_bindings[v]
                 self.free_regs.append(reg)
                 continue
-            if not save_all_regs and reg not in self.save_around_call_regs:
-                # we don't have to
-                continue
+            if save_all_regs != 1 and reg not in self.save_around_call_regs:
+                if save_all_regs == 0:
+                    continue    # we don't have to
+                if v.type != REF:
+                    continue    # only save GC pointers
             self._sync_var(v)
             del self.reg_bindings[v]
             self.free_regs.append(reg)


diff --git a/pypy/module/pypyjit/test/test_pypy_c.py b/pypy/module/pypyjit/test/test_pypy_c.py
--- a/pypy/module/pypyjit/test/test_pypy_c.py
+++ b/pypy/module/pypyjit/test/test_pypy_c.py
@@ -3,6 +3,7 @@
 import py
 from py.test import skip
 import sys, os, re
+import subprocess
 
 class BytecodeTrace(list):
     def get_opnames(self, prefix=""):
@@ -116,13 +117,12 @@
         print >> f, "print 'OK :-)'"
         f.close()
 
-        if sys.platform.startswith('win'):
-            py.test.skip("XXX this is not Windows-friendly")
         print logfilepath
-        child_stdout = os.popen('PYPYLOG=":%s" "%s" "%s"' % (
-            logfilepath, self.pypy_c, filepath), 'r')
-        result = child_stdout.read()
-        child_stdout.close()
+        env = os.environ.copy()
+        env['PYPYLOG'] = ":%s" % (logfilepath,)
+        p = subprocess.Popen([self.pypy_c, str(filepath)],
+                             env=env, stdout=subprocess.PIPE)
+        result, _ = p.communicate()
         assert result
         if result.strip().startswith('SKIP:'):
             py.test.skip(result.strip())
@@ -198,44 +198,6 @@
         print
         print '@' * 79
 
-    def test_f1(self):
-        self.run_source('''
-            def main(n):
-                "Arbitrary test function."
-                i = 0
-                x = 1
-                while i<n:
-                    j = 0   #ZERO
-                    while j<=i:
-                        j = j + 1
-                        x = x + (i&j)
-                    i = i + 1
-                return x
-        ''', 220,
-                   ([2117], 1083876708))
-
-    def test_factorial(self):
-        self.run_source('''
-            def main(n):
-                r = 1
-                while n > 1:
-                    r *= n
-                    n -= 1
-                return r
-        ''', 28,
-                   ([5], 120),
-                    ([25], 15511210043330985984000000L))
-
-    def test_factorialrec(self):
-        self.run_source('''
-            def main(n):
-                if n > 1:
-                    return n * main(n-1)
-                else:
-                    return 1
-        ''', 0,
-                   ([5], 120),
-                    ([25], 15511210043330985984000000L))
 
     def test_richards(self):
         self.run_source('''
@@ -247,529 +209,6 @@
         ''' % (sys.path,), 7200,
                    ([], 42))
 
-    def test_simple_call(self):
-        self.run_source('''
-            OFFSET = 0
-            def f(i):
-                return i + 1 + OFFSET
-            def main(n):
-                i = 0
-                while i < n+OFFSET:
-                    i = f(f(i))
-                return i
-        ''', 98,
-                   ([20], 20),
-                    ([31], 32))
-        ops = self.get_by_bytecode("LOAD_GLOBAL", True)
-        assert len(ops) == 5
-        assert ops[0].get_opnames() == ["guard_value",
-                                        "getfield_gc", "guard_value",
-                                        "getfield_gc", "guard_isnull",
-                                        "getfield_gc", "guard_nonnull_class"]
-        # the second getfield on the same globals is quicker
-        assert ops[1].get_opnames() == ["getfield_gc", "guard_nonnull_class"]
-        assert not ops[2] # second LOAD_GLOBAL of the same name folded away
-        # LOAD_GLOBAL of the same name but in different function partially
-        # folded away
-        # XXX could be improved
-        assert ops[3].get_opnames() == ["guard_value",
-                                        "getfield_gc", "guard_isnull"]
-        assert not ops[4]
-        ops = self.get_by_bytecode("CALL_FUNCTION", True)
-        assert len(ops) == 2
-        for i, bytecode in enumerate(ops):
-            if i == 0:
-                assert "call(getexecutioncontext)" in str(bytecode)
-            else:
-                assert not bytecode.get_opnames("call")
-            assert not bytecode.get_opnames("new")
-            assert len(bytecode.get_opnames("guard")) <= 10
-
-        ops = self.get_by_bytecode("LOAD_GLOBAL")
-        assert len(ops) == 5
-        for bytecode in ops:
-            assert not bytecode
-
-        ops = self.get_by_bytecode("CALL_FUNCTION")
-        assert len(ops) == 2
-        for bytecode in ops:
-            assert len(bytecode) <= 1
-        
-
-    def test_method_call(self):
-        self.run_source('''
-            class A(object):
-                def __init__(self, a):
-                    self.a = a
-                def f(self, i):
-                    return self.a + i
-            def main(n):
-                i = 0
-                a = A(1)
-                while i < n:
-                    x = a.f(i)
-                    i = a.f(x)
-                return i
-        ''', 93,
-                   ([20], 20),
-                    ([31], 32))
-        ops = self.get_by_bytecode("LOOKUP_METHOD", True)
-        assert len(ops) == 2
-        assert not ops[0].get_opnames("call")
-        assert not ops[0].get_opnames("new")
-        assert len(ops[0].get_opnames("guard")) <= 3
-        assert not ops[1] # second LOOKUP_METHOD folded away
-
-        ops = self.get_by_bytecode("LOOKUP_METHOD")
-        assert not ops[0] # first LOOKUP_METHOD folded away
-        assert not ops[1] # second LOOKUP_METHOD folded away
-
-        ops = self.get_by_bytecode("CALL_METHOD", True)
-        assert len(ops) == 2
-        for i, bytecode in enumerate(ops):
-            if i == 0:
-                assert "call(getexecutioncontext)" in str(bytecode)
-            else:
-                assert not bytecode.get_opnames("call")
-            assert not bytecode.get_opnames("new")
-            assert len(bytecode.get_opnames("guard")) <= 6
-        assert len(ops[1]) < len(ops[0])
-
-        ops = self.get_by_bytecode("CALL_METHOD")
-        assert len(ops) == 2
-        assert len(ops[0]) <= 1
-        assert len(ops[1]) <= 1
-        
-        ops = self.get_by_bytecode("LOAD_ATTR", True)
-        assert len(ops) == 2
-        # With mapdict, we get fast access to (so far) the 5 first
-        # attributes, which means it is done with only the following
-        # operations.  (For the other attributes there is additionally
-        # a getarrayitem_gc.)
-        assert ops[0].get_opnames() == ["getfield_gc",
-                                        "guard_nonnull_class"]
-        assert not ops[1] # second LOAD_ATTR folded away
-
-        ops = self.get_by_bytecode("LOAD_ATTR")
-        assert not ops[0] # first LOAD_ATTR folded away
-        assert not ops[1] # second LOAD_ATTR folded away
-
-    def test_static_classmethod_call(self):
-        self.run_source('''
-            class A(object):
-                @classmethod
-                def f(cls, i):
-                    return i + (cls is A) + 1
-
-                @staticmethod
-                def g(i):
-                    return i - 1
-
-            def main(n):
-                i = 0
-                a = A()
-                while i < n:
-                    x = a.f(i)
-                    i = a.g(x)
-                return i
-        ''', 106,
-                   ([20], 20),
-                   ([31], 31))
-        ops = self.get_by_bytecode("LOOKUP_METHOD")
-        assert len(ops) == 2
-        assert not ops[0].get_opnames("call")
-        assert not ops[0].get_opnames("new")
-        assert len(ops[0].get_opnames("guard")) <= 2
-        assert len(ops[0].get_opnames("getfield")) <= 4
-        assert not ops[1] # second LOOKUP_METHOD folded away
-
-    def test_default_and_kw(self):
-        self.run_source('''
-            def f(i, j=1):
-                return i + j
-            def main(n):
-                i = 0
-                while i < n:
-                    i = f(f(i), j=1)
-                return i
-        ''', 100,
-                   ([20], 20),
-                   ([31], 32))
-        ops = self.get_by_bytecode("CALL_FUNCTION")
-        assert len(ops) == 2
-        for i, bytecode in enumerate(ops):
-            assert not bytecode.get_opnames("call")
-            assert not bytecode.get_opnames("new")
-        assert len(ops[0].get_opnames("guard")) <= 14
-        assert len(ops[1].get_opnames("guard")) <= 3
-
-        ops = self.get_by_bytecode("CALL_FUNCTION", True)
-        assert len(ops) == 2
-        for i, bytecode in enumerate(ops):
-            if i == 0:
-                assert "call(getexecutioncontext)" in str(bytecode)
-            else:
-                assert not bytecode.get_opnames("call")
-            assert not bytecode.get_opnames("new")
-        assert len(ops[0].get_opnames("guard")) <= 14
-        assert len(ops[1].get_opnames("guard")) <= 3
-
-    def test_kwargs(self):
-        self.run_source('''
-            d = {}
-
-            def g(**args):
-                return len(args)
-
-            def main(x):
-                s = 0
-                d = {}
-                for i in range(x):
-                    s += g(**d)
-                    d[str(i)] = i
-                    if i % 100 == 99:
-                        d = {}
-                return s
-        ''', 100000, ([100], 4950),
-                    ([1000], 49500),
-                    ([10000], 495000),
-                    ([100000], 4950000))
-        assert len(self.rawloops)  + len(self.rawentrybridges) == 4
-        op, = self.get_by_bytecode("CALL_FUNCTION_KW")
-        # XXX a bit too many guards, but better than before
-        assert len(op.get_opnames("guard")) <= 12
-
-    def test_stararg_virtual(self):
-        self.run_source('''
-            d = {}
-
-            def g(*args):
-                return len(args)
-            def h(a, b, c):
-                return c
-
-            def main(x):
-                s = 0
-                for i in range(x):
-                    l = [i, x, 2]
-                    s += g(*l)
-                    s += h(*l)
-                    s += g(i, x, 2)
-                for i in range(x):
-                    l = [x, 2]
-                    s += g(i, *l)
-                    s += h(i, *l)
-                return s
-        ''', 100000, ([100], 1300),
-                    ([1000], 13000),
-                    ([10000], 130000),
-                    ([100000], 1300000))
-        assert len(self.loops) == 2
-        ops = self.get_by_bytecode("CALL_FUNCTION_VAR")
-        assert len(ops) == 4
-        for op in ops:
-            assert len(op.get_opnames("new")) == 0
-            assert len(op.get_opnames("call_may_force")) == 0
-
-        ops = self.get_by_bytecode("CALL_FUNCTION")
-        for op in ops:
-            assert len(op.get_opnames("new")) == 0
-            assert len(op.get_opnames("call_may_force")) == 0
-
-    def test_stararg(self):
-        self.run_source('''
-            d = {}
-
-            def g(*args):
-                return args[-1]
-            def h(*args):
-                return len(args)
-
-            def main(x):
-                s = 0
-                l = []
-                i = 0
-                while i < x:
-                    l.append(1)
-                    s += g(*l)
-                    i = h(*l)
-                return s
-        ''', 100000, ([100], 100),
-                     ([1000], 1000),
-                     ([2000], 2000),
-                     ([4000], 4000))
-        assert len(self.loops) == 1
-        ops = self.get_by_bytecode("CALL_FUNCTION_VAR")
-        for op in ops:
-            assert len(op.get_opnames("new_with_vtable")) == 0
-            assert len(op.get_opnames("call_may_force")) == 0
-
-    def test_virtual_instance(self):
-        self.run_source('''
-            class A(object):
-                pass
-            def main(n):
-                i = 0
-                while i < n:
-                    a = A()
-                    assert isinstance(a, A)
-                    assert not isinstance(a, int)
-                    a.x = 2
-                    i = i + a.x
-                return i
-        ''', 69,
-                   ([20], 20),
-                   ([31], 32))
-
-        callA, callisinstance1, callisinstance2 = (
-                self.get_by_bytecode("CALL_FUNCTION"))
-        assert not callA.get_opnames("call")
-        assert not callA.get_opnames("new")
-        assert len(callA.get_opnames("guard")) <= 2
-        assert not callisinstance1.get_opnames("call")
-        assert not callisinstance1.get_opnames("new")
-        assert len(callisinstance1.get_opnames("guard")) <= 2
-        # calling isinstance on a builtin type gives zero guards
-        # because the version_tag of a builtin type is immutable
-        assert not len(callisinstance1.get_opnames("guard"))
-
-
-        bytecode, = self.get_by_bytecode("STORE_ATTR")
-        assert bytecode.get_opnames() == []
-
-    def test_load_attr(self):
-        self.run_source('''
-            class A(object):
-                pass
-            a = A()
-            a.x = 2
-            def main(n):
-                i = 0
-                while i < n:
-                    i = i + a.x
-                return i
-        ''', 41,
-                   ([20], 20),
-                   ([31], 32))
-
-        load, = self.get_by_bytecode("LOAD_ATTR")
-        # 1 guard_value for the class
-        # 1 guard_value for the version_tag
-        # 1 guard_value for the structure
-        # 1 guard_nonnull_class for the result since it is used later
-        assert len(load.get_opnames("guard")) <= 4
-
-    def test_mixed_type_loop(self):
-        self.run_source('''
-            class A(object):
-                pass
-            def main(n):
-                i = 0.0
-                j = 2
-                while i < n:
-                    i = j + i
-                return i, type(i) is float
-        ''', 35,
-                   ([20], (20, True)),
-                   ([31], (32, True)))
-
-        bytecode, = self.get_by_bytecode("BINARY_ADD")
-        assert not bytecode.get_opnames("call")
-        assert not bytecode.get_opnames("new")
-        assert len(bytecode.get_opnames("guard")) <= 2
-
-    def test_call_builtin_function(self):
-        self.run_source('''
-            class A(object):
-                pass
-            def main(n):
-                i = 2
-                l = []
-                while i < n:
-                    i += 1
-                    l.append(i)
-                return i, len(l)
-        ''', 39,
-                   ([20], (20, 18)),
-                   ([31], (31, 29)))
-
-        bytecode, = self.get_by_bytecode("CALL_METHOD")
-        assert len(bytecode.get_opnames("new_with_vtable")) == 1 # the forcing of the int
-        assert len(bytecode.get_opnames("call")) == 1 # the call to append
-        assert len(bytecode.get_opnames("guard")) == 1 # guard for guard_no_exception after the call
-        bytecode, = self.get_by_bytecode("CALL_METHOD", True)
-        assert len(bytecode.get_opnames("guard")) == 2 # guard for profiling disabledness + guard_no_exception after the call
-
-    def test_range_iter(self):
-        self.run_source('''
-            def g(n):
-                return range(n)
-
-            def main(n):
-                s = 0
-                for i in range(n):
-                    s += g(n)[i]
-                return s
-        ''', 143, ([1000], 1000 * 999 / 2))
-        bytecode, = self.get_by_bytecode("BINARY_SUBSCR", True)
-        assert bytecode.get_opnames("guard") == [
-            "guard_false",   # check that the index is >= 0
-            "guard_false",   # check that the index is lower than the current length
-            ]
-        bytecode, _ = self.get_by_bytecode("FOR_ITER", True) # second bytecode is the end of the loop
-        assert bytecode.get_opnames("guard") == [
-            "guard_value",
-            "guard_class",   # check the class of the iterator
-            "guard_nonnull", # check that the iterator is not finished
-            "guard_isnull",  # check that the range list is not forced
-            "guard_false",   # check that the index is lower than the current length
-            ]
-
-        bytecode, = self.get_by_bytecode("BINARY_SUBSCR")
-        assert bytecode.get_opnames("guard") == [
-            "guard_false",   # check that the index is >= 0
-            "guard_false",   # check that the index is lower than the current length
-            ]
-        bytecode, _ = self.get_by_bytecode("FOR_ITER") # second bytecode is the end of the loop
-        assert bytecode.get_opnames("guard") == [
-            "guard_false",   # check that the index is lower than the current length
-            ]
-
-    def test_exception_inside_loop_1(self):
-        self.run_source('''
-            def main(n):
-                while n:
-                    try:
-                        raise ValueError
-                    except ValueError:
-                        pass
-                    n -= 1
-                return n
-        ''', 33,
-                  ([30], 0))
-
-        bytecode, = self.get_by_bytecode("SETUP_EXCEPT")
-        #assert not bytecode.get_opnames("new")   -- currently, we have
-        #               new_with_vtable(pypy.interpreter.pyopcode.ExceptBlock)
-        bytecode, = self.get_by_bytecode("RAISE_VARARGS")
-        assert not bytecode.get_opnames("new")
-        bytecode, = self.get_by_bytecode("COMPARE_OP")
-        assert not bytecode.get_opnames()
-
-    def test_exception_inside_loop_2(self):
-        self.run_source('''
-            def g(n):
-                raise ValueError(n)
-            def f(n):
-                g(n)
-            def main(n):
-                while n:
-                    try:
-                        f(n)
-                    except ValueError:
-                        pass
-                    n -= 1
-                return n
-        ''', 51,
-                  ([30], 0))
-
-        bytecode, = self.get_by_bytecode("RAISE_VARARGS")
-        assert not bytecode.get_opnames("new")
-        bytecode, = self.get_by_bytecode("COMPARE_OP")
-        assert len(bytecode.get_opnames()) <= 2    # oois, guard_true
-
-    def test_chain_of_guards(self):
-        self.run_source('''
-        class A(object):
-            def method_x(self):
-                return 3
-
-        l = ["x", "y"]
-
-        def main(arg):
-            sum = 0
-            a = A()
-            i = 0
-            while i < 2000:
-                name = l[arg]
-                sum += getattr(a, 'method_' + name)()
-                i += 1
-            return sum
-        ''', 3000, ([0], 2000*3))
-        assert len(self.loops) == 1
-
-    def test_getattr_with_dynamic_attribute(self):
-        self.run_source('''
-        class A(object):
-            pass
-
-        l = ["x", "y"]
-
-        def main(arg):
-            sum = 0
-            a = A()
-            a.a1 = 0
-            a.a2 = 0
-            a.a3 = 0
-            a.a4 = 0
-            a.a5 = 0 # workaround, because the first five attributes need a promotion
-            a.x = 1
-            a.y = 2
-            i = 0
-            while i < 2000:
-                name = l[i % 2]
-                sum += getattr(a, name)
-                i += 1
-            return sum
-        ''', 3000, ([0], 3000))
-        assert len(self.loops) == 1
-
-    def test_blockstack_virtualizable(self):
-        self.run_source('''
-        from pypyjit import residual_call
-
-        def main():
-            i = 0
-            while i < 100:
-                try:
-                    residual_call(len, [])
-                except:
-                    pass
-                i += 1
-            return i
-        ''', 1000, ([], 100))
-        bytecode, = self.get_by_bytecode("CALL_FUNCTION")
-        # we allocate virtual ref and frame, we don't want block
-        assert len(bytecode.get_opnames('new_with_vtable')) == 2
-
-    def test_import_in_function(self):
-        self.run_source('''
-        def main():
-            i = 0
-            while i < 100:
-                from sys import version
-                i += 1
-            return i
-        ''', 100, ([], 100))
-        bytecode, = self.get_by_bytecode('IMPORT_NAME')
-        bytecode2, = self.get_by_bytecode('IMPORT_FROM')
-        assert len(bytecode.get_opnames('call')) == 2 # split_chr and list_pop
-        assert len(bytecode2.get_opnames('call')) == 0
-
-    def test_arraycopy_disappears(self):
-        self.run_source('''
-        def main():
-            i = 0
-            while i < 100:
-                t = (1, 2, 3, i + 1)
-                t2 = t[:]
-                del t
-                i = t2[3]
-                del t2
-            return i
-        ''', 40, ([], 100))
-        bytecode, = self.get_by_bytecode('BINARY_SUBSCR')
-        assert len(bytecode.get_opnames('new_array')) == 0
 
     def test_overflow_checking(self):
         startvalue = sys.maxint - 2147483647
@@ -784,514 +223,6 @@
             return total
         ''' % startvalue, 170, ([], startvalue + 4999450000L))
 
-    def test_boolrewrite_invers(self):
-        for a, b, res, ops in (('2000', '2000', 20001000, 51),
-                               ( '500',  '500', 15001500, 81),
-                               ( '300',  '600', 16001700, 83),
-                               (   'a',    'b', 16001700, 89),
-                               (   'a',    'a', 13001700, 85)):
-
-            self.run_source('''
-            def main():
-                sa = 0
-                a = 300
-                b = 600
-                for i in range(1000):
-                    if i < %s: sa += 1
-                    else: sa += 2
-                    if i >= %s: sa += 10000
-                    else: sa += 20000
-                return sa
-            '''%(a, b), ops, ([], res))
-
-    def test_boolrewrite_reflex(self):
-        for a, b, res, ops in (('2000', '2000', 10001000, 51),
-                               ( '500',  '500', 15001500, 81),
-                               ( '300',  '600', 14001700, 83),
-                               (   'a',    'b', 14001700, 89),
-                               (   'a',    'a', 17001700, 85)):
-
-            self.run_source('''
-            def main():
-                sa = 0
-                a = 300
-                b = 600
-                for i in range(1000):
-                    if i < %s: sa += 1
-                    else: sa += 2
-                    if %s > i: sa += 10000
-                    else: sa += 20000
-                return sa
-            '''%(a, b), ops, ([], res))
-
-
-    def test_boolrewrite_correct_invers(self):
-        def opval(i, op, a):
-            if eval('%d %s %d' % (i, op, a)): return 1
-            return 2
-
-        ops = ('<', '>', '<=', '>=', '==', '!=')        
-        for op1 in ops:
-            for op2 in ops:
-                for a,b in ((500, 500), (300, 600)):
-                    res = 0
-                    res += opval(a-1, op1, a) * (a)
-                    res += opval(  a, op1, a) 
-                    res += opval(a+1, op1, a) * (1000 - a - 1)
-                    res += opval(b-1, op2, b) * 10000 * (b)
-                    res += opval(  b, op2, b) * 10000 
-                    res += opval(b+1, op2, b) * 10000 * (1000 - b - 1)
-
-                    self.run_source('''
-                    def main():
-                        sa = 0
-                        for i in range(1000):
-                            if i %s %d: sa += 1
-                            else: sa += 2
-                            if i %s %d: sa += 10000
-                            else: sa += 20000
-                        return sa
-                    '''%(op1, a, op2, b), 83, ([], res))
-
-                    self.run_source('''
-                    def main():
-                        sa = 0
-                        i = 0.0
-                        while i < 250.0:
-                            if i %s %f: sa += 1
-                            else: sa += 2
-                            if i %s %f: sa += 10000
-                            else: sa += 20000
-                            i += 0.25
-                        return sa
-                    '''%(op1, float(a)/4.0, op2, float(b)/4.0), 156, ([], res))
-                    
-
-    def test_boolrewrite_correct_reflex(self):
-        def opval(i, op, a):
-            if eval('%d %s %d' % (i, op, a)): return 1
-            return 2
-
-        ops = ('<', '>', '<=', '>=', '==', '!=')        
-        for op1 in ops:
-            for op2 in ops:
-                for a,b in ((500, 500), (300, 600)):
-                    res = 0
-                    res += opval(a-1, op1, a) * (a)
-                    res += opval(  a, op1, a) 
-                    res += opval(a+1, op1, a) * (1000 - a - 1)
-                    res += opval(b, op2, b-1) * 10000 * (b)
-                    res += opval(b, op2,   b) * 10000
-                    res += opval(b, op2, b+1) * 10000 * (1000 - b - 1)
-
-                    self.run_source('''
-                    def main():
-                        sa = 0
-                        for i in range(1000):
-                            if i %s %d: sa += 1
-                            else: sa += 2
-                            if %d %s i: sa += 10000
-                            else: sa += 20000
-                        return sa
-                    '''%(op1, a, b, op2), 83, ([], res))
-
-                    self.run_source('''
-                    def main():
-                        sa = 0
-                        i = 0.0
-                        while i < 250.0:
-                            if i %s %f: sa += 1
-                            else: sa += 2
-                            if %f %s i: sa += 10000
-                            else: sa += 20000
-                            i += 0.25
-                        return sa
-                    '''%(op1, float(a)/4.0, float(b)/4.0, op2), 156, ([], res))
-
-    def test_boolrewrite_ptr(self):
-        # XXX this test is way too imprecise in what it is actually testing
-        # it should count the number of guards instead
-        compares = ('a == b', 'b == a', 'a != b', 'b != a', 'a == c', 'c != b')
-        for e1 in compares:
-            for e2 in compares:
-                a, b, c = 1, 2, 3
-                if eval(e1): res = 752 * 1 
-                else: res = 752 * 2 
-                if eval(e2): res += 752 * 10000 
-                else: res += 752 * 20000 
-                a = b
-                if eval(e1): res += 248 * 1
-                else: res += 248 * 2
-                if eval(e2): res += 248 * 10000
-                else: res += 248 * 20000
-
-
-                if 'c' in e1 or 'c' in e2:
-                    n = 337
-                else:
-                    n = 215
-
-                print
-                print 'Test:', e1, e2, n, res
-                self.run_source('''
-                class tst(object):
-                    pass
-                def main():
-                    a = tst()
-                    b = tst()
-                    c = tst()
-                    sa = 0
-                    for i in range(1000):
-                        if %s: sa += 1
-                        else: sa += 2
-                        if %s: sa += 10000
-                        else: sa += 20000
-                        if i > 750: a = b
-                    return sa
-                '''%(e1, e2), n, ([], res))
-
-    def test_array_sum(self):
-        for tc, maxops in zip('bhilBHILfd', (38,) * 6 + (40, 40, 41, 38)):
-            res = 19352859
-            if tc == 'L':
-                res = long(res)
-            elif tc in 'fd':
-                res = float(res)
-            elif tc == 'I' and sys.maxint == 2147483647:
-                res = long(res)
-                # note: in CPython we always get longs here, even on 64-bits
-
-            self.run_source('''
-            from array import array
-
-            def main():
-                img = array("%s", range(127) * 5) * 484
-                l, i = 0, 0
-                while i < 640 * 480:
-                    l += img[i]
-                    i += 1
-                return l
-            ''' % tc, maxops, ([], res))
-
-    def test_array_sum_char(self):
-        self.run_source('''
-            from array import array
-
-            def main():
-                img = array("c", "Hello") * 130 * 480
-                l, i = 0, 0
-                while i < 640 * 480:
-                    l += ord(img[i])
-                    i += 1
-                return l
-            ''', 60, ([], 30720000))
-
-    def test_array_sum_unicode(self):
-        self.run_source('''
-            from array import array
-
-            def main():
-                img = array("u", u"Hello") * 130 * 480
-                l, i = 0, 0
-                while i < 640 * 480:
-                    if img[i] == u"l":
-                        l += 1
-                    i += 1
-                return l
-            ''', 65, ([], 122880))
-
-    def test_array_intimg(self):
-        # XXX this test is way too imprecise in what it is actually testing
-        # it should count the number of guards instead
-        for tc, maxops in zip('ilILd', (67, 67, 70, 70, 61)):
-            print
-            print '='*65
-            print '='*20, 'running test for tc=%r' % (tc,), '='*20
-            res = 73574560
-            if tc == 'L':
-                res = long(res)
-            elif tc in 'fd':
-                res = float(res)
-            elif tc == 'I' and sys.maxint == 2147483647:
-                res = long(res)
-                # note: in CPython we always get longs here, even on 64-bits
-
-            self.run_source('''
-            from array import array
-
-            def main(tc):
-                img = array(tc, range(3)) * (350 * 480)
-                intimg = array(tc, (0,)) * (640 * 480)
-                l, i = 0, 640
-                while i < 640 * 480:
-                    l = l + img[i]
-                    intimg[i] = (intimg[i-640] + l) 
-                    i += 1
-                return intimg[i - 1]
-            ''', maxops, ([tc], res))
-
-    def test_unpackiterable(self):
-        self.run_source('''
-        from array import array
-
-        def main():
-            i = 0
-            t = array('l', (1, 2))
-            while i < 2000:
-                a, b = t
-                i += 1
-            return 3
-
-        ''', 100, ([], 3))
-        bytecode, = self.get_by_bytecode("UNPACK_SEQUENCE")
-        # we allocate virtual ref and frame, we don't want block
-        assert len(bytecode.get_opnames('call_may_force')) == 0
-        
-
-    def test_intbound_simple(self):
-        ops = ('<', '>', '<=', '>=', '==', '!=')
-        nbr = (3, 7)
-        for o1 in ops:
-            for o2 in ops:
-                for n1 in nbr:
-                    for n2 in nbr:
-                        src = '''
-                        def f(i):
-                            a, b = 3, 3
-                            if i %s %d:
-                                a = 0
-                            else:
-                                a = 1
-                            if i %s %d:
-                                b = 0
-                            else:
-                                b = 1
-                            return a + b * 2
-
-                        def main():
-                            res = [0] * 4
-                            idx = []
-                            for i in range(15):
-                                idx.extend([i] * 1500)
-                            for i in idx:
-                                res[f(i)] += 1
-                            return res
-
-                        ''' % (o1, n1, o2, n2)
-
-                        exec(str(py.code.Source(src)))
-                        res = [0] * 4
-                        for i in range(15):
-                            res[f(i)] += 1500
-                        self.run_source(src, 268, ([], res))
-
-    def test_intbound_addsub_mix(self):
-        tests = ('i > 4', 'i > 2', 'i + 1 > 2', '1 + i > 4',
-                 'i - 1 > 1', '1 - i > 1', '1 - i < -3',
-                 'i == 1', 'i == 5', 'i != 1', '-2 * i < -4')
-        for t1 in tests:
-            for t2 in tests:
-                print t1, t2
-                src = '''
-                def f(i):
-                    a, b = 3, 3
-                    if %s:
-                        a = 0
-                    else:
-                        a = 1
-                    if %s:
-                        b = 0
-                    else:
-                        b = 1
-                    return a + b * 2
-
-                def main():
-                    res = [0] * 4
-                    idx = []
-                    for i in range(15):
-                        idx.extend([i] * 1500)
-                    for i in idx:
-                        res[f(i)] += 1
-                    return res
-
-                ''' % (t1, t2)
-
-                exec(str(py.code.Source(src)))
-                res = [0] * 4
-                for i in range(15):
-                    res[f(i)] += 1500
-                self.run_source(src, 280, ([], res))
-
-    def test_intbound_gt(self):
-        self.run_source('''
-        def main():
-            i, a, b = 0, 0, 0
-            while i < 2000:
-                if i > -1:
-                    a += 1
-                if i > -2:
-                    b += 1
-                i += 1
-            return (a, b)
-        ''', 48, ([], (2000, 2000)))
-
-    def test_intbound_sub_lt(self):
-        self.run_source('''
-        def main():
-            i, a, b = 0, 0, 0
-            while i < 2000:
-                if i - 10 < 1995:
-                    a += 1
-                i += 1
-            return (a, b)
-        ''', 38, ([], (2000, 0)))
-
-    def test_intbound_addsub_ge(self):
-        self.run_source('''
-        def main():
-            i, a, b = 0, 0, 0
-            while i < 2000:
-                if i + 5 >= 5:
-                    a += 1
-                if i - 1 >= -1:
-                    b += 1
-                i += 1
-            return (a, b)
-        ''', 56, ([], (2000, 2000)))
-
-    def test_intbound_addmul_ge(self):
-        self.run_source('''
-        def main():
-            i, a, b = 0, 0, 0
-            while i < 2000:
-                if i + 5 >= 5:
-                    a += 1
-                if 2 * i >= 0:
-                    b += 1
-                i += 1
-            return (a, b)
-        ''', 53, ([], (2000, 2000)))
-
-    def test_intbound_eq(self):
-        self.run_source('''
-        def main(a):
-            i, s = 0, 0
-            while i < 1500:
-                if a == 7:
-                    s += a + 1
-                elif i == 10:
-                    s += i
-                else:
-                    s += 1
-                i += 1
-            return s
-        ''', 69, ([7], 12000), ([42], 1509), ([10], 1509))
-        
-    def test_intbound_mul(self):
-        self.run_source('''
-        def main(a):
-            i, s = 0, 0
-            while i < 1500:
-                assert i >= 0
-                if 2 * i < 30000:
-                    s += 1
-                else:
-                    s += a
-                i += 1
-            return s
-        ''', 43, ([7], 1500))
-        
-    def test_assert(self):
-        self.run_source('''
-        def main(a):
-            i, s = 0, 0
-            while i < 1500:
-                assert a == 7
-                s += a + 1
-                i += 1
-            return s
-        ''', 38, ([7], 8*1500))
-        
-    def test_zeropadded(self):
-        self.run_source('''
-        from array import array
-        class ZeroPadded(array):
-            def __new__(cls, l):
-                self = array.__new__(cls, 'd', range(l))
-                return self
-
-            def __getitem__(self, i):
-                if i < 0 or i >= self.__len__():
-                    return 0
-                return array.__getitem__(self, i)
-
-
-        def main():
-            buf = ZeroPadded(2000)
-            i = 10
-            sa = 0
-            while i < 2000 - 10:
-                sa += buf[i-2] + buf[i-1] + buf[i] + buf[i+1] + buf[i+2]
-                i += 1
-            return sa
-
-        ''', 232, ([], 9895050.0))
-
-    def test_circular(self):
-        self.run_source('''
-        from array import array
-        class Circular(array):
-            def __new__(cls):
-                self = array.__new__(cls, 'd', range(256))
-                return self
-            def __getitem__(self, i):
-                # assert self.__len__() == 256 (FIXME: does not improve)
-                return array.__getitem__(self, i & 255)
-
-        def main():
-            buf = Circular()
-            i = 10
-            sa = 0
-            while i < 2000 - 10:
-                sa += buf[i-2] + buf[i-1] + buf[i] + buf[i+1] + buf[i+2]
-                i += 1
-            return sa
-
-        ''', 170, ([], 1239690.0))
-
-    def test_min_max(self):
-        self.run_source('''
-        def main():
-            i=0
-            sa=0
-            while i < 2000: 
-                sa+=min(max(i, 3000), 4000)
-                i+=1
-            return sa
-        ''', 51, ([], 2000*3000))
-
-    def test_silly_max(self):
-        self.run_source('''
-        def main():
-            i=2
-            sa=0
-            while i < 2000: 
-                sa+=max(*range(i))
-                i+=1
-            return sa
-        ''', 125, ([], 1997001))
-
-    def test_iter_max(self):
-        self.run_source('''
-        def main():
-            i=2
-            sa=0
-            while i < 2000: 
-                sa+=max(range(i))
-                i+=1
-            return sa
-        ''', 88, ([], 1997001))
-
     def test__ffi_call(self):
         from pypy.rlib.test.test_libffi import get_libm_name
         libm_name = get_libm_name(sys.platform)

diff --git a/pypy/jit/metainterp/test/test_blackhole.py b/pypy/jit/metainterp/test/test_blackhole.py
--- a/pypy/jit/metainterp/test/test_blackhole.py
+++ b/pypy/jit/metainterp/test/test_blackhole.py
@@ -1,6 +1,6 @@
 import py
 from pypy.rlib.jit import JitDriver
-from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
+from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
 from pypy.jit.metainterp.blackhole import BlackholeInterpBuilder
 from pypy.jit.metainterp.blackhole import BlackholeInterpreter
 from pypy.jit.metainterp.blackhole import convert_and_run_from_pyjitpl

diff --git a/pypy/rpython/test/test_rint.py b/pypy/rpython/test/test_rint.py
--- a/pypy/rpython/test/test_rint.py
+++ b/pypy/rpython/test/test_rint.py
@@ -4,7 +4,7 @@
 from pypy.annotation import model as annmodel
 from pypy.rpython.test import snippet
 from pypy.rlib.rarithmetic import r_int, r_uint, r_longlong, r_ulonglong
-from pypy.rlib.rarithmetic import ovfcheck, r_int64, intmask
+from pypy.rlib.rarithmetic import ovfcheck, r_int64, intmask, int_between
 from pypy.rlib import objectmodel
 from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin
 
@@ -215,6 +215,14 @@
             assert res == f(inttype(0))
             assert type(res) == inttype
 
+    def test_and_or(self):
+        inttypes = [int, r_uint, r_int64, r_ulonglong]
+        for inttype in inttypes:
+            def f(a, b, c):
+                return a&b|c
+            res = self.interpret(f, [inttype(0x1234), inttype(0x00FF), inttype(0x5600)])
+            assert res == f(0x1234, 0x00FF, 0x5600)
+
     def test_neg_abs_ovf(self):
         for op in (operator.neg, abs):
             def f(x):
@@ -388,6 +396,18 @@
         else:
             assert res == 123456789012345678
 
+    def test_int_between(self):
+        def fn(a, b, c):
+            return int_between(a, b, c)
+        assert self.interpret(fn, [1, 1, 3])
+        assert self.interpret(fn, [1, 2, 3])
+        assert not self.interpret(fn, [1, 0, 2])
+        assert not self.interpret(fn, [1, 5, 2])
+        assert not self.interpret(fn, [1, 2, 2])
+        assert not self.interpret(fn, [1, 1, 1])
+
+
+
 class TestLLtype(BaseTestRint, LLRtypeMixin):
     pass
 

diff --git a/pypy/translator/jvm/src/pypy/PyPy.java b/pypy/translator/jvm/src/pypy/PyPy.java
--- a/pypy/translator/jvm/src/pypy/PyPy.java
+++ b/pypy/translator/jvm/src/pypy/PyPy.java
@@ -38,6 +38,10 @@
     public final static int INT_MIN = Integer.MIN_VALUE;
     public final static double ULONG_MAX = 18446744073709551616.0;
 
+    public static boolean int_between(int a, int b, int c) {
+        return a <= b && b < c;
+    }
+
     /** 
      * Compares two unsigned integers (value1 and value2) and returns
      * a value greater than, equal to, or less than zero if value 1 is
@@ -163,6 +167,13 @@
             return ULONG_MAX + value;
         }
     }
+
+    public static long double_to_ulong(double value) {
+        if (value < 0)
+            return (long)(ULONG_MAX + value);
+        else
+            return (long)value;
+    }
     
     public static int double_to_uint(double value) {
         if (value <= Integer.MAX_VALUE)
@@ -1175,6 +1186,18 @@
         return Math.tanh(x);
     }
 
+    public double ll_math_copysign(double x, double y) {
+        return Math.copySign(x, y);
+    }
+
+    public boolean ll_math_isnan(double x) {
+        return Double.isNaN(x);
+    }
+
+    public boolean ll_math_isinf(double x) {
+        return Double.isInfinite(x);
+    }
+
     private double check(double v) {
         if (Double.isNaN(v))
             interlink.throwValueError();
@@ -1187,9 +1210,42 @@
         return Character.toLowerCase(c);
     }
 
+    public int locale_tolower(int chr)
+    {
+        return Character.toLowerCase(chr);
+    }
+
+    public int locale_isupper(int chr)
+    {
+        return boolean2int(Character.isUpperCase(chr));
+    }
+
+    public int locale_islower(int chr)
+    {
+        return boolean2int(Character.isLowerCase(chr));
+    }
+
+    public int locale_isalpha(int chr)
+    {
+        return boolean2int(Character.isLetter(chr));
+    }
+
+    public int locale_isalnum(int chr)
+    {
+        return boolean2int(Character.isLetterOrDigit(chr));
+    }
+
+
     // ----------------------------------------------------------------------
     // Self Test
 
+    public static int boolean2int(boolean b)
+    {
+        if (b)
+            return 1;
+        return 0;
+    }
+
     public static int __counter = 0, __failures = 0;
     public static void ensure(boolean f) {
         if (f) {

diff --git a/pypy/jit/metainterp/test/test_string.py b/pypy/jit/metainterp/test/test_string.py
--- a/pypy/jit/metainterp/test/test_string.py
+++ b/pypy/jit/metainterp/test/test_string.py
@@ -2,7 +2,7 @@
 from pypy.rlib.jit import JitDriver, dont_look_inside, we_are_jitted
 from pypy.jit.codewriter.policy import StopAtXPolicy
 from pypy.rpython.ootypesystem import ootype
-from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
+from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
 
 
 class StringTests:

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

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

diff --git a/pypy/jit/metainterp/test/test_greenfield.py b/pypy/jit/metainterp/test/test_greenfield.py
--- a/pypy/jit/metainterp/test/test_greenfield.py
+++ b/pypy/jit/metainterp/test/test_greenfield.py
@@ -1,4 +1,4 @@
-from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
+from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
 from pypy.rlib.jit import JitDriver
 
 

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

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

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

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

diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py
--- a/pypy/config/pypyoption.py
+++ b/pypy/config/pypyoption.py
@@ -13,7 +13,7 @@
                and not p.basename.startswith('test')]
 
 essential_modules = dict.fromkeys(
-    ["exceptions", "_file", "sys", "__builtin__", "posix", "signal"]
+    ["exceptions", "_file", "sys", "__builtin__", "posix"]
 )
 
 default_modules = essential_modules.copy()
@@ -39,7 +39,7 @@
 translation_modules = default_modules.copy()
 translation_modules.update(dict.fromkeys(
     ["fcntl", "rctime", "select", "signal", "_rawffi", "zlib",
-     "struct", "md5", "cStringIO", "array"]))
+     "struct", "_md5", "cStringIO", "array"]))
 
 working_oo_modules = default_modules.copy()
 working_oo_modules.update(dict.fromkeys(

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

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

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

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

diff --git a/pypy/rpython/lltypesystem/test/test_ll2ctypes.py b/pypy/rpython/lltypesystem/test/test_ll2ctypes.py
--- a/pypy/rpython/lltypesystem/test/test_ll2ctypes.py
+++ b/pypy/rpython/lltypesystem/test/test_ll2ctypes.py
@@ -1000,6 +1000,13 @@
         p = ctypes2lltype(lltype.Ptr(NODE), ctypes.pointer(pc))
         assert p.pong.ping == p
 
+    def test_typedef(self):
+        assert ctypes2lltype(lltype.Typedef(lltype.Signed, 'test'), 6) == 6
+        assert ctypes2lltype(lltype.Typedef(lltype.Float, 'test2'), 3.4) == 3.4
+
+        assert get_ctypes_type(lltype.Signed) == get_ctypes_type(
+            lltype.Typedef(lltype.Signed, 'test3'))
+
     def test_cast_adr_to_int(self):
         class someaddr(object):
             def _cast_to_int(self):
@@ -1014,7 +1021,7 @@
         node = lltype.malloc(NODE)
         ref = lltype.cast_opaque_ptr(llmemory.GCREF, node)
         back = rffi.cast(llmemory.GCREF, rffi.cast(lltype.Signed, ref))
-        assert lltype.cast_opaque_ptr(lltype.Ptr(NODE), ref) == node
+        assert lltype.cast_opaque_ptr(lltype.Ptr(NODE), back) == node
 
     def test_gcref_forth_and_back(self):
         cp = ctypes.c_void_p(1234)

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

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

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

diff --git a/pypy/jit/metainterp/test/test_longlong.py b/pypy/jit/metainterp/test/test_longlong.py
--- a/pypy/jit/metainterp/test/test_longlong.py
+++ b/pypy/jit/metainterp/test/test_longlong.py
@@ -1,6 +1,6 @@
 import py, sys
 from pypy.rlib.rarithmetic import r_longlong, r_ulonglong, r_uint, intmask
-from pypy.jit.metainterp.test.test_basic import LLJitMixin
+from pypy.jit.metainterp.test.support import LLJitMixin
 
 class WrongResult(Exception):
     pass

diff --git a/pypy/module/__builtin__/test/test_builtin.py b/pypy/module/__builtin__/test/test_builtin.py
--- a/pypy/module/__builtin__/test/test_builtin.py
+++ b/pypy/module/__builtin__/test/test_builtin.py
@@ -110,6 +110,13 @@
             __dict__ = 8
         raises(TypeError, dir, Foo("foo"))
 
+    def test_dir_broken_object(self):
+        class Foo(object):
+            x = 3
+            def __getattribute__(self, name):
+                return name
+        assert dir(Foo()) == []
+
     def test_dir_custom(self):
         class Foo(object):
             def __dir__(self):

diff --git a/lib_pypy/_ctypes/builtin.py b/lib_pypy/_ctypes/builtin.py
--- a/lib_pypy/_ctypes/builtin.py
+++ b/lib_pypy/_ctypes/builtin.py
@@ -1,6 +1,9 @@
 
 import _rawffi, sys
-import threading
+try:
+    from thread import _local as local
+except ImportError:
+    local = object    # no threads
 
 class ConvMode:
     encoding = 'ascii'
@@ -28,7 +31,7 @@
     arg = cobj._get_buffer_value()
     return _rawffi.wcharp2rawunicode(arg, lgt)
 
-class ErrorObject(threading.local):
+class ErrorObject(local):
     def __init__(self):
         self.errno = 0
         self.winerror = 0

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

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

diff --git a/pypy/rpython/lltypesystem/lltype.py b/pypy/rpython/lltypesystem/lltype.py
--- a/pypy/rpython/lltypesystem/lltype.py
+++ b/pypy/rpython/lltypesystem/lltype.py
@@ -95,6 +95,8 @@
     __slots__ = ['__dict__', '__cached_hash']
 
     def __eq__(self, other):
+        if isinstance(other, Typedef):
+            return other.__eq__(self)
         return self.__class__ is other.__class__ and (
             self is other or safe_equal(self.__dict__, other.__dict__))
 
@@ -194,6 +196,36 @@
         raise NotImplementedError
 
 
+class Typedef(LowLevelType):
+    """A typedef is just another name for an existing type"""
+    def __init__(self, OF, c_name):
+        """
+        @param OF: the equivalent rffi type
+        @param c_name: the name we want in C code
+        """
+        assert isinstance(OF, LowLevelType)
+        # Look through typedefs, so other places don't have to
+        if isinstance(OF, Typedef):
+            OF = OF.OF # haha
+        self.OF = OF
+        self.c_name = c_name
+
+    def __repr__(self):
+        return '<Typedef "%s" of %r>' % (self.c_name, self.OF)
+
+    def __eq__(self, other):
+        return other == self.OF
+
+    def __getattr__(self, name):
+        return self.OF.get(name)
+
+    def _defl(self, parent=None, parentindex=None):
+        return self.OF._defl()
+
+    def _allocate(self, initialization, parent=None, parentindex=None):
+        return self.OF._allocate(initialization, parent, parentindex)
+
+
 class Struct(ContainerType):
     _gckind = 'raw'
 

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


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


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

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

diff --git a/pypy/jit/metainterp/test/test_fficall.py b/pypy/jit/metainterp/test/test_fficall.py
--- a/pypy/jit/metainterp/test/test_fficall.py
+++ b/pypy/jit/metainterp/test/test_fficall.py
@@ -5,7 +5,7 @@
 from pypy.rlib.libffi import ArgChain
 from pypy.rlib.test.test_libffi import TestLibffiCall as _TestLibffiCall
 from pypy.rpython.lltypesystem import lltype, rffi
-from pypy.jit.metainterp.test.test_basic import LLJitMixin
+from pypy.jit.metainterp.test.support import LLJitMixin
 
 
 class TestFfiCall(LLJitMixin, _TestLibffiCall):

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

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

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

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

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

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

diff --git a/pypy/translator/cli/src/pypylib.cs b/pypy/translator/cli/src/pypylib.cs
--- a/pypy/translator/cli/src/pypylib.cs
+++ b/pypy/translator/cli/src/pypylib.cs
@@ -501,6 +501,11 @@
             }
         }
 
+        public static bool IntBetween(int a, int b, int c)
+        {
+            return a <= b && b < c;
+        }
+
         public static bool Equal<T>(T t1, T t2) 
         { 
             if (t1 == null)
@@ -1148,10 +1153,36 @@
 
     public class rffi
     {
-      public static int tolower(int chr)
-      {
-        return (int)Char.ToLower((char)chr);
-      }
+        public static int tolower(int chr)
+        {
+            return (int)Char.ToLower((char)chr);
+        }
+
+        public static int locale_tolower(int chr)
+        {
+            return (int)Char.ToLower((char)chr);
+        }
+
+        public static int locale_isupper(int chr)
+        {
+            return Convert.ToInt32(Char.IsUpper((char)chr));
+        }
+
+        public static int locale_islower(int chr)
+        {
+            return Convert.ToInt32(Char.IsLower((char)chr));
+        }
+
+        public static int locale_isalpha(int chr)
+        {
+            return Convert.ToInt32(Char.IsLetter((char)chr));
+        }
+
+        public static int locale_isalnum(int chr)
+        {
+            return Convert.ToInt32(Char.IsLetterOrDigit((char)chr));
+        }
+
     }
 
 }

diff --git a/pypy/jit/backend/x86/test/test_basic.py b/pypy/jit/backend/x86/test/test_basic.py
--- a/pypy/jit/backend/x86/test/test_basic.py
+++ b/pypy/jit/backend/x86/test/test_basic.py
@@ -1,18 +1,18 @@
 import py
 from pypy.jit.backend.detect_cpu import getcpuclass
 from pypy.jit.metainterp.warmspot import ll_meta_interp
-from pypy.jit.metainterp.test import test_basic
+from pypy.jit.metainterp.test import support, test_ajit
 from pypy.jit.codewriter.policy import StopAtXPolicy
 from pypy.rlib.jit import JitDriver
 
-class Jit386Mixin(test_basic.LLJitMixin):
+class Jit386Mixin(support.LLJitMixin):
     type_system = 'lltype'
     CPUClass = getcpuclass()
 
     def check_jumps(self, maxcount):
         pass
 
-class TestBasic(Jit386Mixin, test_basic.BaseLLtypeTests):
+class TestBasic(Jit386Mixin, test_ajit.BaseLLtypeTests):
     # for the individual tests see
     # ====> ../../../metainterp/test/test_basic.py
     def test_bug(self):

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

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

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


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

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

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



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



diff --git a/pypy/jit/metainterp/test/test_loop_unroll.py b/pypy/jit/metainterp/test/test_loop_unroll.py
--- a/pypy/jit/metainterp/test/test_loop_unroll.py
+++ b/pypy/jit/metainterp/test/test_loop_unroll.py
@@ -1,7 +1,7 @@
 import py
 from pypy.rlib.jit import JitDriver
 from pypy.jit.metainterp.test import test_loop
-from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
+from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
 from pypy.jit.metainterp.optimizeopt import ALL_OPTS_NAMES
 
 class LoopUnrollTest(test_loop.LoopTest):

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

diff --git a/pypy/module/cpyext/object.py b/pypy/module/cpyext/object.py
--- a/pypy/module/cpyext/object.py
+++ b/pypy/module/cpyext/object.py
@@ -245,6 +245,16 @@
     expression cmp(o1, o2)."""
     return space.int_w(space.cmp(w_o1, w_o2))
 
+ at cpython_api([PyObject, PyObject, rffi.INTP], rffi.INT_real, error=-1)
+def PyObject_Cmp(space, w_o1, w_o2, result):
+    """Compare the values of o1 and o2 using a routine provided by o1, if one
+    exists, otherwise with a routine provided by o2.  The result of the
+    comparison is returned in result.  Returns -1 on failure.  This is the
+    equivalent of the Python statement result = cmp(o1, o2)."""
+    res = space.int_w(space.cmp(w_o1, w_o2))
+    result[0] = rffi.cast(rffi.INT, res)
+    return 0
+
 @cpython_api([PyObject, PyObject, rffi.INT_real], PyObject)
 def PyObject_RichCompare(space, w_o1, w_o2, opid_int):
     """Compare the values of o1 and o2 using the operation specified by opid,
@@ -385,7 +395,7 @@
         raise OperationError(space.w_TypeError, space.wrap(
             "expected a character buffer object"))
     if generic_cpy_call(space, pb.c_bf_getsegcount,
-                        obj, lltype.nullptr(rffi.INTP.TO)) != 1:
+                        obj, lltype.nullptr(Py_ssize_tP.TO)) != 1:
         raise OperationError(space.w_TypeError, space.wrap(
             "expected a single-segment buffer object"))
     size = generic_cpy_call(space, pb.c_bf_getcharbuffer,



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
@@ -446,7 +446,6 @@
     IGNORE_OPS_WITH_PREFIXES = dict.fromkeys([
         'cmp', 'test', 'set', 'sahf', 'lahf', 'cltd', 'cld', 'std',
         'rep', 'movs', 'lods', 'stos', 'scas', 'cwtl', 'cwde', 'prefetch',
-        'pslld', 
         # floating-point operations cannot produce GC pointers
         'f',
         'cvt', 'ucomi', 'comi', 'subs', 'subp' , 'adds', 'addp', 'xorp',
@@ -457,6 +456,7 @@
         'shl', 'shr', 'sal', 'sar', 'rol', 'ror', 'mul', 'imul', 'div', 'idiv',
         'bswap', 'bt', 'rdtsc',
         'punpck', 'pshufd', 'pcmp', 'pand', 'psllw', 'pslld', 'psllq',
+        'paddq', 'pinsr',
         # zero-extending moves should not produce GC pointers
         'movz', 
         ])
@@ -1645,7 +1645,7 @@
                      darwin64='')
             print >> output, "%s:" % _globalname('pypy_asm_stackwalk')
 
-            print >> output, """\
+            s = """\
             /* See description in asmgcroot.py */
             .cfi_startproc
             movq\t%rdi, %rdx\t/* 1st argument, which is the callback */
@@ -1691,6 +1691,12 @@
             ret
             .cfi_endproc
             """
+            if self.format == 'darwin64':
+                # obscure.  gcc there seems not to support .cfi_...
+                # hack it out...
+                s = re.sub(r'([.]cfi_[^/\n]+)([/\n])',
+                           r'/* \1 disabled on darwin */\2', s)
+            print >> output, s
             _variant(elf64='.size pypy_asm_stackwalk, .-pypy_asm_stackwalk',
                      darwin64='')
         else:

diff --git a/pypy/rlib/runicode.py b/pypy/rlib/runicode.py
--- a/pypy/rlib/runicode.py
+++ b/pypy/rlib/runicode.py
@@ -87,8 +87,9 @@
     result = UnicodeBuilder(size)
     pos = 0
     while pos < size:
-        ch = s[pos]
-        ordch1 = ord(ch)
+        ordch1 = ord(s[pos])
+        # fast path for ASCII
+        # XXX maybe use a while loop here
         if ordch1 < 0x80:
             result.append(unichr(ordch1))
             pos += 1
@@ -98,110 +99,149 @@
         if pos + n > size:
             if not final:
                 break
-            else:
-                endpos = pos + 1
-                while endpos < size and ord(s[endpos]) & 0xC0 == 0x80:
-                    endpos += 1
-                r, pos = errorhandler(errors, "utf-8",
-                                      "unexpected end of data",
-                                      s,  pos, endpos)
+            charsleft = size - pos - 1 # either 0, 1, 2
+            # note: when we get the 'unexpected end of data' we don't care
+            # about the pos anymore and we just ignore the value
+            if not charsleft:
+                # there's only the start byte and nothing else
+                r, pos = errorhandler(errors, 'utf-8',
+                                      'unexpected end of data',
+                                      s, pos, pos+1)
+                result.append(r)
+                break
+            ordch2 = ord(s[pos+1])
+            if n == 3:
+                # 3-bytes seq with only a continuation byte
+                if (ordch2>>6 != 0x2 or   # 0b10
+                    (ordch1 == 0xe0 and ordch2 < 0xa0)):
+                    # or (ordch1 == 0xed and ordch2 > 0x9f)
+                    # second byte invalid, take the first and continue
+                    r, pos = errorhandler(errors, 'utf-8',
+                                          'invalid continuation byte',
+                                          s, pos, pos+1)
+                    result.append(r)
+                    continue
+                else:
+                    # second byte valid, but third byte missing
+                    r, pos = errorhandler(errors, 'utf-8',
+                                      'unexpected end of data',
+                                      s, pos, pos+2)
+                    result.append(r)
+                    break
+            elif n == 4:
+                # 4-bytes seq with 1 or 2 continuation bytes
+                if (ordch2>>6 != 0x2 or    # 0b10
+                    (ordch1 == 0xf0 and ordch2 < 0x90) or
+                    (ordch1 == 0xf4 and ordch2 > 0x8f)):
+                    # second byte invalid, take the first and continue
+                    r, pos = errorhandler(errors, 'utf-8',
+                                          'invalid continuation byte',
+                                          s, pos, pos+1)
+                    result.append(r)
+                    continue
+                elif charsleft == 2 and ord(s[pos+2])>>6 != 0x2:   # 0b10
+                    # third byte invalid, take the first two and continue
+                    r, pos = errorhandler(errors, 'utf-8',
+                                          'invalid continuation byte',
+                                          s, pos, pos+2)
+                    result.append(r)
+                    continue
+                else:
+                    # there's only 1 or 2 valid cb, but the others are missing
+                    r, pos = errorhandler(errors, 'utf-8',
+                                      'unexpected end of data',
+                                      s, pos, pos+charsleft+1)
+                    result.append(r)
+                    break
+
+        if n == 0:
+            r, pos = errorhandler(errors, 'utf-8',
+                                  'invalid start byte',
+                                  s, pos, pos+1)
+            result.append(r)
+
+        elif n == 1:
+            assert 0, "ascii should have gone through the fast path"
+
+        elif n == 2:
+            ordch2 = ord(s[pos+1])
+            if ordch2>>6 != 0x2:   # 0b10
+                r, pos = errorhandler(errors, 'utf-8',
+                                      'invalid continuation byte',
+                                      s, pos, pos+1)
                 result.append(r)
                 continue
+            # 110yyyyy 10zzzzzz -> 00000000 00000yyy yyzzzzzz
+            result.append(unichr(((ordch1 & 0x1F) << 6) +    # 0b00011111
+                                 (ordch2 & 0x3F)))           # 0b00111111
+            pos += 2
 
-        if n == 0:
-            r, pos = errorhandler(errors, "utf-8",
-                                  "invalid start byte",
-                                  s,  pos, pos + 1)
-            result.append(r)
-        elif n == 1:
-            assert 0, "you can never get here"
-        elif n == 2:
-            # 110yyyyy 10zzzzzz   ====>  00000000 00000yyy yyzzzzzz
-
-            ordch2 = ord(s[pos+1])
-            z, two = splitter[6, 2](ordch2)
-            y, six = splitter[5, 3](ordch1)
-            assert six == 6
-            if two != 2:
-                r, pos = errorhandler(errors, "utf-8",
-                                      "invalid continuation byte",
-                                      s,  pos, pos + 1)
-                result.append(r)
-            else:
-                c = (y << 6) + z
-                result.append(unichr(c))
-                pos += n
         elif n == 3:
-            #  1110xxxx 10yyyyyy 10zzzzzz ====> 00000000 xxxxyyyy yyzzzzzz
             ordch2 = ord(s[pos+1])
             ordch3 = ord(s[pos+2])
-            z, two1 = splitter[6, 2](ordch3)
-            y, two2 = splitter[6, 2](ordch2)
-            x, fourteen = splitter[4, 4](ordch1)
-            assert fourteen == 14
-            if (two1 != 2 or two2 != 2 or
+            if (ordch2>>6 != 0x2 or    # 0b10
                 (ordch1 == 0xe0 and ordch2 < 0xa0)
                 # surrogates shouldn't be valid UTF-8!
                 # Uncomment the line below to make them invalid.
                 # or (ordch1 == 0xed and ordch2 > 0x9f)
                 ):
+                r, pos = errorhandler(errors, 'utf-8',
+                                      'invalid continuation byte',
+                                      s, pos, pos+1)
+                result.append(r)
+                continue
+            elif ordch3>>6 != 0x2:     # 0b10
+                r, pos = errorhandler(errors, 'utf-8',
+                                      'invalid continuation byte',
+                                      s, pos, pos+2)
+                result.append(r)
+                continue
+            # 1110xxxx 10yyyyyy 10zzzzzz -> 00000000 xxxxyyyy yyzzzzzz
+            result.append(unichr(((ordch1 & 0x0F) << 12) +     # 0b00001111
+                                 ((ordch2 & 0x3F) << 6) +      # 0b00111111
+                                 (ordch3 & 0x3F)))             # 0b00111111
+            pos += 3
 
-                # if ordch2 first two bits are 1 and 0, then the invalid
-                # continuation byte is ordch3; else ordch2 is invalid.
-                if two2 == 2:
-                    endpos = pos + 2
-                else:
-                    endpos = pos + 1
-                r, pos = errorhandler(errors, "utf-8",
-                                      "invalid continuation byte",
-                                      s,  pos, endpos)
-                result.append(r)
-            else:
-                c = (x << 12) + (y << 6) + z
-                result.append(unichr(c))
-                pos += n
         elif n == 4:
-            # 11110www 10xxxxxx 10yyyyyy 10zzzzzz ====>
-            # 000wwwxx xxxxyyyy yyzzzzzz
             ordch2 = ord(s[pos+1])
             ordch3 = ord(s[pos+2])
             ordch4 = ord(s[pos+3])
-            z, two1 = splitter[6, 2](ordch4)
-            y, two2 = splitter[6, 2](ordch3)
-            x, two3 = splitter[6, 2](ordch2)
-            w, thirty = splitter[3, 5](ordch1)
-            assert thirty == 30
-            if (two1 != 2 or two2 != 2 or two3 != 2 or
+            if (ordch2>>6 != 0x2 or     # 0b10
                 (ordch1 == 0xf0 and ordch2 < 0x90) or
                 (ordch1 == 0xf4 and ordch2 > 0x8f)):
-                endpos = pos + 1
-                if ordch2 & 0xc0 == 0x80:
-                    endpos += 1
-                    if ordch3 & 0xc0 == 0x80:
-                        endpos += 1
-                r, pos = errorhandler(errors, "utf-8",
-                                      "invalid continuation byte",
-                                      s,  pos, endpos)
+                r, pos = errorhandler(errors, 'utf-8',
+                                      'invalid continuation byte',
+                                      s, pos, pos+1)
                 result.append(r)
+                continue
+            elif ordch3>>6 != 0x2:     # 0b10
+                r, pos = errorhandler(errors, 'utf-8',
+                                      'invalid continuation byte',
+                                      s, pos, pos+2)
+                result.append(r)
+                continue
+            elif ordch4>>6 != 0x2:     # 0b10
+                r, pos = errorhandler(errors, 'utf-8',
+                                      'invalid continuation byte',
+                                      s, pos, pos+3)
+                result.append(r)
+                continue
+            # 11110www 10xxxxxx 10yyyyyy 10zzzzzz -> 000wwwxx xxxxyyyy yyzzzzzz
+            c = (((ordch1 & 0x07) << 18) +      # 0b00000111
+                 ((ordch2 & 0x3F) << 12) +      # 0b00111111
+                 ((ordch3 & 0x3F) << 6) +       # 0b00111111
+                 (ordch4 & 0x3F))               # 0b00111111
+            if c <= MAXUNICODE:
+                result.append(UNICHR(c))
             else:
-                c = (w << 18) + (x << 12) + (y << 6) + z
-                # convert to UTF-16 if necessary
-                if c <= MAXUNICODE:
-                    result.append(UNICHR(c))
-                else:
-                    # compute and append the two surrogates:
-                    # translate from 10000..10FFFF to 0..FFFF
-                    c -= 0x10000
-                    # high surrogate = top 10 bits added to D800
-                    result.append(unichr(0xD800 + (c >> 10)))
-                    # low surrogate = bottom 10 bits added to DC00
-                    result.append(unichr(0xDC00 + (c & 0x03FF)))
-                pos += n
-        else:
-            r, pos = errorhandler(errors, "utf-8",
-                                  "unsupported Unicode code range",
-                                  s,  pos, pos + n)
-            result.append(r)
+                # compute and append the two surrogates:
+                # translate from 10000..10FFFF to 0..FFFF
+                c -= 0x10000
+                # high surrogate = top 10 bits added to D800
+                result.append(unichr(0xD800 + (c >> 10)))
+                # low surrogate = bottom 10 bits added to DC00
+                result.append(unichr(0xDC00 + (c & 0x03FF)))
+            pos += 4
 
     return result.build(), pos
 
@@ -629,7 +669,7 @@
     3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,
 #  sp   !   "   #   $   %   &   '   (   )   *   +   ,   -   .   /
     2,  1,  1,  1,  1,  1,  1,  0,  0,  0,  1,  3,  0,  0,  0,  0,
-#   0   1   2   3   4   5   6   7   8   9   :   ;   <   =   >   ? 
+#   0   1   2   3   4   5   6   7   8   9   :   ;   <   =   >   ?
     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  0,
 #   @   A   B   C   D   E   F   G   H   I   J   K   L   M   N   O
     1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
@@ -905,20 +945,20 @@
     pos = 0
     while pos < size:
         ch = p[pos]
-        
+
         if ord(ch) < limit:
             result.append(chr(ord(ch)))
             pos += 1
         else:
             # startpos for collecting unencodable chars
-            collstart = pos 
-            collend = pos+1 
+            collstart = pos
+            collend = pos+1
             while collend < len(p) and ord(p[collend]) >= limit:
                 collend += 1
             r, pos = errorhandler(errors, encoding, reason, p,
                                   collstart, collend)
             result.append(r)
-    
+
     return result.build()
 
 def unicode_encode_latin_1(p, size, errors, errorhandler=None):

diff --git a/pypy/jit/tl/spli/test/test_jit.py b/pypy/jit/tl/spli/test/test_jit.py
--- a/pypy/jit/tl/spli/test/test_jit.py
+++ b/pypy/jit/tl/spli/test/test_jit.py
@@ -1,6 +1,6 @@
 
 import py
-from pypy.jit.metainterp.test.test_basic import JitMixin
+from pypy.jit.metainterp.test.support import JitMixin
 from pypy.jit.tl.spli import interpreter, objects, serializer
 from pypy.jit.metainterp.typesystem import LLTypeHelper, OOTypeHelper
 from pypy.jit.backend.llgraph import runner

diff --git a/pypy/jit/metainterp/test/test_virtual.py b/pypy/jit/metainterp/test/test_virtual.py
--- a/pypy/jit/metainterp/test/test_virtual.py
+++ b/pypy/jit/metainterp/test/test_virtual.py
@@ -2,7 +2,7 @@
 from pypy.rlib.jit import JitDriver, hint
 from pypy.rlib.objectmodel import compute_unique_id
 from pypy.jit.codewriter.policy import StopAtXPolicy
-from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
+from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
 from pypy.rpython.lltypesystem import lltype, rclass
 from pypy.rpython.lltypesystem.lloperation import llop
 from pypy.rpython.ootypesystem import ootype

diff --git a/pypy/jit/metainterp/test/support.py b/pypy/jit/metainterp/test/support.py
new file mode 100644
--- /dev/null
+++ b/pypy/jit/metainterp/test/support.py
@@ -0,0 +1,261 @@
+
+import py, sys
+from pypy.rpython.lltypesystem import lltype, llmemory
+from pypy.rpython.ootypesystem import ootype
+from pypy.jit.backend.llgraph import runner
+from pypy.jit.metainterp.warmspot import ll_meta_interp, get_stats
+from pypy.jit.metainterp.optimizeopt import ALL_OPTS_DICT
+from pypy.jit.metainterp import pyjitpl, history
+from pypy.jit.metainterp.warmstate import set_future_value
+from pypy.jit.codewriter.policy import JitPolicy
+from pypy.jit.codewriter import longlong
+
+def _get_jitcodes(testself, CPUClass, func, values, type_system,
+                  supports_longlong=False, **kwds):
+    from pypy.jit.codewriter import support, codewriter
+
+    class FakeJitCell:
+        __compiled_merge_points = []
+        def get_compiled_merge_points(self):
+            return self.__compiled_merge_points[:]
+        def set_compiled_merge_points(self, lst):
+            self.__compiled_merge_points = lst
+
+    class FakeWarmRunnerState:
+        def attach_unoptimized_bridge_from_interp(self, greenkey, newloop):
+            pass
+
+        def jit_cell_at_key(self, greenkey):
+            assert greenkey == []
+            return self._cell
+        _cell = FakeJitCell()
+
+        trace_limit = sys.maxint
+        enable_opts = ALL_OPTS_DICT
+
+    func._jit_unroll_safe_ = True
+    rtyper = support.annotate(func, values, type_system=type_system)
+    graphs = rtyper.annotator.translator.graphs
+    result_kind = history.getkind(graphs[0].getreturnvar().concretetype)[0]
+
+    class FakeJitDriverSD:
+        num_green_args = 0
+        portal_graph = graphs[0]
+        virtualizable_info = None
+        greenfield_info = None
+        result_type = result_kind
+        portal_runner_ptr = "???"
+
+    stats = history.Stats()
+    cpu = CPUClass(rtyper, stats, None, False)
+    cw = codewriter.CodeWriter(cpu, [FakeJitDriverSD()])
+    testself.cw = cw
+    policy = JitPolicy()
+    policy.set_supports_longlong(supports_longlong)
+    cw.find_all_graphs(policy)
+    #
+    testself.warmrunnerstate = FakeWarmRunnerState()
+    testself.warmrunnerstate.cpu = cpu
+    FakeJitDriverSD.warmstate = testself.warmrunnerstate
+    if hasattr(testself, 'finish_setup_for_interp_operations'):
+        testself.finish_setup_for_interp_operations()
+    #
+    cw.make_jitcodes(verbose=True)
+
+def _run_with_blackhole(testself, args):
+    from pypy.jit.metainterp.blackhole import BlackholeInterpBuilder
+    cw = testself.cw
+    blackholeinterpbuilder = BlackholeInterpBuilder(cw)
+    blackholeinterp = blackholeinterpbuilder.acquire_interp()
+    count_i = count_r = count_f = 0
+    for value in args:
+        T = lltype.typeOf(value)
+        if T == lltype.Signed:
+            blackholeinterp.setarg_i(count_i, value)
+            count_i += 1
+        elif T == llmemory.GCREF:
+            blackholeinterp.setarg_r(count_r, value)
+            count_r += 1
+        elif T == lltype.Float:
+            value = longlong.getfloatstorage(value)
+            blackholeinterp.setarg_f(count_f, value)
+            count_f += 1
+        else:
+            raise TypeError(T)
+    [jitdriver_sd] = cw.callcontrol.jitdrivers_sd
+    blackholeinterp.setposition(jitdriver_sd.mainjitcode, 0)
+    blackholeinterp.run()
+    return blackholeinterp._final_result_anytype()
+
+def _run_with_pyjitpl(testself, args):
+
+    class DoneWithThisFrame(Exception):
+        pass
+
+    class DoneWithThisFrameRef(DoneWithThisFrame):
+        def __init__(self, cpu, *args):
+            DoneWithThisFrame.__init__(self, *args)
+
+    cw = testself.cw
+    opt = history.Options(listops=True)
+    metainterp_sd = pyjitpl.MetaInterpStaticData(cw.cpu, opt)
+    metainterp_sd.finish_setup(cw)
+    [jitdriver_sd] = metainterp_sd.jitdrivers_sd
+    metainterp = pyjitpl.MetaInterp(metainterp_sd, jitdriver_sd)
+    metainterp_sd.DoneWithThisFrameInt = DoneWithThisFrame
+    metainterp_sd.DoneWithThisFrameRef = DoneWithThisFrameRef
+    metainterp_sd.DoneWithThisFrameFloat = DoneWithThisFrame
+    testself.metainterp = metainterp
+    try:
+        metainterp.compile_and_run_once(jitdriver_sd, *args)
+    except DoneWithThisFrame, e:
+        #if conftest.option.view:
+        #    metainterp.stats.view()
+        return e.args[0]
+    else:
+        raise Exception("FAILED")
+
+def _run_with_machine_code(testself, args):
+    metainterp = testself.metainterp
+    num_green_args = metainterp.jitdriver_sd.num_green_args
+    loop_tokens = metainterp.get_compiled_merge_points(args[:num_green_args])
+    if len(loop_tokens) != 1:
+        return NotImplemented
+    # a loop was successfully created by _run_with_pyjitpl(); call it
+    cpu = metainterp.cpu
+    for i in range(len(args) - num_green_args):
+        x = args[num_green_args + i]
+        typecode = history.getkind(lltype.typeOf(x))
+        set_future_value(cpu, i, x, typecode)
+    faildescr = cpu.execute_token(loop_tokens[0])
+    assert faildescr.__class__.__name__.startswith('DoneWithThisFrameDescr')
+    if metainterp.jitdriver_sd.result_type == history.INT:
+        return cpu.get_latest_value_int(0)
+    elif metainterp.jitdriver_sd.result_type == history.REF:
+        return cpu.get_latest_value_ref(0)
+    elif metainterp.jitdriver_sd.result_type == history.FLOAT:
+        return cpu.get_latest_value_float(0)
+    else:
+        return None
+
+
+class JitMixin:
+    basic = True
+    def check_loops(self, expected=None, everywhere=False, **check):
+        get_stats().check_loops(expected=expected, everywhere=everywhere,
+                                **check)
+    def check_loop_count(self, count):
+        """NB. This is a hack; use check_tree_loop_count() or
+        check_enter_count() for the real thing.
+        This counts as 1 every bridge in addition to every loop; and it does
+        not count at all the entry bridges from interpreter, although they
+        are TreeLoops as well."""
+        assert get_stats().compiled_count == count
+    def check_tree_loop_count(self, count):
+        assert len(get_stats().loops) == count
+    def check_loop_count_at_most(self, count):
+        assert get_stats().compiled_count <= count
+    def check_enter_count(self, count):
+        assert get_stats().enter_count == count
+    def check_enter_count_at_most(self, count):
+        assert get_stats().enter_count <= count
+    def check_jumps(self, maxcount):
+        assert get_stats().exec_jumps <= maxcount
+    def check_aborted_count(self, count):
+        assert get_stats().aborted_count == count
+    def check_aborted_count_at_least(self, count):
+        assert get_stats().aborted_count >= count
+
+    def meta_interp(self, *args, **kwds):
+        kwds['CPUClass'] = self.CPUClass
+        kwds['type_system'] = self.type_system
+        if "backendopt" not in kwds:
+            kwds["backendopt"] = False
+        return ll_meta_interp(*args, **kwds)
+
+    def interp_operations(self, f, args, **kwds):
+        # get the JitCodes for the function f
+        _get_jitcodes(self, self.CPUClass, f, args, self.type_system, **kwds)
+        # try to run it with blackhole.py
+        result1 = _run_with_blackhole(self, args)
+        # try to run it with pyjitpl.py
+        result2 = _run_with_pyjitpl(self, args)
+        assert result1 == result2
+        # try to run it by running the code compiled just before
+        result3 = _run_with_machine_code(self, args)
+        assert result1 == result3 or result3 == NotImplemented
+        #
+        if (longlong.supports_longlong and
+            isinstance(result1, longlong.r_float_storage)):
+            result1 = longlong.getrealfloat(result1)
+        return result1
+
+    def check_history(self, expected=None, **isns):
+        # this can be used after calling meta_interp
+        get_stats().check_history(expected, **isns)
+
+    def check_operations_history(self, expected=None, **isns):
+        # this can be used after interp_operations
+        if expected is not None:
+            expected = dict(expected)
+            expected['jump'] = 1
+        self.metainterp.staticdata.stats.check_history(expected, **isns)
+
+
+class LLJitMixin(JitMixin):
+    type_system = 'lltype'
+    CPUClass = runner.LLtypeCPU
+
+    @staticmethod
+    def Ptr(T):
+        return lltype.Ptr(T)
+
+    @staticmethod
+    def GcStruct(name, *fields, **kwds):
+        S = lltype.GcStruct(name, *fields, **kwds)
+        return S
+
+    malloc = staticmethod(lltype.malloc)
+    nullptr = staticmethod(lltype.nullptr)
+
+    @staticmethod
+    def malloc_immortal(T):
+        return lltype.malloc(T, immortal=True)
+
+    def _get_NODE(self):
+        NODE = lltype.GcForwardReference()
+        NODE.become(lltype.GcStruct('NODE', ('value', lltype.Signed),
+                                            ('next', lltype.Ptr(NODE))))
+        return NODE
+    
+class OOJitMixin(JitMixin):
+    type_system = 'ootype'
+    #CPUClass = runner.OOtypeCPU
+
+    def setup_class(cls):
+        py.test.skip("ootype tests skipped for now")
+
+    @staticmethod
+    def Ptr(T):
+        return T
+
+    @staticmethod
+    def GcStruct(name, *fields, **kwds):
+        if 'hints' in kwds:
+            kwds['_hints'] = kwds['hints']
+            del kwds['hints']
+        I = ootype.Instance(name, ootype.ROOT, dict(fields), **kwds)
+        return I
+
+    malloc = staticmethod(ootype.new)
+    nullptr = staticmethod(ootype.null)
+
+    @staticmethod
+    def malloc_immortal(T):
+        return ootype.new(T)
+
+    def _get_NODE(self):
+        NODE = ootype.Instance('NODE', ootype.ROOT, {})
+        NODE._add_fields({'value': ootype.Signed,
+                          'next': NODE})
+        return NODE

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

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


diff --git a/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py b/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py
--- a/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py
@@ -277,6 +277,7 @@
         """)
 
     def test_default_and_kw(self):
+        py.test.skip("Wait until we have saner defaults strat")
         def main(n):
             def f(i, j=1):
                 return i + j
@@ -539,7 +540,7 @@
         i12 = int_sub_ovf(i3, 1)
         guard_no_overflow(descr=<Guard5>)
         --TICK--
-        jump(p0, p1, p2, i12, p4, descr=<Loop0>)
+        jump(p0, p1, p2, i12, descr=<Loop0>)
         """)
 
     def test_exception_inside_loop_2(self):
@@ -585,7 +586,7 @@
             --EXC-TICK--
             i14 = int_add(i4, 1)
             --TICK--
-            jump(p0, p1, p2, p3, i14, i5, p6, descr=<Loop0>)
+            jump(p0, p1, p2, p3, i14, i5, descr=<Loop0>)
         """)
 
     def test_chain_of_guards(self):
@@ -685,13 +686,13 @@
         assert log.result == 500
         loop, = log.loops_by_id('import')
         assert loop.match_by_id('import', """
-            p14 = call(ConstClass(ll_split_chr__GcStruct_listLlT_rpy_stringPtr_Char), p8, 46, descr=<GcPtrCallDescr>)
+            p14 = call(ConstClass(ll_split_chr), p8, 46, -1, descr=<GcPtrCallDescr>)
             guard_no_exception(descr=<Guard4>)
             guard_nonnull(p14, descr=<Guard5>)
             i15 = getfield_gc(p14, descr=<SignedFieldDescr list.length .*>)
             i16 = int_is_true(i15)
             guard_true(i16, descr=<Guard6>)
-            p18 = call(ConstClass(ll_pop_default__dum_nocheckConst_listPtr), p14, descr=<GcPtrCallDescr>)
+            p18 = call(ConstClass(ll_pop_default), p14, descr=<GcPtrCallDescr>)
             guard_no_exception(descr=<Guard7>)
             i19 = getfield_gc(p14, descr=<SignedFieldDescr list.length .*>)
             i20 = int_is_true(i19)
@@ -837,7 +838,7 @@
                     src = """
                         def main():
                             sa = 0
-                            for i in range(1000):
+                            for i in range(300):
                                 if i %s %d:
                                     sa += 1
                                 else:
@@ -848,7 +849,7 @@
                                     sa += 20000
                             return sa
                     """ % (op1, a, op2, b)
-                    self.run_and_check(src, threshold=400)
+                    self.run_and_check(src, threshold=200)
 
                     src = """
                         def main():
@@ -866,7 +867,7 @@
                                 i += 0.25
                             return sa
                     """ % (op1, float(a)/4.0, op2, float(b)/4.0)
-                    self.run_and_check(src, threshold=400)
+                    self.run_and_check(src, threshold=300)
 
 
     def test_boolrewrite_allcases_reflex(self):
@@ -887,7 +888,7 @@
                     src = """
                         def main():
                             sa = 0
-                            for i in range(1000):
+                            for i in range(300):
                                 if i %s %d:
                                     sa += 1
                                 else:
@@ -898,7 +899,7 @@
                                     sa += 20000
                             return sa
                     """ % (op1, a, b, op2)
-                    self.run_and_check(src, threshold=400)
+                    self.run_and_check(src, threshold=200)
 
                     src = """
                         def main():
@@ -916,11 +917,13 @@
                                 i += 0.25
                             return sa
                     """ % (op1, float(a)/4.0, float(b)/4.0, op2)
-                    self.run_and_check(src, threshold=400)
+                    self.run_and_check(src, threshold=300)
 
     def test_boolrewrite_ptr(self):
-        # XXX this test is way too imprecise in what it is actually testing
-        # it should count the number of guards instead
+        """
+        This test only checks that we get the expected result, not that any
+        optimization has been applied.
+        """
         compares = ('a == b', 'b == a', 'a != b', 'b != a', 'a == c', 'c != b')
         for e1 in compares:
             for e2 in compares:
@@ -932,7 +935,7 @@
                         b = tst()
                         c = tst()
                         sa = 0
-                        for i in range(1000):
+                        for i in range(300):
                             if %s:
                                 sa += 1
                             else:
@@ -945,7 +948,7 @@
                                 a = b
                         return sa
                 """ % (e1, e2)
-                self.run_and_check(src, threshold=400)
+                self.run_and_check(src, threshold=200)
 
     def test_array_sum(self):
         def main():
@@ -1009,6 +1012,7 @@
         """)
 
     def test_func_defaults(self):
+        py.test.skip("until we fix defaults")
         def main(n):
             i = 1
             while i < n:
@@ -1061,7 +1065,7 @@
             i23 = int_lt(0, i21)
             guard_true(i23, descr=<Guard5>)
             i24 = getfield_gc(p17, descr=<NonGcPtrFieldDescr .*W_ArrayTypei.inst_buffer .*>)
-            i25 = getarrayitem_raw(i24, 0, descr=<SignedArrayNoLengthDescr>)
+            i25 = getarrayitem_raw(i24, 0, descr=<.*>)
             i27 = int_lt(1, i21)
             guard_false(i27, descr=<Guard6>)
             i28 = int_add_ovf(i10, i25)
@@ -1069,7 +1073,7 @@
             --TICK--
             jump(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, i28, i25, i19, i13, p14, p15, descr=<Loop0>)
         """)
-
+        
     def test_mutate_class(self):
         def fn(n):
             class A(object):
@@ -1112,3 +1116,461 @@
             setfield_gc(ConstPtr(ptr21), p20, descr=<GcPtrFieldDescr .*TypeCell.inst_w_value .*>)
             jump(p0, p1, p2, p3, p4, p20, p6, i7, descr=<Loop.>)
         """)
+
+
+    def test_intbound_simple(self):
+        """
+        This test only checks that we get the expected result, not that any
+        optimization has been applied.
+        """
+        ops = ('<', '>', '<=', '>=', '==', '!=')
+        nbr = (3, 7)
+        for o1 in ops:
+            for o2 in ops:
+                for n1 in nbr:
+                    for n2 in nbr:
+                        src = '''
+                        def f(i):
+                            a, b = 3, 3
+                            if i %s %d:
+                                a = 0
+                            else:
+                                a = 1
+                            if i %s %d:
+                                b = 0
+                            else:
+                                b = 1
+                            return a + b * 2
+
+                        def main():
+                            res = [0] * 4
+                            idx = []
+                            for i in range(15):
+                                idx.extend([i] * 15)
+                            for i in idx:
+                                res[f(i)] += 1
+                            return res
+
+                        ''' % (o1, n1, o2, n2)
+                        self.run_and_check(src, threshold=200)
+
+    def test_intbound_addsub_mix(self):
+        """
+        This test only checks that we get the expected result, not that any
+        optimization has been applied.
+        """
+        tests = ('i > 4', 'i > 2', 'i + 1 > 2', '1 + i > 4',
+                 'i - 1 > 1', '1 - i > 1', '1 - i < -3',
+                 'i == 1', 'i == 5', 'i != 1', '-2 * i < -4')
+        for t1 in tests:
+            for t2 in tests:
+                src = '''
+                def f(i):
+                    a, b = 3, 3
+                    if %s:
+                        a = 0
+                    else:
+                        a = 1
+                    if %s:
+                        b = 0
+                    else:
+                        b = 1
+                    return a + b * 2
+
+                def main():
+                    res = [0] * 4
+                    idx = []
+                    for i in range(15):
+                        idx.extend([i] * 15)
+                    for i in idx:
+                        res[f(i)] += 1
+                    return res
+
+                ''' % (t1, t2)
+                self.run_and_check(src, threshold=200)
+
+    def test_intbound_gt(self):
+        def main(n):
+            i, a, b = 0, 0, 0
+            while i < n:
+                if i > -1:
+                    a += 1
+                if i > -2:
+                    b += 1
+                i += 1
+            return (a, b)
+        #
+        log = self.run(main, [300], threshold=200)
+        assert log.result == (300, 300)
+        loop, = log.loops_by_filename(self.filepath)
+        assert loop.match("""
+            i10 = int_lt(i8, i9)
+            guard_true(i10, descr=...)
+            i12 = int_add_ovf(i7, 1)
+            guard_no_overflow(descr=...)
+            i14 = int_add_ovf(i6, 1)
+            guard_no_overflow(descr=...)
+            i17 = int_add(i8, 1)
+            --TICK--
+            jump(p0, p1, p2, p3, p4, p5, i14, i12, i17, i9, descr=<Loop0>)
+        """)
+
+    def test_intbound_sub_lt(self):
+        def main():
+            i, a = 0, 0
+            while i < 300:
+                if i - 10 < 295:
+                    a += 1
+                i += 1
+            return a
+        #
+        log = self.run(main, [], threshold=200)
+        assert log.result == 300
+        loop, = log.loops_by_filename(self.filepath)
+        assert loop.match("""
+            i7 = int_lt(i5, 300)
+            guard_true(i7, descr=...)
+            i9 = int_sub_ovf(i5, 10)
+            guard_no_overflow(descr=...)
+            i11 = int_add_ovf(i4, 1)
+            guard_no_overflow(descr=...)
+            i13 = int_add(i5, 1)
+            --TICK--
+            jump(p0, p1, p2, p3, i11, i13, descr=<Loop0>)
+        """)
+
+    def test_intbound_addsub_ge(self):
+        def main(n):
+            i, a, b = 0, 0, 0
+            while i < n:
+                if i + 5 >= 5:
+                    a += 1
+                if i - 1 >= -1:
+                    b += 1
+                i += 1
+            return (a, b)
+        #
+        log = self.run(main, [300], threshold=200)
+        assert log.result == (300, 300)
+        loop, = log.loops_by_filename(self.filepath)
+        assert loop.match("""
+            i10 = int_lt(i8, i9)
+            guard_true(i10, descr=...)
+            i12 = int_add_ovf(i8, 5)
+            guard_no_overflow(descr=...)
+            i14 = int_add_ovf(i7, 1)
+            guard_no_overflow(descr=...)
+            i16 = int_add_ovf(i6, 1)
+            guard_no_overflow(descr=...)
+            i19 = int_add(i8, 1)
+            --TICK--
+            jump(p0, p1, p2, p3, p4, p5, i16, i14, i19, i9, descr=<Loop0>)
+        """)
+
+    def test_intbound_addmul_ge(self):
+        def main(n):
+            i, a, b = 0, 0, 0
+            while i < 300:
+                if i + 5 >= 5:
+                    a += 1
+                if 2 * i >= 0:
+                    b += 1
+                i += 1
+            return (a, b)
+        #
+        log = self.run(main, [300], threshold=200)
+        assert log.result == (300, 300)
+        loop, = log.loops_by_filename(self.filepath)
+        assert loop.match("""
+            i10 = int_lt(i8, 300)
+            guard_true(i10, descr=...)
+            i12 = int_add(i8, 5)
+            i14 = int_add_ovf(i7, 1)
+            guard_no_overflow(descr=...)
+            i16 = int_lshift(i8, 1)
+            i18 = int_add_ovf(i6, 1)
+            guard_no_overflow(descr=...)
+            i21 = int_add(i8, 1)
+            --TICK--
+            jump(p0, p1, p2, p3, p4, p5, i18, i14, i21, descr=<Loop0>)
+        """)
+
+    def test_intbound_eq(self):
+        def main(a, n):
+            i, s = 0, 0
+            while i < 300:
+                if a == 7:
+                    s += a + 1
+                elif i == 10:
+                    s += i
+                else:
+                    s += 1
+                i += 1
+            return s
+        #
+        log = self.run(main, [7, 300], threshold=200)
+        assert log.result == main(7, 300)
+        log = self.run(main, [10, 300], threshold=200)
+        assert log.result == main(10, 300)
+        log = self.run(main, [42, 300], threshold=200)
+        assert log.result == main(42, 300)
+        loop, = log.loops_by_filename(self.filepath)
+        assert loop.match("""
+            i10 = int_lt(i8, 300)
+            guard_true(i10, descr=...)
+            i12 = int_eq(i8, 10)
+            guard_false(i12, descr=...)
+            i14 = int_add_ovf(i7, 1)
+            guard_no_overflow(descr=...)
+            i16 = int_add(i8, 1)
+            --TICK--
+            jump(p0, p1, p2, p3, p4, p5, p6, i14, i16, descr=<Loop0>)
+        """)
+
+    def test_intbound_mul(self):
+        def main(a):
+            i, s = 0, 0
+            while i < 300:
+                assert i >= 0
+                if 2 * i < 30000:
+                    s += 1
+                else:
+                    s += a
+                i += 1
+            return s
+        #
+        log = self.run(main, [7], threshold=200)
+        assert log.result == 300
+        loop, = log.loops_by_filename(self.filepath)
+        assert loop.match("""
+            i8 = int_lt(i6, 300)
+            guard_true(i8, descr=...)
+            i10 = int_lshift(i6, 1)
+            i12 = int_add_ovf(i5, 1)
+            guard_no_overflow(descr=...)
+            i14 = int_add(i6, 1)
+            --TICK--
+            jump(p0, p1, p2, p3, p4, i12, i14, descr=<Loop0>)
+        """)
+
+    def test_assert(self):
+        def main(a):
+            i, s = 0, 0
+            while i < 300:
+                assert a == 7
+                s += a + 1
+                i += 1
+            return s
+        log = self.run(main, [7], threshold=200)
+        assert log.result == 300*8
+        loop, = log.loops_by_filename(self.filepath)
+        assert loop.match("""
+            i8 = int_lt(i6, 300)
+            guard_true(i8, descr=...)
+            i10 = int_add_ovf(i5, 8)
+            guard_no_overflow(descr=...)
+            i12 = int_add(i6, 1)
+            --TICK--
+            jump(p0, p1, p2, p3, p4, i10, i12, descr=<Loop0>)
+        """)
+
+    def test_zeropadded(self):
+        def main():
+            from array import array
+            class ZeroPadded(array):
+                def __new__(cls, l):
+                    self = array.__new__(cls, 'd', range(l))
+                    return self
+
+                def __getitem__(self, i):
+                    if i < 0 or i >= len(self):
+                        return 0
+                    return array.__getitem__(self, i) # ID: get
+            #
+            buf = ZeroPadded(2000)
+            i = 10
+            sa = 0
+            while i < 2000 - 10:
+                sa += buf[i-2] + buf[i-1] + buf[i] + buf[i+1] + buf[i+2]
+                i += 1
+            return sa
+
+        log = self.run(main, [], threshold=200)
+        assert log.result == 9895050.0
+        loop, = log.loops_by_filename(self.filepath)
+        #
+        # check that the overloaded __getitem__ does not introduce double
+        # array bound checks.
+        #
+        # The force_token()s are still there, but will be eliminated by the
+        # backend regalloc, so they are harmless
+        assert loop.match(ignore_ops=['force_token'],
+                          expected_src="""
+            ...
+            i20 = int_ge(i18, i8)
+            guard_false(i20, descr=...)
+            f21 = getarrayitem_raw(i13, i18, descr=...)
+            f23 = getarrayitem_raw(i13, i14, descr=...)
+            f24 = float_add(f21, f23)
+            f26 = getarrayitem_raw(i13, i6, descr=...)
+            f27 = float_add(f24, f26)
+            i29 = int_add(i6, 1)
+            i31 = int_ge(i29, i8)
+            guard_false(i31, descr=...)
+            f33 = getarrayitem_raw(i13, i29, descr=...)
+            f34 = float_add(f27, f33)
+            i36 = int_add(i6, 2)
+            i38 = int_ge(i36, i8)
+            guard_false(i38, descr=...)
+            f39 = getarrayitem_raw(i13, i36, descr=...)
+            ...
+        """)
+
+
+    def test_circular(self):
+        def main():
+            from array import array
+            class Circular(array):
+                def __new__(cls):
+                    self = array.__new__(cls, 'd', range(256))
+                    return self
+                def __getitem__(self, i):
+                    assert len(self) == 256
+                    return array.__getitem__(self, i & 255)
+            #
+            buf = Circular()
+            i = 10
+            sa = 0
+            while i < 2000 - 10:
+                sa += buf[i-2] + buf[i-1] + buf[i] + buf[i+1] + buf[i+2]
+                i += 1
+            return sa
+        #
+        log = self.run(main, [], threshold=200)
+        assert log.result == 1239690.0
+        loop, = log.loops_by_filename(self.filepath)
+        #
+        # check that the array bound checks are removed
+        #
+        # The force_token()s are still there, but will be eliminated by the
+        # backend regalloc, so they are harmless
+        assert loop.match(ignore_ops=['force_token'],
+                          expected_src="""
+            ...
+            i17 = int_and(i14, 255)
+            f18 = getarrayitem_raw(i8, i17, descr=...)
+            f20 = getarrayitem_raw(i8, i9, descr=...)
+            f21 = float_add(f18, f20)
+            f23 = getarrayitem_raw(i8, i10, descr=...)
+            f24 = float_add(f21, f23)
+            i26 = int_add(i6, 1)
+            i29 = int_and(i26, 255)
+            f30 = getarrayitem_raw(i8, i29, descr=...)
+            f31 = float_add(f24, f30)
+            i33 = int_add(i6, 2)
+            i36 = int_and(i33, 255)
+            f37 = getarrayitem_raw(i8, i36, descr=...)
+            ...
+        """)
+
+    def test_min_max(self):
+        def main():
+            i=0
+            sa=0
+            while i < 300: 
+                sa+=min(max(i, 3000), 4000)
+                i+=1
+            return sa
+        log = self.run(main, [], threshold=200)
+        assert log.result == 300*3000
+        loop, = log.loops_by_filename(self.filepath)
+        assert loop.match("""
+            i7 = int_lt(i4, 300)
+            guard_true(i7, descr=...)
+            i9 = int_add_ovf(i5, 3000)
+            guard_no_overflow(descr=...)
+            i11 = int_add(i4, 1)
+            --TICK--
+            jump(p0, p1, p2, p3, i11, i9, descr=<Loop0>)
+        """)
+
+    def test_silly_max(self):
+        def main():
+            i = 2
+            sa = 0
+            while i < 300:
+                lst = range(i)
+                sa += max(*lst) # ID: max
+                i += 1
+            return sa
+        log = self.run(main, [], threshold=200)
+        assert log.result == main()
+        loop, = log.loops_by_filename(self.filepath)
+        # We dont want too many guards, but a residual call to min_max_loop
+        guards = [n for n in log.opnames(loop.ops_by_id("max")) if n.startswith('guard')]
+        assert len(guards) < 20
+        assert loop.match_by_id('max',"""
+            ...
+            p76 = call_may_force(ConstClass(min_max_loop__max), _, _, descr=...)
+            ...
+        """)
+        
+    def test_iter_max(self):
+        def main():
+            i = 2
+            sa = 0
+            while i < 300:
+                lst = range(i)
+                sa += max(lst) # ID: max
+                i += 1
+            return sa
+        log = self.run(main, [], threshold=200)
+        assert log.result == main()
+        loop, = log.loops_by_filename(self.filepath)
+        # We dont want too many guards, but a residual call to min_max_loop
+        guards = [n for n in log.opnames(loop.ops_by_id("max")) if n.startswith('guard')]
+        assert len(guards) < 20
+        assert loop.match_by_id('max',"""
+            ...
+            p76 = call_may_force(ConstClass(min_max_loop__max), _, _, descr=...)            
+            ...
+        """)
+
+    def test__ffi_call(self):
+        from pypy.rlib.test.test_libffi import get_libm_name
+        def main(libm_name):
+            try:
+                from _ffi import CDLL, types
+            except ImportError:
+                sys.stderr.write('SKIP: cannot import _ffi\n')
+                return 0
+
+            libm = CDLL(libm_name)
+            pow = libm.getfunc('pow', [types.double, types.double],
+                               types.double)
+            i = 0
+            res = 0
+            while i < 300:
+                res += pow(2, 3)
+                i += 1
+            return pow.getaddr(), res
+        #
+        libm_name = get_libm_name(sys.platform)
+        log = self.run(main, [libm_name], threshold=200)
+        pow_addr, res = log.result
+        assert res == 8.0 * 300
+        loop, = log.loops_by_filename(self.filepath)
+        # XXX: write the actual test when we merge this to jitypes2
+        ## ops = self.get_by_bytecode('CALL_FUNCTION')
+        ## assert len(ops) == 2 # we get two loops, because of specialization
+        ## call_function = ops[0]
+        ## last_ops = [op.getopname() for op in call_function[-5:]]
+        ## assert last_ops == ['force_token',
+        ##                     'setfield_gc',
+        ##                     'call_may_force',
+        ##                     'guard_not_forced',
+        ##                     'guard_no_exception']
+        ## call = call_function[-3]
+        ## assert call.getarg(0).value == pow_addr
+        ## assert call.getarg(1).value == 2.0
+        ## assert call.getarg(2).value == 3.0

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

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

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

diff --git a/pypy/jit/metainterp/test/test_tlc.py b/pypy/jit/metainterp/test/test_tlc.py
--- a/pypy/jit/metainterp/test/test_tlc.py
+++ b/pypy/jit/metainterp/test/test_tlc.py
@@ -3,7 +3,7 @@
 
 from pypy.jit.tl import tlc
 
-from pypy.jit.metainterp.test.test_basic import OOJitMixin, LLJitMixin
+from pypy.jit.metainterp.test.support import OOJitMixin, LLJitMixin
 
 
 class TLCTests:

diff --git a/pypy/module/cpyext/test/test_cpyext.py b/pypy/module/cpyext/test/test_cpyext.py
--- a/pypy/module/cpyext/test/test_cpyext.py
+++ b/pypy/module/cpyext/test/test_cpyext.py
@@ -106,6 +106,11 @@
             del obj
         import gc; gc.collect()
 
+        try:
+            del space.getexecutioncontext().cpyext_threadstate
+        except AttributeError:
+            pass
+
         for w_obj in state.non_heaptypes_w:
             Py_DecRef(space, w_obj)
         state.non_heaptypes_w[:] = []

diff --git a/pypy/jit/metainterp/test/test_slist.py b/pypy/jit/metainterp/test/test_slist.py
--- a/pypy/jit/metainterp/test/test_slist.py
+++ b/pypy/jit/metainterp/test/test_slist.py
@@ -1,5 +1,5 @@
 import py
-from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
+from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
 from pypy.rlib.jit import JitDriver
 
 class ListTests(object):

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

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

diff --git a/pypy/rpython/rpbc.py b/pypy/rpython/rpbc.py
--- a/pypy/rpython/rpbc.py
+++ b/pypy/rpython/rpbc.py
@@ -485,7 +485,7 @@
                 try:
                     thisattrvalue = frozendesc.attrcache[attr]
                 except KeyError:
-                    if not frozendesc.has_attribute(attr):
+                    if frozendesc.warn_missing_attribute(attr):
                         warning("Desc %r has no attribute %r" % (frozendesc, attr))
                     continue
                 llvalue = r_value.convert_const(thisattrvalue)

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

diff --git a/pypy/jit/metainterp/test/test_dlist.py b/pypy/jit/metainterp/test/test_dlist.py
deleted file mode 100644
--- a/pypy/jit/metainterp/test/test_dlist.py
+++ /dev/null
@@ -1,165 +0,0 @@
-
-import py
-from pypy.rlib.jit import JitDriver
-from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
-py.test.skip("Disabled")
-
-class ListTests:
-    def test_basic(self):
-        myjitdriver = JitDriver(greens = [], reds = ['n', 'l'])
-        def f(n):
-            l = [0]
-            while n > 0:
-                myjitdriver.can_enter_jit(n=n, l=l)
-                myjitdriver.jit_merge_point(n=n, l=l)
-                x = l[0]
-                l[0] = x + 1
-                n -= 1
-            return l[0]
-
-        res = self.meta_interp(f, [10], listops=True)
-        assert res == f(10)        
-        self.check_loops(getarrayitem_gc=0, setarrayitem_gc=1)
-#                         XXX fix codewriter
-#                         guard_exception=0,
-#                         guard_no_exception=1)
-
-    def test_list_escapes(self):
-        myjitdriver = JitDriver(greens = [], reds = ['n', 'l'])
-        def f(n):
-            l = [0] * (n + 1)
-            while n > 0:
-                myjitdriver.can_enter_jit(n=n, l=l)
-                myjitdriver.jit_merge_point(n=n, l=l)
-                x = l[0]
-                l[0] = x + 1
-                l[n] = n
-                n -= 1
-            return l[3]
-
-        res = self.meta_interp(f, [10], listops=True)
-        assert res == f(10)
-        self.check_loops(setarrayitem_gc=2, getarrayitem_gc=0)
-
-    def test_list_escapes_but_getitem_goes(self):
-        myjitdriver = JitDriver(greens = [], reds = ['n', 'l'])
-        def f(n):
-            l = [0] * (n + 1)
-            while n > 0:
-                myjitdriver.can_enter_jit(n=n, l=l)
-                myjitdriver.jit_merge_point(n=n, l=l)
-                x = l[0]
-                l[0] = x + 1
-                l[n] = n
-                x = l[2]
-                y = l[1] + l[2]
-                l[1] = x + y
-                n -= 1
-            return l[3]
-
-        res = self.meta_interp(f, [10], listops=True)
-        assert res == f(10)
-        self.check_loops(setarrayitem_gc=3, getarrayitem_gc=0)
-
-    def test_list_of_ptrs(self):
-        myjitdriver = JitDriver(greens = [], reds = ['n', 'l'])
-        class A(object):
-            def __init__(self, x):
-                self.x = x
-
-        def f(n):
-            l = [A(3)]
-            while n > 0:
-                myjitdriver.can_enter_jit(n=n, l=l)
-                myjitdriver.jit_merge_point(n=n, l=l)
-                x = l[0].x + 1
-                l[0] = A(x)
-                n -= 1
-            return l[0].x
-
-        res = self.meta_interp(f, [10], listops=True)
-        assert res == f(10)
-        self.check_loops(setarrayitem_gc=1, getarrayitem_gc=0,
-                         new_with_vtable=1) # A should escape
-
-    def test_list_checklength(self):
-        myjitdriver = JitDriver(greens = [], reds = ['n', 'l'])
-
-        def f(n, a):
-            l = [0] * a
-            while n > 0:
-                myjitdriver.can_enter_jit(n=n, l=l)
-                myjitdriver.jit_merge_point(n=n, l=l)
-                if len(l) < 3:
-                    return 42
-                l[0] = n
-                n -= 1
-            return l[0]
-
-        res = self.meta_interp(f, [10, 13], listops=True)
-        assert res == f(10, 13)
-        self.check_loops(setarrayitem_gc=1, arraylen_gc=1)
-
-    def test_list_checklength_run(self):
-        myjitdriver = JitDriver(greens = [], reds = ['n', 'l'])
-
-        def f(n, a):
-            l = [0] * a
-            while n > 0:
-                myjitdriver.can_enter_jit(n=n, l=l)
-                myjitdriver.jit_merge_point(n=n, l=l)
-                if len(l) > n:
-                    return 42
-                l[0] = n
-                n -= 1
-            return l[0]
-
-        res = self.meta_interp(f, [50, 13], listops=True)
-        assert res == 42
-        self.check_loops(setarrayitem_gc=1, arraylen_gc=1)
-
-    def test_checklength_cannot_go_away(self):
-        myjitdriver = JitDriver(greens = [], reds = ['n', 'l'])
-
-        def f(n):
-            l = [0] * n
-            while n > 0:
-                myjitdriver.can_enter_jit(n=n, l=l)
-                myjitdriver.jit_merge_point(n=n, l=l)
-                if len(l) < 3:
-                    return len(l)
-                l = [0] * n
-                n -= 1
-            return 0
-
-        res = self.meta_interp(f, [10], listops=True)
-        assert res == 2
-        self.check_loops(arraylen_gc=1)
-
-    def test_list_indexerror(self):
-        # this is an example where IndexError is raised before
-        # even getting to the JIT
-        py.test.skip("I suspect bug somewhere outside of the JIT")
-        myjitdriver = JitDriver(greens = [], reds = ['n', 'l'])
-        def f(n):
-            l = [0]
-            while n > 0:
-                myjitdriver.can_enter_jit(n=n, l=l)
-                myjitdriver.jit_merge_point(n=n, l=l)
-                l[n] = n
-                n -= 1
-            return l[3]
-
-        def g(n):
-            try:
-                f(n)
-                return 0
-            except IndexError:
-                return 42
-
-        res = self.meta_interp(g, [10])
-        assert res == 42
-        self.check_loops(setitem=2)
-
-class TestLLtype(ListTests, LLJitMixin):
-    pass

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

diff --git a/pypy/rlib/rsre/test/test_zjit.py b/pypy/rlib/rsre/test/test_zjit.py
--- a/pypy/rlib/rsre/test/test_zjit.py
+++ b/pypy/rlib/rsre/test/test_zjit.py
@@ -1,5 +1,5 @@
 import py
-from pypy.jit.metainterp.test import test_basic
+from pypy.jit.metainterp.test import support
 from pypy.rlib.nonconst import NonConstant
 from pypy.rlib.rsre.test.test_match import get_code
 from pypy.rlib.rsre import rsre_core
@@ -45,7 +45,7 @@
         assert m._jit_unroll_safe_
 
 
-class TestJitRSre(test_basic.LLJitMixin):
+class TestJitRSre(support.LLJitMixin):
 
     def meta_interp_match(self, pattern, string, repeat=1):
         r = get_code(pattern)

diff --git a/pypy/module/cpyext/stubs.py b/pypy/module/cpyext/stubs.py
--- a/pypy/module/cpyext/stubs.py
+++ b/pypy/module/cpyext/stubs.py
@@ -351,14 +351,6 @@
     """Return the number of free variables in co."""
     raise NotImplementedError
 
- at cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real, PyObject, PyObject, PyObject, PyObject, PyObject, PyObject, PyObject, PyObject, rffi.INT_real, PyObject], PyCodeObject)
-def PyCode_New(space, argcount, nlocals, stacksize, flags, code, consts, names, varnames, freevars, cellvars, filename, name, firstlineno, lnotab):
-    """Return a new code object.  If you need a dummy code object to
-    create a frame, use PyCode_NewEmpty() instead.  Calling
-    PyCode_New() directly can bind you to a precise Python
-    version since the definition of the bytecode changes often."""
-    raise NotImplementedError
-
 @cpython_api([PyObject], rffi.INT_real, error=-1)
 def PyCodec_Register(space, search_function):
     """Register a new codec search function.
@@ -1116,20 +1108,6 @@
     with an exception set on failure (the module still exists in this case)."""
     raise NotImplementedError
 
- at cpython_api([rffi.CCHARP], PyObject)
-def PyImport_AddModule(space, name):
-    """Return the module object corresponding to a module name.  The name argument
-    may be of the form package.module. First check the modules dictionary if
-    there's one there, and if not, create a new one and insert it in the modules
-    dictionary. Return NULL with an exception set on failure.
-    
-    This function does not load or import the module; if the module wasn't already
-    loaded, you will get an empty module object. Use PyImport_ImportModule()
-    or one of its variants to import a module.  Package structures implied by a
-    dotted name for name are not created if not already present."""
-    borrow_from()
-    raise NotImplementedError
-
 @cpython_api([rffi.CCHARP, PyObject], PyObject)
 def PyImport_ExecCodeModule(space, name, co):
     """Given a module name (possibly of the form package.module) and a code
@@ -1965,14 +1943,6 @@
     """
     raise NotImplementedError
 
- at cpython_api([PyObject, PyObject, rffi.INTP], rffi.INT_real, error=-1)
-def PyObject_Cmp(space, o1, o2, result):
-    """Compare the values of o1 and o2 using a routine provided by o1, if one
-    exists, otherwise with a routine provided by o2.  The result of the
-    comparison is returned in result.  Returns -1 on failure.  This is the
-    equivalent of the Python statement result = cmp(o1, o2)."""
-    raise NotImplementedError
-
 @cpython_api([PyObject], PyObject)
 def PyObject_Bytes(space, o):
     """Compute a bytes representation of object o.  In 2.x, this is just a alias

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

diff --git a/pypy/module/pypyjit/test_pypy_c/test_model.py b/pypy/module/pypyjit/test_pypy_c/test_model.py
--- a/pypy/module/pypyjit/test_pypy_c/test_model.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_model.py
@@ -52,6 +52,8 @@
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE)
         stdout, stderr = pipe.communicate()
+        if stderr.startswith('SKIP:'):
+            py.test.skip(stderr)
         assert not stderr
         #
         # parse the JIT log
@@ -100,11 +102,11 @@
 
 class TestOpMatcher(object):
 
-    def match(self, src1, src2):
+    def match(self, src1, src2, **kwds):
         from pypy.tool.jitlogparser.parser import SimpleParser
         loop = SimpleParser.parse_from_input(src1)
         matcher = OpMatcher(loop.operations, src=src1)
-        return matcher.match(src2)
+        return matcher.match(src2, **kwds)
 
     def test_match_var(self):
         match_var = OpMatcher([]).match_var
@@ -234,6 +236,21 @@
         """
         assert self.match(loop, expected)
 
+    def test_ignore_opcodes(self):
+        loop = """
+            [i0]
+            i1 = int_add(i0, 1)
+            i4 = force_token()
+            i2 = int_sub(i1, 10)
+            jump(i4)
+        """
+        expected = """
+            i1 = int_add(i0, 1)
+            i2 = int_sub(i1, 10)
+            jump(i4, descr=...)
+        """
+        assert self.match(loop, expected, ignore_ops=['force_token'])
+
 
 class TestRunPyPyC(BaseTestPyPyC):
 
@@ -253,6 +270,14 @@
         log = self.run(src, [30, 12])
         assert log.result == 42
 
+    def test_skip(self):
+        import pytest
+        def f():
+            import sys
+            print >> sys.stderr, 'SKIP: foobar'
+        #
+        raises(pytest.skip.Exception, "self.run(f, [])")
+
     def test_parse_jitlog(self):
         def f():
             i = 0

diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -37,7 +37,7 @@
 DEBUG_WRAPPER = True
 
 # update these for other platforms
-Py_ssize_t = lltype.Signed
+Py_ssize_t = lltype.Typedef(rffi.SSIZE_T, 'Py_ssize_t')
 Py_ssize_tP = rffi.CArrayPtr(Py_ssize_t)
 size_t = rffi.ULONG
 ADDR = lltype.Signed
@@ -192,14 +192,19 @@
     - set `external` to False to get a C function pointer, but not exported by
       the API headers.
     """
+    if isinstance(restype, lltype.Typedef):
+        real_restype = restype.OF
+    else:
+        real_restype = restype
+
     if error is _NOT_SPECIFIED:
-        if isinstance(restype, lltype.Ptr):
-            error = lltype.nullptr(restype.TO)
-        elif restype is lltype.Void:
+        if isinstance(real_restype, lltype.Ptr):
+            error = lltype.nullptr(real_restype.TO)
+        elif real_restype is lltype.Void:
             error = CANNOT_FAIL
     if type(error) is int:
-        error = rffi.cast(restype, error)
-    expect_integer = (isinstance(restype, lltype.Primitive) and
+        error = rffi.cast(real_restype, error)
+    expect_integer = (isinstance(real_restype, lltype.Primitive) and
                       rffi.cast(restype, 0) == 0)
 
     def decorate(func):
@@ -400,21 +405,9 @@
 # So we need a forward and backward mapping in our State instance
 PyObjectStruct = lltype.ForwardReference()
 PyObject = lltype.Ptr(PyObjectStruct)
-PyBufferProcs = lltype.ForwardReference()
 PyObjectFields = (("ob_refcnt", lltype.Signed), ("ob_type", PyTypeObjectPtr))
-def F(ARGS, RESULT=lltype.Signed):
-    return lltype.Ptr(lltype.FuncType(ARGS, RESULT))
-PyBufferProcsFields = (
-    ("bf_getreadbuffer", F([PyObject, lltype.Signed, rffi.VOIDPP])),
-    ("bf_getwritebuffer", F([PyObject, lltype.Signed, rffi.VOIDPP])),
-    ("bf_getsegcount", F([PyObject, rffi.INTP])),
-    ("bf_getcharbuffer", F([PyObject, lltype.Signed, rffi.CCHARPP])),
-# we don't support new buffer interface for now
-    ("bf_getbuffer", rffi.VOIDP),
-    ("bf_releasebuffer", rffi.VOIDP))
 PyVarObjectFields = PyObjectFields + (("ob_size", Py_ssize_t), )
 cpython_struct('PyObject', PyObjectFields, PyObjectStruct)
-cpython_struct('PyBufferProcs', PyBufferProcsFields, PyBufferProcs)
 PyVarObjectStruct = cpython_struct("PyVarObject", PyVarObjectFields)
 PyVarObject = lltype.Ptr(PyVarObjectStruct)
 
@@ -539,7 +532,8 @@
 
             elif is_PyObject(callable.api_func.restype):
                 if result is None:
-                    retval = make_ref(space, None)
+                    retval = rffi.cast(callable.api_func.restype,
+                                       make_ref(space, None))
                 elif isinstance(result, Reference):
                     retval = result.get_ref(space)
                 elif not rffi._isllptr(result):

diff --git a/pypy/rpython/lltypesystem/ll2ctypes.py b/pypy/rpython/lltypesystem/ll2ctypes.py
--- a/pypy/rpython/lltypesystem/ll2ctypes.py
+++ b/pypy/rpython/lltypesystem/ll2ctypes.py
@@ -255,6 +255,9 @@
         return cls
 
 def build_new_ctypes_type(T, delayed_builders):
+    if isinstance(T, lltype.Typedef):
+        T = T.OF
+
     if isinstance(T, lltype.Ptr):
         if isinstance(T.TO, lltype.FuncType):
             argtypes = [get_ctypes_type(ARG) for ARG in T.TO.ARGS
@@ -758,6 +761,8 @@
     """
     if T is lltype.Void:
         return None
+    if isinstance(T, lltype.Typedef):
+        T = T.OF
     if isinstance(T, lltype.Ptr):
         if not cobj or not ctypes.cast(cobj, ctypes.c_void_p).value:   # NULL pointer
             # CFunctionType.__nonzero__ is broken before Python 2.6

diff --git a/pypy/module/cpyext/typeobject.py b/pypy/module/cpyext/typeobject.py
--- a/pypy/module/cpyext/typeobject.py
+++ b/pypy/module/cpyext/typeobject.py
@@ -7,10 +7,10 @@
 from pypy.objspace.std.typeobject import W_TypeObject
 from pypy.interpreter.typedef import GetSetProperty
 from pypy.module.cpyext.api import (
-    cpython_api, cpython_struct, bootstrap_function, Py_ssize_t,
+    cpython_api, cpython_struct, bootstrap_function, Py_ssize_t, Py_ssize_tP,
     generic_cpy_call, Py_TPFLAGS_READY, Py_TPFLAGS_READYING,
     Py_TPFLAGS_HEAPTYPE, METH_VARARGS, METH_KEYWORDS, CANNOT_FAIL,
-    PyBufferProcs, build_type_checkers)
+    build_type_checkers)
 from pypy.module.cpyext.pyobject import (
     PyObject, make_ref, create_ref, from_ref, get_typedescr, make_typedescr,
     track_reference, RefcountState, borrow_from)
@@ -24,7 +24,7 @@
 from pypy.module.cpyext.structmember import PyMember_GetOne, PyMember_SetOne
 from pypy.module.cpyext.typeobjectdefs import (
     PyTypeObjectPtr, PyTypeObject, PyGetSetDef, PyMemberDef, newfunc,
-    PyNumberMethods, PySequenceMethods)
+    PyNumberMethods, PySequenceMethods, PyBufferProcs)
 from pypy.module.cpyext.slotdefs import (
     slotdefs_for_tp_slots, slotdefs_for_wrappers, get_slot_tp_function)
 from pypy.interpreter.error import OperationError
@@ -361,14 +361,14 @@
     # hopefully this does not clash with the memory model assumed in
     # extension modules
 
- at cpython_api([PyObject, rffi.INTP], lltype.Signed, external=False,
+ at cpython_api([PyObject, Py_ssize_tP], lltype.Signed, external=False,
              error=CANNOT_FAIL)
 def str_segcount(space, w_obj, ref):
     if ref:
-        ref[0] = rffi.cast(rffi.INT, space.len_w(w_obj))
+        ref[0] = space.len_w(w_obj)
     return 1
 
- at cpython_api([PyObject, lltype.Signed, rffi.VOIDPP], lltype.Signed,
+ at cpython_api([PyObject, Py_ssize_t, rffi.VOIDPP], lltype.Signed,
              external=False, error=-1)
 def str_getreadbuffer(space, w_str, segment, ref):
     from pypy.module.cpyext.stringobject import PyString_AsString
@@ -381,7 +381,7 @@
     Py_DecRef(space, pyref)
     return space.len_w(w_str)
 
- at cpython_api([PyObject, lltype.Signed, rffi.CCHARPP], lltype.Signed,
+ at cpython_api([PyObject, Py_ssize_t, rffi.CCHARPP], lltype.Signed,
              external=False, error=-1)
 def str_getcharbuffer(space, w_str, segment, ref):
     from pypy.module.cpyext.stringobject import PyString_AsString

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


diff --git a/pypy/objspace/std/dictmultiobject.py b/pypy/objspace/std/dictmultiobject.py
--- a/pypy/objspace/std/dictmultiobject.py
+++ b/pypy/objspace/std/dictmultiobject.py
@@ -798,7 +798,6 @@
         return w_default
 
 def dict_setdefault__DictMulti_ANY_ANY(space, w_dict, w_key, w_default):
-    # XXX should be more efficient, with only one dict lookup
     return w_dict.setdefault(w_key, w_default)
 
 def dict_pop__DictMulti_ANY(space, w_dict, w_key, defaults_w):

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

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

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

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

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

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

diff --git a/pypy/jit/backend/cli/test/test_basic.py b/pypy/jit/backend/cli/test/test_basic.py
--- a/pypy/jit/backend/cli/test/test_basic.py
+++ b/pypy/jit/backend/cli/test/test_basic.py
@@ -1,14 +1,14 @@
 import py
 from pypy.jit.backend.cli.runner import CliCPU
-from pypy.jit.metainterp.test import test_basic
+from pypy.jit.metainterp.test import support, test_ajit
 
-class CliJitMixin(test_basic.OOJitMixin):
+class CliJitMixin(suport.OOJitMixin):
     CPUClass = CliCPU
     def setup_class(cls):
         from pypy.translator.cli.support import PythonNet
         PythonNet.System     # possibly raises Skip
 
-class TestBasic(CliJitMixin, test_basic.TestOOtype):
+class TestBasic(CliJitMixin, test_ajit.TestOOtype):
     # for the individual tests see
     # ====> ../../../metainterp/test/test_basic.py
 

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

diff --git a/pypy/jit/metainterp/test/test_tl.py b/pypy/jit/metainterp/test/test_tl.py
--- a/pypy/jit/metainterp/test/test_tl.py
+++ b/pypy/jit/metainterp/test/test_tl.py
@@ -1,6 +1,6 @@
 import py
 from pypy.jit.codewriter.policy import StopAtXPolicy
-from pypy.jit.metainterp.test.test_basic import OOJitMixin, LLJitMixin
+from pypy.jit.metainterp.test.support import OOJitMixin, LLJitMixin
 
 
 class ToyLanguageTests:

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

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


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


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

diff --git a/pypy/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
@@ -1007,7 +1007,8 @@
 
 class AppTestPyPyExtension(object):
     def setup_class(cls):
-        cls.space = gettestobjspace(usemodules=['imp', 'zipimport'])
+        cls.space = gettestobjspace(usemodules=['imp', 'zipimport',
+                                                '__pypy__'])
         cls.w_udir = cls.space.wrap(str(udir))
 
     def test_run_compiled_module(self):

diff --git a/pypy/module/imp/interp_imp.py b/pypy/module/imp/interp_imp.py
--- a/pypy/module/imp/interp_imp.py
+++ b/pypy/module/imp/interp_imp.py
@@ -135,7 +135,7 @@
     return importing.check_sys_modules(space, w_modulename)
 
 def new_module(space, w_name):
-    return space.wrap(Module(space, w_name))
+    return space.wrap(Module(space, w_name, add_package=False))
 
 def init_builtin(space, w_name):
     name = space.str_w(w_name)

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


diff --git a/pypy/interpreter/astcompiler/test/test_astbuilder.py b/pypy/interpreter/astcompiler/test/test_astbuilder.py
--- a/pypy/interpreter/astcompiler/test/test_astbuilder.py
+++ b/pypy/interpreter/astcompiler/test/test_astbuilder.py
@@ -754,6 +754,8 @@
             ("{x for x in z}", "set comprehension"),
             ("{x : x for x in z}", "dict comprehension"),
             ("'str'", "literal"),
+            ("u'str'", "literal"),
+            ("b'bytes'", "literal"),
             ("()", "()"),
             ("23", "literal"),
             ("{}", "literal"),

diff --git a/pypy/jit/metainterp/test/test_virtualref.py b/pypy/jit/metainterp/test/test_virtualref.py
--- a/pypy/jit/metainterp/test/test_virtualref.py
+++ b/pypy/jit/metainterp/test/test_virtualref.py
@@ -3,7 +3,7 @@
 from pypy.rlib.jit import JitDriver, dont_look_inside, vref_None
 from pypy.rlib.jit import virtual_ref, virtual_ref_finish
 from pypy.rlib.objectmodel import compute_unique_id
-from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
+from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
 from pypy.jit.metainterp.resoperation import rop
 from pypy.jit.metainterp.virtualref import VirtualRefInfo
 

diff --git a/pypy/translator/jvm/test/test_extreme.py b/pypy/translator/jvm/test/test_extreme.py
--- a/pypy/translator/jvm/test/test_extreme.py
+++ b/pypy/translator/jvm/test/test_extreme.py
@@ -1,5 +1,8 @@
+import py
 from pypy.translator.jvm.test.runtest import JvmTest
 from pypy.translator.oosupport.test_template.extreme import BaseTestExtreme
 
 class TestExtreme(BaseTestExtreme, JvmTest):
-    pass
+
+    def test_runtimeerror_due_to_stack_overflow(self):
+        py.test.skip('hotspot bug')


diff --git a/pypy/jit/tl/tla/test_tla.py b/pypy/jit/tl/tla/test_tla.py
--- a/pypy/jit/tl/tla/test_tla.py
+++ b/pypy/jit/tl/tla/test_tla.py
@@ -155,7 +155,7 @@
 
 # ____________________________________________________________
 
-from pypy.jit.metainterp.test.test_basic import LLJitMixin
+from pypy.jit.metainterp.test.support import LLJitMixin
 
 class TestLLtype(LLJitMixin):
     def test_loop(self):


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

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


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

diff --git a/pypy/jit/backend/x86/runner.py b/pypy/jit/backend/x86/runner.py
--- a/pypy/jit/backend/x86/runner.py
+++ b/pypy/jit/backend/x86/runner.py
@@ -19,6 +19,8 @@
 
     def __init__(self, rtyper, stats, opts=None, translate_support_code=False,
                  gcdescr=None):
+        if gcdescr is not None:
+            gcdescr.force_index_ofs = FORCE_INDEX_OFS
         AbstractLLCPU.__init__(self, rtyper, stats, opts,
                                translate_support_code, gcdescr)
 
@@ -127,7 +129,7 @@
         fail_index = rffi.cast(TP, addr_of_force_index)[0]
         assert fail_index >= 0, "already forced!"
         faildescr = self.get_fail_descr_from_number(fail_index)
-        rffi.cast(TP, addr_of_force_index)[0] = -1
+        rffi.cast(TP, addr_of_force_index)[0] = ~fail_index
         frb = self.assembler._find_failure_recovery_bytecode(faildescr)
         bytecode = rffi.cast(rffi.UCHARP, frb)
         # start of "no gc operation!" block
@@ -147,7 +149,6 @@
     WORD = 4
     NUM_REGS = 8
     CALLEE_SAVE_REGISTERS = [regloc.ebx, regloc.esi, regloc.edi]
-    FRAME_FIXED_SIZE = len(CALLEE_SAVE_REGISTERS) + 2
 
     supports_longlong = True
 
@@ -163,7 +164,6 @@
     WORD = 8
     NUM_REGS = 16
     CALLEE_SAVE_REGISTERS = [regloc.ebx, regloc.r12, regloc.r13, regloc.r14, regloc.r15]
-    FRAME_FIXED_SIZE = len(CALLEE_SAVE_REGISTERS) + 2
 
     def __init__(self, *args, **kwargs):
         assert sys.maxint == (2**63 - 1)

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

diff --git a/pypy/jit/metainterp/test/test_recursive.py b/pypy/jit/metainterp/test/test_recursive.py
--- a/pypy/jit/metainterp/test/test_recursive.py
+++ b/pypy/jit/metainterp/test/test_recursive.py
@@ -3,7 +3,7 @@
 from pypy.rlib.jit import unroll_safe, dont_look_inside
 from pypy.rlib.objectmodel import we_are_translated
 from pypy.rlib.debug import fatalerror
-from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
+from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
 from pypy.jit.codewriter.policy import StopAtXPolicy
 from pypy.rpython.annlowlevel import hlstr
 from pypy.jit.metainterp.warmspot import get_stats

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

diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -1350,6 +1350,11 @@
         pass
     def _freeze_(self):
         return True
+    def __enter__(self):
+        pass
+    def __exit__(self, *args):
+        pass
+
 dummy_lock = DummyLock()
 
 ## Table describing the regular part of the interface of object spaces,

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

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

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

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

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

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

diff --git a/pypy/jit/metainterp/test/test_warmspot.py b/pypy/jit/metainterp/test/test_warmspot.py
--- a/pypy/jit/metainterp/test/test_warmspot.py
+++ b/pypy/jit/metainterp/test/test_warmspot.py
@@ -6,7 +6,7 @@
 from pypy.jit.backend.llgraph import runner
 from pypy.jit.metainterp.history import BoxInt
 
-from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
+from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
 from pypy.jit.metainterp.optimizeopt import ALL_OPTS_NAMES
 
 

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

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

diff --git a/pypy/module/cpyext/test/test_api.py b/pypy/module/cpyext/test/test_api.py
--- a/pypy/module/cpyext/test/test_api.py
+++ b/pypy/module/cpyext/test/test_api.py
@@ -61,14 +61,44 @@
         except OperationError, e:
             print e.errorstr(self.space)
             raise
+
+        try:
+            del self.space.getexecutioncontext().cpyext_threadstate
+        except AttributeError:
+            pass
+
         if self.check_and_print_leaks():
             assert False, "Test leaks or loses object(s)."
 
+ at api.cpython_api([api.Py_ssize_t], api.Py_ssize_t, error=-1)
+def PyPy_TypedefTest1(space, arg):
+    assert lltype.typeOf(arg) == api.Py_ssize_t
+    return 0
+
+ at api.cpython_api([api.Py_ssize_tP], api.Py_ssize_tP)
+def PyPy_TypedefTest2(space, arg):
+    assert lltype.typeOf(arg) == api.Py_ssize_tP
+    return None
+
 class TestConversion(BaseApiTest):
     def test_conversions(self, space, api):
         api.PyPy_GetWrapped(space.w_None)
         api.PyPy_GetReference(space.w_None)
 
+    def test_typedef(self, space):
+        from pypy.translator.c.database import LowLevelDatabase
+        db = LowLevelDatabase()
+        assert (api.c_function_signature(db, api.FUNCTIONS['PyPy_TypedefTest1'])
+                == ('Py_ssize_t', 'Py_ssize_t arg0'))
+        assert (api.c_function_signature(db, api.FUNCTIONS['PyPy_TypedefTest2'])
+                == ('Py_ssize_t *', 'Py_ssize_t *arg0'))
+
+        PyPy_TypedefTest1(space, 0)
+        ppos = lltype.malloc(api.Py_ssize_tP.TO, 1, flavor='raw')
+        ppos[0] = 0
+        PyPy_TypedefTest2(space, ppos)
+        lltype.free(ppos, flavor='raw')
+
 
 def test_copy_header_files(tmpdir):
     api.copy_header_files(tmpdir)

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

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


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

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


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

diff --git a/pypy/objspace/std/fake.py b/pypy/objspace/std/fake.py
--- a/pypy/objspace/std/fake.py
+++ b/pypy/objspace/std/fake.py
@@ -151,9 +151,9 @@
 
 class CPythonFakeFrame(eval.Frame):
 
-    def __init__(self, space, code, w_globals=None, numlocals=-1):
+    def __init__(self, space, code, w_globals=None):
         self.fakecode = code
-        eval.Frame.__init__(self, space, w_globals, numlocals)
+        eval.Frame.__init__(self, space, w_globals)
 
     def getcode(self):
         return self.fakecode

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

diff --git a/pypy/jit/backend/x86/assembler.py b/pypy/jit/backend/x86/assembler.py
--- a/pypy/jit/backend/x86/assembler.py
+++ b/pypy/jit/backend/x86/assembler.py
@@ -8,9 +8,8 @@
 from pypy.rpython.lltypesystem.lloperation import llop
 from pypy.rpython.annlowlevel import llhelper
 from pypy.jit.backend.model import CompiledLoopToken
-from pypy.jit.backend.x86.regalloc import (RegAlloc, X86RegisterManager,
-                                           X86XMMRegisterManager, get_ebp_ofs,
-                                           _get_scale)
+from pypy.jit.backend.x86.regalloc import (RegAlloc, get_ebp_ofs,
+                                           _get_scale, gpr_reg_mgr_cls)
 
 from pypy.jit.backend.x86.arch import (FRAME_FIXED_SIZE, FORCE_INDEX_OFS, WORD,
                                        IS_X86_32, IS_X86_64)
@@ -78,8 +77,8 @@
         self.loop_run_counters = []
         self.float_const_neg_addr = 0
         self.float_const_abs_addr = 0
-        self.malloc_fixedsize_slowpath1 = 0
-        self.malloc_fixedsize_slowpath2 = 0
+        self.malloc_slowpath1 = 0
+        self.malloc_slowpath2 = 0
         self.memcpy_addr = 0
         self.setup_failure_recovery()
         self._debug = False
@@ -124,8 +123,8 @@
             self._build_failure_recovery(True, withfloats=True)
             support.ensure_sse2_floats()
             self._build_float_constants()
-        if hasattr(gc_ll_descr, 'get_malloc_fixedsize_slowpath_addr'):
-            self._build_malloc_fixedsize_slowpath()
+        if gc_ll_descr.get_malloc_slowpath_addr is not None:
+            self._build_malloc_slowpath()
         self._build_stack_check_slowpath()
         debug_start('jit-backend-counts')
         self.set_debug(have_debug_prints())
@@ -133,6 +132,7 @@
 
     def setup(self, looptoken):
         assert self.memcpy_addr != 0, "setup_once() not called?"
+        self.current_clt = looptoken.compiled_loop_token
         self.pending_guard_tokens = []
         self.mc = codebuf.MachineCodeBlockWrapper()
         if self.datablockwrapper is None:
@@ -145,6 +145,7 @@
         self.mc = None
         self.looppos = -1
         self.currently_compiling_loop = None
+        self.current_clt = None
 
     def finish_once(self):
         if self._debug:
@@ -170,26 +171,47 @@
         self.float_const_neg_addr = float_constants
         self.float_const_abs_addr = float_constants + 16
 
-    def _build_malloc_fixedsize_slowpath(self):
+    def _build_malloc_slowpath(self):
+        # With asmgcc, we need two helpers, so that we can write two CALL
+        # instructions in assembler, with a mark_gc_roots in between.
+        # With shadowstack, this is not needed, so we produce a single helper.
+        gcrootmap = self.cpu.gc_ll_descr.gcrootmap
+        #
         # ---------- first helper for the slow path of malloc ----------
         mc = codebuf.MachineCodeBlockWrapper()
         if self.cpu.supports_floats:          # save the XMM registers in
             for i in range(self.cpu.NUM_REGS):# the *caller* frame, from esp+8
                 mc.MOVSD_sx((WORD*2)+8*i, i)
         mc.SUB_rr(edx.value, eax.value)       # compute the size we want
-        if IS_X86_32:
-            mc.MOV_sr(WORD, edx.value)        # save it as the new argument
-        elif IS_X86_64:
-            # rdi can be clobbered: its content was forced to the stack
-            # by _fastpath_malloc(), like all other save_around_call_regs.
-            mc.MOV_rr(edi.value, edx.value)
-
-        addr = self.cpu.gc_ll_descr.get_malloc_fixedsize_slowpath_addr()
-        mc.JMP(imm(addr))                    # tail call to the real malloc
-        rawstart = mc.materialize(self.cpu.asmmemmgr, [])
-        self.malloc_fixedsize_slowpath1 = rawstart
-        # ---------- second helper for the slow path of malloc ----------
-        mc = codebuf.MachineCodeBlockWrapper()
+        addr = self.cpu.gc_ll_descr.get_malloc_slowpath_addr()
+        #
+        if gcrootmap is not None and gcrootmap.is_shadow_stack:
+            # ---- shadowstack ----
+            for reg, ofs in gpr_reg_mgr_cls.REGLOC_TO_COPY_AREA_OFS.items():
+                mc.MOV_br(ofs, reg.value)
+            mc.SUB_ri(esp.value, 16 - WORD)      # stack alignment of 16 bytes
+            if IS_X86_32:
+                mc.MOV_sr(0, edx.value)          # push argument
+            elif IS_X86_64:
+                mc.MOV_rr(edi.value, edx.value)
+            mc.CALL(imm(addr))
+            mc.ADD_ri(esp.value, 16 - WORD)
+            for reg, ofs in gpr_reg_mgr_cls.REGLOC_TO_COPY_AREA_OFS.items():
+                mc.MOV_rb(reg.value, ofs)
+        else:
+            # ---- asmgcc ----
+            if IS_X86_32:
+                mc.MOV_sr(WORD, edx.value)       # save it as the new argument
+            elif IS_X86_64:
+                # rdi can be clobbered: its content was forced to the stack
+                # by _fastpath_malloc(), like all other save_around_call_regs.
+                mc.MOV_rr(edi.value, edx.value)
+            mc.JMP(imm(addr))                    # tail call to the real malloc
+            rawstart = mc.materialize(self.cpu.asmmemmgr, [])
+            self.malloc_slowpath1 = rawstart
+            # ---------- second helper for the slow path of malloc ----------
+            mc = codebuf.MachineCodeBlockWrapper()
+        #
         if self.cpu.supports_floats:          # restore the XMM registers
             for i in range(self.cpu.NUM_REGS):# from where they were saved
                 mc.MOVSD_xs(i, (WORD*2)+8*i)
@@ -197,7 +219,7 @@
         mc.MOV(edx, heap(nursery_free_adr))   # load this in EDX
         mc.RET()
         rawstart = mc.materialize(self.cpu.asmmemmgr, [])
-        self.malloc_fixedsize_slowpath2 = rawstart
+        self.malloc_slowpath2 = rawstart
 
     def _build_stack_check_slowpath(self):
         _, _, slowpathaddr = self.cpu.insert_stack_check()
@@ -544,7 +566,7 @@
     def _get_offset_of_ebp_from_esp(self, allocated_depth):
         # Given that [EBP] is where we saved EBP, i.e. in the last word
         # of our fixed frame, then the 'words' value is:
-        words = (self.cpu.FRAME_FIXED_SIZE - 1) + allocated_depth
+        words = (FRAME_FIXED_SIZE - 1) + allocated_depth
         # align, e.g. for Mac OS X
         aligned_words = align_stack_words(words+2)-2 # 2 = EIP+EBP
         return -WORD * aligned_words
@@ -557,6 +579,10 @@
         for regloc in self.cpu.CALLEE_SAVE_REGISTERS:
             self.mc.PUSH_r(regloc.value)
 
+        gcrootmap = self.cpu.gc_ll_descr.gcrootmap
+        if gcrootmap and gcrootmap.is_shadow_stack:
+            self._call_header_shadowstack(gcrootmap)
+
     def _call_header_with_stack_check(self):
         if self.stack_check_slowpath == 0:
             pass                # no stack check (e.g. not translated)
@@ -578,12 +604,32 @@
     def _call_footer(self):
         self.mc.LEA_rb(esp.value, -len(self.cpu.CALLEE_SAVE_REGISTERS) * WORD)
 
+        gcrootmap = self.cpu.gc_ll_descr.gcrootmap
+        if gcrootmap and gcrootmap.is_shadow_stack:
+            self._call_footer_shadowstack(gcrootmap)
+
         for i in range(len(self.cpu.CALLEE_SAVE_REGISTERS)-1, -1, -1):
             self.mc.POP_r(self.cpu.CALLEE_SAVE_REGISTERS[i].value)
 
         self.mc.POP_r(ebp.value)
         self.mc.RET()
 
+    def _call_header_shadowstack(self, gcrootmap):
+        # we need to put two words into the shadowstack: the MARKER
+        # and the address of the frame (ebp, actually)
+        rst = gcrootmap.get_root_stack_top_addr()
+        assert rx86.fits_in_32bits(rst)
+        self.mc.MOV_rj(eax.value, rst)                # MOV eax, [rootstacktop]
+        self.mc.LEA_rm(edx.value, (eax.value, 2*WORD))  # LEA edx, [eax+2*WORD]
+        self.mc.MOV_mi((eax.value, 0), gcrootmap.MARKER)    # MOV [eax], MARKER
+        self.mc.MOV_mr((eax.value, WORD), ebp.value)      # MOV [eax+WORD], ebp
+        self.mc.MOV_jr(rst, edx.value)                # MOV [rootstacktop], edx
+
+    def _call_footer_shadowstack(self, gcrootmap):
+        rst = gcrootmap.get_root_stack_top_addr()
+        assert rx86.fits_in_32bits(rst)
+        self.mc.SUB_ji8(rst, 2*WORD)       # SUB [rootstacktop], 2*WORD
+
     def _assemble_bootstrap_direct_call(self, arglocs, jmppos, stackdepth):
         if IS_X86_64:
             return self._assemble_bootstrap_direct_call_64(arglocs, jmppos, stackdepth)
@@ -693,8 +739,8 @@
         nonfloatlocs, floatlocs = arglocs
         self._call_header()
         stackadjustpos = self._patchable_stackadjust()
-        tmp = X86RegisterManager.all_regs[0]
-        xmmtmp = X86XMMRegisterManager.all_regs[0]
+        tmp = eax
+        xmmtmp = xmm0
         self.mc.begin_reuse_scratch_register()
         for i in range(len(nonfloatlocs)):
             loc = nonfloatlocs[i]
@@ -903,9 +949,9 @@
                     self.implement_guard(guard_token, checkfalsecond)
         return genop_cmp_guard_float
 
-    def _emit_call(self, x, arglocs, start=0, tmp=eax):
+    def _emit_call(self, force_index, x, arglocs, start=0, tmp=eax):
         if IS_X86_64:
-            return self._emit_call_64(x, arglocs, start)
+            return self._emit_call_64(force_index, x, arglocs, start)
 
         p = 0
         n = len(arglocs)
@@ -931,9 +977,9 @@
         self._regalloc.reserve_param(p//WORD)
         # x is a location
         self.mc.CALL(x)
-        self.mark_gc_roots()
+        self.mark_gc_roots(force_index)
 
-    def _emit_call_64(self, x, arglocs, start=0):
+    def _emit_call_64(self, force_index, x, arglocs, start):
         src_locs = []
         dst_locs = []
         xmm_src_locs = []
@@ -991,12 +1037,27 @@
 
         self._regalloc.reserve_param(len(pass_on_stack))
         self.mc.CALL(x)
-        self.mark_gc_roots()
+        self.mark_gc_roots(force_index)
 
     def call(self, addr, args, res):
-        self._emit_call(imm(addr), args)
+        force_index = self.write_new_force_index()
+        self._emit_call(force_index, imm(addr), args)
         assert res is eax
 
+    def write_new_force_index(self):
+        # for shadowstack only: get a new, unused force_index number and
+        # write it to FORCE_INDEX_OFS.  Used to record the call shape
+        # (i.e. where the GC pointers are in the stack) around a CALL
+        # instruction that doesn't already have a force_index.
+        gcrootmap = self.cpu.gc_ll_descr.gcrootmap
+        if gcrootmap and gcrootmap.is_shadow_stack:
+            clt = self.current_clt
+            force_index = clt.reserve_and_record_some_faildescr_index()
+            self.mc.MOV_bi(FORCE_INDEX_OFS, force_index)
+            return force_index
+        else:
+            return 0
+
     genop_int_neg = _unaryop("NEG")
     genop_int_invert = _unaryop("NOT")
     genop_int_add = _binaryop("ADD", True)
@@ -1212,6 +1273,11 @@
             assert isinstance(loc_vtable, ImmedLoc)
             self.mc.MOV(mem(loc, self.cpu.vtable_offset), loc_vtable)
 
+    def set_new_array_length(self, loc, ofs_length, loc_num_elem):
+        assert isinstance(loc, RegLoc)
+        assert isinstance(loc_num_elem, ImmedLoc)
+        self.mc.MOV(mem(loc, ofs_length), loc_num_elem)
+
     # XXX genop_new is abused for all varsized mallocs with Boehm, for now
     # (instead of genop_new_array, genop_newstr, genop_newunicode)
     def genop_new(self, op, arglocs, result_loc):
@@ -1790,6 +1856,10 @@
         self.pending_guard_tokens.append(guard_token)
 
     def genop_call(self, op, arglocs, resloc):
+        force_index = self.write_new_force_index()
+        self._genop_call(op, arglocs, resloc, force_index)
+
+    def _genop_call(self, op, arglocs, resloc, force_index):
         sizeloc = arglocs[0]
         assert isinstance(sizeloc, ImmedLoc)
         size = sizeloc.value
@@ -1803,8 +1873,8 @@
             tmp = ecx
         else:
             tmp = eax
-        
-        self._emit_call(x, arglocs, 3, tmp=tmp)
+
+        self._emit_call(force_index, x, arglocs, 3, tmp=tmp)
 
         if IS_X86_32 and isinstance(resloc, StackLoc) and resloc.width == 8:
             # a float or a long long return
@@ -1835,7 +1905,7 @@
         faildescr = guard_op.getdescr()
         fail_index = self.cpu.get_fail_descr_number(faildescr)
         self.mc.MOV_bi(FORCE_INDEX_OFS, fail_index)
-        self.genop_call(op, arglocs, result_loc)
+        self._genop_call(op, arglocs, result_loc, fail_index)
         self.mc.CMP_bi(FORCE_INDEX_OFS, 0)
         self.implement_guard(guard_token, 'L')
 
@@ -1849,8 +1919,8 @@
         assert len(arglocs) - 2 == len(descr._x86_arglocs[0])
         #
         # Write a call to the direct_bootstrap_code of the target assembler
-        self._emit_call(imm(descr._x86_direct_bootstrap_code), arglocs, 2,
-                        tmp=eax)
+        self._emit_call(fail_index, imm(descr._x86_direct_bootstrap_code),
+                        arglocs, 2, tmp=eax)
         if op.result is None:
             assert result_loc is None
             value = self.cpu.done_with_this_frame_void_v
@@ -1875,7 +1945,7 @@
         jd = descr.outermost_jitdriver_sd
         assert jd is not None
         asm_helper_adr = self.cpu.cast_adr_to_int(jd.assembler_helper_adr)
-        self._emit_call(imm(asm_helper_adr), [eax, arglocs[1]], 0,
+        self._emit_call(fail_index, imm(asm_helper_adr), [eax, arglocs[1]], 0,
                         tmp=ecx)
         if IS_X86_32 and isinstance(result_loc, StackLoc) and result_loc.type == FLOAT:
             self.mc.FSTP_b(result_loc.value)
@@ -1902,7 +1972,7 @@
             # load the return value from fail_boxes_xxx[0]
             kind = op.result.type
             if kind == FLOAT:
-                xmmtmp = X86XMMRegisterManager.all_regs[0]
+                xmmtmp = xmm0
                 adr = self.fail_boxes_float.get_addr_for_num(0)
                 self.mc.MOVSD(xmmtmp, heap(adr))
                 self.mc.MOVSD(result_loc, xmmtmp)
@@ -1997,11 +2067,16 @@
         not_implemented("not implemented operation (guard): %s" %
                         op.getopname())
 
-    def mark_gc_roots(self):
+    def mark_gc_roots(self, force_index, use_copy_area=False):
+        if force_index < 0:
+            return     # not needed
         gcrootmap = self.cpu.gc_ll_descr.gcrootmap
         if gcrootmap:
-            mark = self._regalloc.get_mark_gc_roots(gcrootmap)
-            self.mc.insert_gcroot_marker(mark)
+            mark = self._regalloc.get_mark_gc_roots(gcrootmap, use_copy_area)
+            if gcrootmap.is_shadow_stack:
+                gcrootmap.write_callshape(mark, force_index)
+            else:
+                self.mc.insert_gcroot_marker(mark)
 
     def target_arglocs(self, loop_token):
         return loop_token._x86_arglocs
@@ -2013,8 +2088,7 @@
         else:
             self.mc.JMP(imm(loop_token._x86_loop_code))
 
-    def malloc_cond_fixedsize(self, nursery_free_adr, nursery_top_adr,
-                              size, tid):
+    def malloc_cond(self, nursery_free_adr, nursery_top_adr, size, tid):
         size = max(size, self.cpu.gc_ll_descr.minimal_size_in_nursery)
         self.mc.MOV(eax, heap(nursery_free_adr))
         self.mc.LEA_rm(edx.value, (eax.value, size))
@@ -2022,7 +2096,7 @@
         self.mc.J_il8(rx86.Conditions['NA'], 0) # patched later
         jmp_adr = self.mc.get_relative_pos()
 
-        # See comments in _build_malloc_fixedsize_slowpath for the
+        # See comments in _build_malloc_slowpath for the
         # details of the two helper functions that we are calling below.
         # First, we need to call two of them and not just one because we
         # need to have a mark_gc_roots() in between.  Then the calling
@@ -2032,19 +2106,27 @@
         # result in EAX; slowpath_addr2 additionally returns in EDX a
         # copy of heap(nursery_free_adr), so that the final MOV below is
         # a no-op.
-        slowpath_addr1 = self.malloc_fixedsize_slowpath1
+
         # reserve room for the argument to the real malloc and the
         # 8 saved XMM regs
         self._regalloc.reserve_param(1+16)
-        self.mc.CALL(imm(slowpath_addr1))
-        self.mark_gc_roots()
-        slowpath_addr2 = self.malloc_fixedsize_slowpath2
+
+        gcrootmap = self.cpu.gc_ll_descr.gcrootmap
+        shadow_stack = (gcrootmap is not None and gcrootmap.is_shadow_stack)
+        if not shadow_stack:
+            # there are two helpers to call only with asmgcc
+            slowpath_addr1 = self.malloc_slowpath1
+            self.mc.CALL(imm(slowpath_addr1))
+        self.mark_gc_roots(self.write_new_force_index(),
+                           use_copy_area=shadow_stack)
+        slowpath_addr2 = self.malloc_slowpath2
         self.mc.CALL(imm(slowpath_addr2))
 
         offset = self.mc.get_relative_pos() - jmp_adr
         assert 0 < offset <= 127
         self.mc.overwrite(jmp_adr-1, chr(offset))
         # on 64-bits, 'tid' is a value that fits in 31 bits
+        assert rx86.fits_in_32bits(tid)
         self.mc.MOV_mi((eax.value, 0), tid)
         self.mc.MOV(heap(nursery_free_adr), edx)
         

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

diff --git a/pypy/jit/metainterp/test/test_loop.py b/pypy/jit/metainterp/test/test_loop.py
--- a/pypy/jit/metainterp/test/test_loop.py
+++ b/pypy/jit/metainterp/test/test_loop.py
@@ -2,7 +2,7 @@
 from pypy.rlib.jit import JitDriver
 from pypy.rlib.objectmodel import compute_hash
 from pypy.jit.metainterp.warmspot import ll_meta_interp, get_stats
-from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
+from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
 from pypy.jit.codewriter.policy import StopAtXPolicy
 from pypy.jit.metainterp.resoperation import rop
 from pypy.jit.metainterp import history


More information about the Pypy-commit mailing list