Author: Wim Lavrijsen <wlavrij...@lbl.gov>
Branch: reflex-support
Changeset: r54878:3f1d1ccdb3f5
Date: 2012-05-01 11:13 -0700
http://bitbucket.org/pypy/pypy/changeset/3f1d1ccdb3f5/

Log:    merge default into branch

diff --git a/lib-python/modified-2.7/test/test_peepholer.py 
b/lib-python/modified-2.7/test/test_peepholer.py
--- a/lib-python/modified-2.7/test/test_peepholer.py
+++ b/lib-python/modified-2.7/test/test_peepholer.py
@@ -145,12 +145,15 @@
 
     def test_binary_subscr_on_unicode(self):
         # valid code get optimized
-        asm = dis_single('u"foo"[0]')
-        self.assertIn("(u'f')", asm)
-        self.assertNotIn('BINARY_SUBSCR', asm)
-        asm = dis_single('u"\u0061\uffff"[1]')
-        self.assertIn("(u'\\uffff')", asm)
-        self.assertNotIn('BINARY_SUBSCR', asm)
+        # XXX for now we always disable this optimization
+        # XXX see CPython's issue5057
+        if 0:
+            asm = dis_single('u"foo"[0]')
+            self.assertIn("(u'f')", asm)
+            self.assertNotIn('BINARY_SUBSCR', asm)
+            asm = dis_single('u"\u0061\uffff"[1]')
+            self.assertIn("(u'\\uffff')", asm)
+            self.assertNotIn('BINARY_SUBSCR', asm)
 
         # invalid code doesn't get optimized
         # out of range
diff --git a/pypy/doc/cppyy.rst b/pypy/doc/cppyy.rst
--- a/pypy/doc/cppyy.rst
+++ b/pypy/doc/cppyy.rst
@@ -21,6 +21,26 @@
 .. _`llvm`: http://llvm.org/
 
 
+Motivation
+==========
+
+The cppyy module offers two unique features, which result in great
+performance as well as better functionality and cross-language integration
+than would otherwise be possible.
+First, cppyy is written in RPython and therefore open to optimizations by the
+JIT up until the actual point of call into C++.
+This means that there are no conversions necessary between a garbage collected
+and a reference counted environment, as is needed for the use of existing
+extension modules written or generated for CPython.
+It also means that if variables are already unboxed by the JIT, they can be
+passed through directly to C++.
+Second, Reflex (and cling far more so) adds dynamic features to C++, thus
+greatly reducing impedance mismatches between the two languages.
+In fact, Reflex is dynamic enough that you could write the runtime bindings
+generation in python (as opposed to RPython) and this is used to create very
+natural "pythonizations" of the bound code.
+
+
 Installation
 ============
 
@@ -195,10 +215,12 @@
     >>>> d = cppyy.gbl.BaseFactory("name", 42, 3.14)
     >>>> type(d)
     <class '__main__.Derived'>
-    >>>> d.m_i
-    42
-    >>>> d.m_d
-    3.14
+    >>>> isinstance(d, cppyy.gbl.Base1)
+    True
+    >>>> isinstance(d, cppyy.gbl.Base2)
+    True
+    >>>> d.m_i, d.m_d
+    (42, 3.14)
     >>>> d.m_name == "name"
     True
     >>>>
@@ -295,6 +317,9 @@
   To select a specific virtual method, do like with normal python classes
   that override methods: select it from the class that you need, rather than
   calling the method on the instance.
+  To select a specific overload, use the __dispatch__ special function, which
+  takes the name of the desired method and its signature (which can be
+  obtained from the doc string) as arguments.
 
 * **namespaces**: Are represented as python classes.
   Namespaces are more open-ended than classes, so sometimes initial access may
diff --git a/pypy/doc/extending.rst b/pypy/doc/extending.rst
--- a/pypy/doc/extending.rst
+++ b/pypy/doc/extending.rst
@@ -116,13 +116,21 @@
 Reflex
 ======
 
-This method is only experimental for now, and is being exercised on a branch,
-`reflex-support`_, so you will have to build PyPy yourself.
+This method is still experimental and is being exercised on a branch,
+`reflex-support`_, which adds the `cppyy`_ module.
 The method works by using the `Reflex package`_ to provide reflection
 information of the C++ code, which is then used to automatically generate
-bindings at runtime, which can then be used from python.
+bindings at runtime.
+From a python standpoint, there is no difference between generating bindings
+at runtime, or having them "statically" generated and available in scripts
+or compiled into extension modules: python classes and functions are always
+runtime structures, created when a script or module loads.
+However, if the backend itself is capable of dynamic behavior, it is a much
+better functional match to python, allowing tighter integration and more
+natural language mappings.
 Full details are `available here`_.
 
+.. _`cppyy`: cppyy.html
 .. _`reflex-support`: cppyy.html
 .. _`Reflex package`: http://root.cern.ch/drupal/content/reflex
 .. _`available here`: cppyy.html
@@ -130,16 +138,33 @@
 Pros
 ----
 
-If it works, it is mostly automatic, and hence easy in use.
-The bindings can make use of direct pointers, in which case the calls are
-very fast.
+The cppyy module is written in RPython, which makes it possible to keep the
+code execution visible to the JIT all the way to the actual point of call into
+C++, thus allowing for a very fast interface.
+Reflex is currently in use in large software environments in High Energy
+Physics (HEP), across many different projects and packages, and its use can be
+virtually completely automated in a production environment.
+One of its uses in HEP is in providing language bindings for CPython.
+Thus, it is possible to use Reflex to have bound code work on both CPython and
+on PyPy.
+In the medium-term, Reflex will be replaced by `cling`_, which is based on
+`llvm`_.
+This will affect the backend only; the python-side interface is expected to
+remain the same, except that cling adds a lot of dynamic behavior to C++,
+enabling further language integration.
+
+.. _`cling`: http://root.cern.ch/drupal/content/cling
+.. _`llvm`: http://llvm.org/
 
 Cons
 ----
 
-C++ is a large language, and these bindings are not yet feature-complete.
-Although missing features should do no harm if you don't use them, if you do
-need a particular feature, it may be necessary to work around it in python
-or with a C++ helper function.
+C++ is a large language, and cppyy is not yet feature-complete.
+Still, the experience gained in developing the equivalent bindings for CPython
+means that adding missing features is a simple matter of engineering, not a
+question of research.
+The module is written so that currently missing features should do no harm if
+you don't use them, if you do need a particular feature, it may be necessary
+to work around it in python or with a C++ helper function.
 Although Reflex works on various platforms, the bindings with PyPy have only
 been tested on Linux.
diff --git a/pypy/interpreter/astcompiler/optimize.py 
b/pypy/interpreter/astcompiler/optimize.py
--- a/pypy/interpreter/astcompiler/optimize.py
+++ b/pypy/interpreter/astcompiler/optimize.py
@@ -304,14 +304,19 @@
                     # produce compatible pycs.
                     if (self.space.isinstance_w(w_obj, self.space.w_unicode) 
and
                         self.space.isinstance_w(w_const, 
self.space.w_unicode)):
-                        unistr = self.space.unicode_w(w_const)
-                        if len(unistr) == 1:
-                            ch = ord(unistr[0])
-                        else:
-                            ch = 0
-                        if (ch > 0xFFFF or
-                            (MAXUNICODE == 0xFFFF and 0xD800 <= ch <= 0xDFFF)):
-                            return subs
+                        #unistr = self.space.unicode_w(w_const)
+                        #if len(unistr) == 1:
+                        #    ch = ord(unistr[0])
+                        #else:
+                        #    ch = 0
+                        #if (ch > 0xFFFF or
+                        #    (MAXUNICODE == 0xFFFF and 0xD800 <= ch <= 
0xDFFF)):
+                        # --XXX-- for now we always disable optimization of
+                        # u'...'[constant] because the tests above are not
+                        # enough to fix issue5057 (CPython has the same
+                        # problem as of April 24, 2012).
+                        # See test_const_fold_unicode_subscr
+                        return subs
 
                     return ast.Const(w_const, subs.lineno, subs.col_offset)
 
diff --git a/pypy/interpreter/astcompiler/test/test_compiler.py 
b/pypy/interpreter/astcompiler/test/test_compiler.py
--- a/pypy/interpreter/astcompiler/test/test_compiler.py
+++ b/pypy/interpreter/astcompiler/test/test_compiler.py
@@ -844,7 +844,8 @@
         return u"abc"[0]
         """
         counts = self.count_instructions(source)
-        assert counts == {ops.LOAD_CONST: 1, ops.RETURN_VALUE: 1}
+        if 0:   # xxx later?
+            assert counts == {ops.LOAD_CONST: 1, ops.RETURN_VALUE: 1}
 
         # getitem outside of the BMP should not be optimized
         source = """def f():
@@ -854,12 +855,20 @@
         assert counts == {ops.LOAD_CONST: 2, ops.BINARY_SUBSCR: 1,
                           ops.RETURN_VALUE: 1}
 
+        source = """def f():
+        return u"\U00012345abcdef"[3]
+        """
+        counts = self.count_instructions(source)
+        assert counts == {ops.LOAD_CONST: 2, ops.BINARY_SUBSCR: 1,
+                          ops.RETURN_VALUE: 1}
+
         monkeypatch.setattr(optimize, "MAXUNICODE", 0xFFFF)
         source = """def f():
         return u"\uE01F"[0]
         """
         counts = self.count_instructions(source)
-        assert counts == {ops.LOAD_CONST: 1, ops.RETURN_VALUE: 1}
+        if 0:   # xxx later?
+            assert counts == {ops.LOAD_CONST: 1, ops.RETURN_VALUE: 1}
         monkeypatch.undo()
 
         # getslice is not yet optimized.
diff --git a/pypy/jit/backend/llsupport/asmmemmgr.py 
b/pypy/jit/backend/llsupport/asmmemmgr.py
--- a/pypy/jit/backend/llsupport/asmmemmgr.py
+++ b/pypy/jit/backend/llsupport/asmmemmgr.py
@@ -277,6 +277,8 @@
             from pypy.jit.backend.hlinfo import highleveljitinfo
             if highleveljitinfo.sys_executable:
                 debug_print('SYS_EXECUTABLE', highleveljitinfo.sys_executable)
+            else:
+                debug_print('SYS_EXECUTABLE', '??')
             #
             HEX = '0123456789ABCDEF'
             dump = []
diff --git a/pypy/jit/backend/llsupport/test/test_asmmemmgr.py 
b/pypy/jit/backend/llsupport/test/test_asmmemmgr.py
--- a/pypy/jit/backend/llsupport/test/test_asmmemmgr.py
+++ b/pypy/jit/backend/llsupport/test/test_asmmemmgr.py
@@ -217,7 +217,8 @@
     encoded = ''.join(writtencode).encode('hex').upper()
     ataddr = '@%x' % addr
     assert log == [('test-logname-section',
-                    [('debug_print', 'CODE_DUMP', ataddr, '+0 ', encoded)])]
+                    [('debug_print', 'SYS_EXECUTABLE', '??'),
+                     ('debug_print', 'CODE_DUMP', ataddr, '+0 ', encoded)])]
     
     lltype.free(p, flavor='raw')
 
diff --git a/pypy/jit/metainterp/jitexc.py b/pypy/jit/metainterp/jitexc.py
--- a/pypy/jit/metainterp/jitexc.py
+++ b/pypy/jit/metainterp/jitexc.py
@@ -12,7 +12,6 @@
     """
     _go_through_llinterp_uncaught_ = True     # ugh
 
-
 def _get_standard_error(rtyper, Class):
     exdata = rtyper.getexceptiondata()
     clsdef = rtyper.annotator.bookkeeper.getuniqueclassdef(Class)
diff --git a/pypy/jit/metainterp/optimize.py b/pypy/jit/metainterp/optimize.py
--- a/pypy/jit/metainterp/optimize.py
+++ b/pypy/jit/metainterp/optimize.py
@@ -5,3 +5,9 @@
     """Raised when the optimize*.py detect that the loop that
     we are trying to build cannot possibly make sense as a
     long-running loop (e.g. it cannot run 2 complete iterations)."""
+
+    def __init__(self, msg='?'):
+        debug_start("jit-abort")
+        debug_print(msg)
+        debug_stop("jit-abort")
+        self.msg = msg
diff --git a/pypy/jit/metainterp/optimizeopt/__init__.py 
b/pypy/jit/metainterp/optimizeopt/__init__.py
--- a/pypy/jit/metainterp/optimizeopt/__init__.py
+++ b/pypy/jit/metainterp/optimizeopt/__init__.py
@@ -49,7 +49,8 @@
                 optimizations.append(OptFfiCall())
 
     if ('rewrite' not in enable_opts or 'virtualize' not in enable_opts
-        or 'heap' not in enable_opts or 'unroll' not in enable_opts):
+        or 'heap' not in enable_opts or 'unroll' not in enable_opts
+        or 'pure' not in enable_opts):
         optimizations.append(OptSimplify())
 
     return optimizations, unroll
diff --git a/pypy/jit/metainterp/optimizeopt/heap.py 
b/pypy/jit/metainterp/optimizeopt/heap.py
--- a/pypy/jit/metainterp/optimizeopt/heap.py
+++ b/pypy/jit/metainterp/optimizeopt/heap.py
@@ -257,8 +257,8 @@
             opnum == rop.COPYSTRCONTENT or       # no effect on GC struct/array
             opnum == rop.COPYUNICODECONTENT):    # no effect on GC struct/array
             return
-        assert opnum != rop.CALL_PURE
         if (opnum == rop.CALL or
+            opnum == rop.CALL_PURE or
             opnum == rop.CALL_MAY_FORCE or
             opnum == rop.CALL_RELEASE_GIL or
             opnum == rop.CALL_ASSEMBLER):
@@ -481,7 +481,7 @@
         # already between the tracing and now.  In this case, we are
         # simply ignoring the QUASIIMMUT_FIELD hint and compiling it
         # as a regular getfield.
-        if not qmutdescr.is_still_valid():
+        if not qmutdescr.is_still_valid_for(structvalue.get_key_box()):
             self._remove_guard_not_invalidated = True
             return
         # record as an out-of-line guard
diff --git a/pypy/jit/metainterp/optimizeopt/intbounds.py 
b/pypy/jit/metainterp/optimizeopt/intbounds.py
--- a/pypy/jit/metainterp/optimizeopt/intbounds.py
+++ b/pypy/jit/metainterp/optimizeopt/intbounds.py
@@ -191,10 +191,13 @@
         # GUARD_OVERFLOW, then the loop is invalid.
         lastop = self.last_emitted_operation
         if lastop is None:
-            raise InvalidLoop
+            raise InvalidLoop('An INT_xxx_OVF was proven not to overflow but' +
+                              'guarded with GUARD_OVERFLOW')
         opnum = lastop.getopnum()
         if opnum not in (rop.INT_ADD_OVF, rop.INT_SUB_OVF, rop.INT_MUL_OVF):
-            raise InvalidLoop
+            raise InvalidLoop('An INT_xxx_OVF was proven not to overflow but' +
+                              'guarded with GUARD_OVERFLOW')
+                             
         self.emit_operation(op)
 
     def optimize_INT_ADD_OVF(self, op):
diff --git a/pypy/jit/metainterp/optimizeopt/optimizer.py 
b/pypy/jit/metainterp/optimizeopt/optimizer.py
--- a/pypy/jit/metainterp/optimizeopt/optimizer.py
+++ b/pypy/jit/metainterp/optimizeopt/optimizer.py
@@ -525,6 +525,7 @@
 
     @specialize.argtype(0)
     def _emit_operation(self, op):
+        assert op.getopnum() != rop.CALL_PURE
         for i in range(op.numargs()):
             arg = op.getarg(i)
             try:
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
@@ -208,7 +208,8 @@
             box = value.box
             assert isinstance(box, Const)
             if not box.same_constant(constbox):
-                raise InvalidLoop
+                raise InvalidLoop('A GURAD_{VALUE,TRUE,FALSE} was proven to' +
+                                  'always fail')
             return
         if emit_operation:
             self.emit_operation(op)
@@ -220,7 +221,7 @@
         if value.is_null():
             return
         elif value.is_nonnull():
-            raise InvalidLoop
+            raise InvalidLoop('A GUARD_ISNULL was proven to always fail')
         self.emit_operation(op)
         value.make_constant(self.optimizer.cpu.ts.CONST_NULL)
 
@@ -229,7 +230,7 @@
         if value.is_nonnull():
             return
         elif value.is_null():
-            raise InvalidLoop
+            raise InvalidLoop('A GUARD_NONNULL was proven to always fail')
         self.emit_operation(op)
         value.make_nonnull(op)
 
@@ -278,7 +279,7 @@
         if realclassbox is not None:
             if realclassbox.same_constant(expectedclassbox):
                 return
-            raise InvalidLoop
+            raise InvalidLoop('A GUARD_CLASS was proven to always fail')
         if value.last_guard:
             # there already has been a guard_nonnull or guard_class or
             # guard_nonnull_class on this value.
@@ -301,7 +302,8 @@
     def optimize_GUARD_NONNULL_CLASS(self, op):
         value = self.getvalue(op.getarg(0))
         if value.is_null():
-            raise InvalidLoop
+            raise InvalidLoop('A GUARD_NONNULL_CLASS was proven to always ' +
+                              'fail')
         self.optimize_GUARD_CLASS(op)
 
     def optimize_CALL_LOOPINVARIANT(self, op):
diff --git a/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py 
b/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py
--- a/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py
+++ b/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py
@@ -5090,7 +5090,6 @@
 class TestLLtype(BaseTestOptimizeBasic, LLtypeMixin):
     pass
 
-
 ##class TestOOtype(BaseTestOptimizeBasic, OOtypeMixin):
 
 ##    def test_instanceof(self):
diff --git a/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py 
b/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py
--- a/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py
+++ b/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py
@@ -6533,9 +6533,9 @@
     def test_quasi_immut_2(self):
         ops = """
         []
-        quasiimmut_field(ConstPtr(myptr), descr=quasiimmutdescr)
+        quasiimmut_field(ConstPtr(quasiptr), descr=quasiimmutdescr)
         guard_not_invalidated() []
-        i1 = getfield_gc(ConstPtr(myptr), descr=quasifielddescr)
+        i1 = getfield_gc(ConstPtr(quasiptr), descr=quasifielddescr)
         escape(i1)
         jump()
         """
@@ -6585,13 +6585,13 @@
     def test_call_may_force_invalidated_guards_reload(self):
         ops = """
         [i0a, i0b]
-        quasiimmut_field(ConstPtr(myptr), descr=quasiimmutdescr)
+        quasiimmut_field(ConstPtr(quasiptr), descr=quasiimmutdescr)
         guard_not_invalidated() []
-        i1 = getfield_gc(ConstPtr(myptr), descr=quasifielddescr)
+        i1 = getfield_gc(ConstPtr(quasiptr), descr=quasifielddescr)
         call_may_force(i0b, descr=mayforcevirtdescr)
-        quasiimmut_field(ConstPtr(myptr), descr=quasiimmutdescr)
+        quasiimmut_field(ConstPtr(quasiptr), descr=quasiimmutdescr)
         guard_not_invalidated() []
-        i2 = getfield_gc(ConstPtr(myptr), descr=quasifielddescr)
+        i2 = getfield_gc(ConstPtr(quasiptr), descr=quasifielddescr)
         i3 = escape(i1)
         i4 = escape(i2)
         jump(i3, i4)
@@ -7813,6 +7813,52 @@
         """
         self.optimize_loop(ops, expected)
 
+    def test_issue1080_infinitie_loop_virtual(self):
+        ops = """
+        [p10]
+        p52 = getfield_gc(p10, descr=nextdescr) # inst_storage
+        p54 = getarrayitem_gc(p52, 0, descr=arraydescr)
+        p69 = getfield_gc_pure(p54, descr=otherdescr) # inst_w_function
+
+        quasiimmut_field(p69, descr=quasiimmutdescr)
+        guard_not_invalidated() []
+        p71 = getfield_gc(p69, descr=quasifielddescr) # inst_code
+        guard_value(p71, -4247) []
+
+        p106 = new_with_vtable(ConstClass(node_vtable))
+        p108 = new_array(3, descr=arraydescr)
+        p110 = new_with_vtable(ConstClass(node_vtable))
+        setfield_gc(p110, ConstPtr(myptr2), descr=otherdescr) # inst_w_function
+        setarrayitem_gc(p108, 0, p110, descr=arraydescr)
+        setfield_gc(p106, p108, descr=nextdescr) # inst_storage
+        jump(p106)
+        """
+        expected = """
+        []
+        p72 = getfield_gc(ConstPtr(myptr2), descr=quasifielddescr)
+        guard_value(p72, -4247) []
+        jump()
+        """
+        self.optimize_loop(ops, expected)
+        
+
+    def test_issue1080_infinitie_loop_simple(self):
+        ops = """
+        [p69]
+        quasiimmut_field(p69, descr=quasiimmutdescr)
+        guard_not_invalidated() []
+        p71 = getfield_gc(p69, descr=quasifielddescr) # inst_code
+        guard_value(p71, -4247) []
+        jump(ConstPtr(myptr))
+        """
+        expected = """
+        []
+        p72 = getfield_gc(ConstPtr(myptr), descr=quasifielddescr)
+        guard_value(p72, -4247) []
+        jump()
+        """
+        self.optimize_loop(ops, expected)
+
 class TestLLtype(OptimizeOptTest, LLtypeMixin):
     pass
 
diff --git a/pypy/jit/metainterp/optimizeopt/test/test_util.py 
b/pypy/jit/metainterp/optimizeopt/test/test_util.py
--- a/pypy/jit/metainterp/optimizeopt/test/test_util.py
+++ b/pypy/jit/metainterp/optimizeopt/test/test_util.py
@@ -122,6 +122,7 @@
     quasi.inst_field = -4247
     quasifielddescr = cpu.fielddescrof(QUASI, 'inst_field')
     quasibox = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, quasi))
+    quasiptr = quasibox.value
     quasiimmutdescr = QuasiImmutDescr(cpu, quasibox,
                                       quasifielddescr,
                                       cpu.fielddescrof(QUASI, 'mutate_field'))
diff --git a/pypy/jit/metainterp/optimizeopt/unroll.py 
b/pypy/jit/metainterp/optimizeopt/unroll.py
--- a/pypy/jit/metainterp/optimizeopt/unroll.py
+++ b/pypy/jit/metainterp/optimizeopt/unroll.py
@@ -315,7 +315,10 @@
         try:
             jumpargs = virtual_state.make_inputargs(values, self.optimizer)
         except BadVirtualState:
-            raise InvalidLoop
+            raise InvalidLoop('The state of the optimizer at the end of ' +
+                              'peeled loop is inconsistent with the ' +
+                              'VirtualState at the begining of the peeled ' +
+                              'loop')
         jumpop.initarglist(jumpargs)
 
         # Inline the short preamble at the end of the loop
@@ -325,7 +328,11 @@
         for i in range(len(short_inputargs)):
             if short_inputargs[i] in args:
                 if args[short_inputargs[i]] != jmp_to_short_args[i]:
-                    raise InvalidLoop
+                    raise InvalidLoop('The short preamble wants the ' +
+                                      'same box passed to multiple of its ' +
+                                      'inputargs, but the jump at the ' +
+                                      'end of this bridge does not do that.')
+                                      
             args[short_inputargs[i]] = jmp_to_short_args[i]
         self.short_inliner = Inliner(short_inputargs, jmp_to_short_args)
         for op in self.short[1:]:
@@ -378,7 +385,10 @@
             #final_virtual_state.debug_print("Bad virtual state at end of 
loop, ",
             #                                bad)
             #debug_stop('jit-log-virtualstate')
-            raise InvalidLoop
+            raise InvalidLoop('The virtual state at the end of the peeled ' +
+                              'loop is not compatible with the virtual ' +
+                              'state at the start of the loop which makes ' +
+                              'it impossible to close the loop')
             
         #debug_stop('jit-log-virtualstate')
 
@@ -526,8 +536,8 @@
         args = jumpop.getarglist()
         modifier = VirtualStateAdder(self.optimizer)
         virtual_state = modifier.get_virtual_state(args)
-        #debug_start('jit-log-virtualstate')
-        #virtual_state.debug_print("Looking for ")
+        debug_start('jit-log-virtualstate')
+        virtual_state.debug_print("Looking for ")
 
         for target in cell_token.target_tokens:
             if not target.virtual_state:
@@ -536,10 +546,10 @@
             extra_guards = []
 
             bad = {}
-            #debugmsg = 'Did not match '
+            debugmsg = 'Did not match '
             if target.virtual_state.generalization_of(virtual_state, bad):
                 ok = True
-                #debugmsg = 'Matched '
+                debugmsg = 'Matched '
             else:
                 try:
                     cpu = self.optimizer.cpu
@@ -548,13 +558,13 @@
                                                          extra_guards)
 
                     ok = True
-                    #debugmsg = 'Guarded to match '
+                    debugmsg = 'Guarded to match '
                 except InvalidLoop:
                     pass
-            #target.virtual_state.debug_print(debugmsg, bad)
+            target.virtual_state.debug_print(debugmsg, bad)
 
             if ok:
-                #debug_stop('jit-log-virtualstate')
+                debug_stop('jit-log-virtualstate')
 
                 values = [self.getvalue(arg)
                           for arg in jumpop.getarglist()]
@@ -581,7 +591,7 @@
                     jumpop.setdescr(cell_token.target_tokens[0])
                     self.optimizer.send_extra_operation(jumpop)
                 return True
-        #debug_stop('jit-log-virtualstate')
+        debug_stop('jit-log-virtualstate')
         return False
 
 class ValueImporter(object):
diff --git a/pypy/jit/metainterp/optimizeopt/virtualstate.py 
b/pypy/jit/metainterp/optimizeopt/virtualstate.py
--- a/pypy/jit/metainterp/optimizeopt/virtualstate.py
+++ b/pypy/jit/metainterp/optimizeopt/virtualstate.py
@@ -27,11 +27,15 @@
         if self.generalization_of(other, renum, {}):
             return
         if renum[self.position] != other.position:
-            raise InvalidLoop
+            raise InvalidLoop('The numbering of the virtual states does not ' +
+                              'match. This means that two virtual fields ' +
+                              'have been set to the same Box in one of the ' +
+                              'virtual states but not in the other.')
         self._generate_guards(other, box, cpu, extra_guards)
 
     def _generate_guards(self, other, box, cpu, extra_guards):
-        raise InvalidLoop
+        raise InvalidLoop('Generating guards for making the VirtualStates ' +
+                          'at hand match have not been implemented')
 
     def enum_forced_boxes(self, boxes, value, optimizer):
         raise NotImplementedError
@@ -346,10 +350,12 @@
 
     def _generate_guards(self, other, box, cpu, extra_guards):
         if not isinstance(other, NotVirtualStateInfo):
-            raise InvalidLoop
+            raise InvalidLoop('The VirtualStates does not match as a ' +
+                              'virtual appears where a pointer is needed ' +
+                              'and it is too late to force it.')
 
         if self.lenbound or other.lenbound:
-            raise InvalidLoop
+            raise InvalidLoop('The array length bounds does not match.')
 
         if self.level == LEVEL_KNOWNCLASS and \
            box.nonnull() and \
@@ -400,7 +406,8 @@
             return
 
         # Remaining cases are probably not interesting
-        raise InvalidLoop
+        raise InvalidLoop('Generating guards for making the VirtualStates ' +
+                          'at hand match have not been implemented')
         if self.level == LEVEL_CONSTANT:
             import pdb; pdb.set_trace()
             raise NotImplementedError
diff --git a/pypy/jit/metainterp/quasiimmut.py 
b/pypy/jit/metainterp/quasiimmut.py
--- a/pypy/jit/metainterp/quasiimmut.py
+++ b/pypy/jit/metainterp/quasiimmut.py
@@ -120,8 +120,10 @@
                                     self.fielddescr, self.structbox)
         return fieldbox.constbox()
 
-    def is_still_valid(self):
+    def is_still_valid_for(self, structconst):
         assert self.structbox is not None
+        if not self.structbox.constbox().same_constant(structconst):
+            return False
         cpu = self.cpu
         gcref = self.structbox.getref_base()
         qmut = get_current_qmut_instance(cpu, gcref, self.mutatefielddescr)
diff --git a/pypy/jit/metainterp/test/test_quasiimmut.py 
b/pypy/jit/metainterp/test/test_quasiimmut.py
--- a/pypy/jit/metainterp/test/test_quasiimmut.py
+++ b/pypy/jit/metainterp/test/test_quasiimmut.py
@@ -8,7 +8,7 @@
 from pypy.jit.metainterp.quasiimmut import get_current_qmut_instance
 from pypy.jit.metainterp.test.support import LLJitMixin
 from pypy.jit.codewriter.policy import StopAtXPolicy
-from pypy.rlib.jit import JitDriver, dont_look_inside, unroll_safe
+from pypy.rlib.jit import JitDriver, dont_look_inside, unroll_safe, promote
 
 
 def test_get_current_qmut_instance():
@@ -506,6 +506,27 @@
             "guard_not_invalidated": 2
         })
 
+    def test_issue1080(self):
+        myjitdriver = JitDriver(greens=[], reds=["n", "sa", "a"])
+        class Foo(object):
+            _immutable_fields_ = ["x?"]
+            def __init__(self, x):
+                self.x = x
+        one, two = Foo(1), Foo(2)
+        def main(n):
+            sa = 0
+            a = one
+            while n:
+                myjitdriver.jit_merge_point(n=n, sa=sa, a=a)
+                sa += a.x
+                if a.x == 1:
+                    a = two
+                elif a.x == 2:
+                    a = one                    
+                n -= 1
+            return sa
+        res = self.meta_interp(main, [10])
+        assert res == main(10)
 
 class TestLLtypeGreenFieldsTests(QuasiImmutTests, LLJitMixin):
     pass
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
@@ -157,13 +157,15 @@
         raises(IOError, _multiprocessing.Connection, -15)
 
     def test_byte_order(self):
+        import socket
+        if not 'fromfd' in dir(socket):
+            skip('No fromfd in socket')
         # The exact format of net strings (length in network byte
         # order) is important for interoperation with others
         # implementations.
         rhandle, whandle = self.make_pair()
         whandle.send_bytes("abc")
         whandle.send_bytes("defg")
-        import socket
         sock = socket.fromfd(rhandle.fileno(),
                              socket.AF_INET, socket.SOCK_STREAM)
         data1 = sock.recv(7)
diff --git a/pypy/module/_winreg/test/test_winreg.py 
b/pypy/module/_winreg/test/test_winreg.py
--- a/pypy/module/_winreg/test/test_winreg.py
+++ b/pypy/module/_winreg/test/test_winreg.py
@@ -198,7 +198,10 @@
         import nt
         r = ExpandEnvironmentStrings(u"%windir%\\test")
         assert isinstance(r, unicode)
-        assert r == nt.environ["WINDIR"] + "\\test"
+        if 'WINDIR' in nt.environ.keys():
+            assert r == nt.environ["WINDIR"] + "\\test"
+        else:
+            assert r == nt.environ["windir"] + "\\test"
 
     def test_long_key(self):
         from _winreg import (
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
@@ -103,8 +103,8 @@
 """.split()
 for name in constant_names:
     setattr(CConfig_constants, name, rffi_platform.ConstantInteger(name))
-udir.join('pypy_decl.h').write("/* Will be filled later */")
-udir.join('pypy_macros.h').write("/* Will be filled later */")
+udir.join('pypy_decl.h').write("/* Will be filled later */\n")
+udir.join('pypy_macros.h').write("/* Will be filled later */\n")
 globals().update(rffi_platform.configure(CConfig_constants))
 
 def copy_header_files(dstdir):
diff --git a/pypy/module/micronumpy/test/test_dtypes.py 
b/pypy/module/micronumpy/test/test_dtypes.py
--- a/pypy/module/micronumpy/test/test_dtypes.py
+++ b/pypy/module/micronumpy/test/test_dtypes.py
@@ -185,6 +185,33 @@
 
         assert dtype("float") is dtype(float)
 
+    def test_index_int8(self):
+        from _numpypy import array, int8
+
+        a = array(range(10), dtype=int8)
+        b = array([0] * 10, dtype=int8)
+        for idx in b: a[idx] += 1
+
+    def test_index_int16(self):
+        from _numpypy import array, int16
+
+        a = array(range(10), dtype=int16)
+        b = array([0] * 10, dtype=int16)
+        for idx in b: a[idx] += 1
+
+    def test_index_int32(self):
+        from _numpypy import array, int32
+
+        a = array(range(10), dtype=int32)
+        b = array([0] * 10, dtype=int32)
+        for idx in b: a[idx] += 1
+
+    def test_index_int64(self):
+        from _numpypy import array, int64
+
+        a = array(range(10), dtype=int64)
+        b = array([0] * 10, dtype=int64)
+        for idx in b: a[idx] += 1
 
 class AppTestTypes(BaseNumpyAppTest):    
     def test_abstract_types(self):
diff --git a/pypy/module/pypyjit/test_pypy_c/test_00_model.py 
b/pypy/module/pypyjit/test_pypy_c/test_00_model.py
--- a/pypy/module/pypyjit/test_pypy_c/test_00_model.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_00_model.py
@@ -54,7 +54,8 @@
             cmdline += ['--jit', ','.join(jitcmdline)]
         cmdline.append(str(self.filepath))
         #
-        env={'PYPYLOG': self.log_string + ':' + str(logfile)}
+        env = os.environ.copy()
+        env['PYPYLOG'] = self.log_string + ':' + str(logfile)
         pipe = subprocess.Popen(cmdline,
                                 env=env,
                                 stdout=subprocess.PIPE,
diff --git a/pypy/module/rctime/interp_time.py 
b/pypy/module/rctime/interp_time.py
--- a/pypy/module/rctime/interp_time.py
+++ b/pypy/module/rctime/interp_time.py
@@ -572,7 +572,7 @@
                 if i < length and format[i] == '#':
                     # not documented by python
                     i += 1
-                if i >= length or format[i] not in "aAbBcdfHIjmMpSUwWxXyYzZ%":
+                if i >= length or format[i] not in "aAbBcdHIjmMpSUwWxXyYzZ%":
                     raise OperationError(space.w_ValueError,
                                          space.wrap("invalid format string"))
             i += 1
diff --git a/pypy/module/rctime/test/test_rctime.py 
b/pypy/module/rctime/test/test_rctime.py
--- a/pypy/module/rctime/test/test_rctime.py
+++ b/pypy/module/rctime/test/test_rctime.py
@@ -64,6 +64,7 @@
 
     def test_localtime(self):
         import time as rctime
+        import os
         raises(TypeError, rctime.localtime, "foo")
         rctime.localtime()
         rctime.localtime(None)
@@ -75,6 +76,10 @@
         assert 0 <= (t1 - t0) < 1.2
         t = rctime.time()
         assert rctime.localtime(t) == rctime.localtime(t)
+        if os.name == 'nt':
+            raises(ValueError, rctime.localtime, -1)
+        else:
+            rctime.localtime(-1)
 
     def test_mktime(self):
         import time as rctime
@@ -108,8 +113,8 @@
         assert long(rctime.mktime(rctime.gmtime(t))) - rctime.timezone == 
long(t)
         ltime = rctime.localtime()
         assert rctime.mktime(tuple(ltime)) == rctime.mktime(ltime)
-
-        assert rctime.mktime(rctime.localtime(-1)) == -1
+        if os.name != 'nt':
+            assert rctime.mktime(rctime.localtime(-1)) == -1
 
     def test_asctime(self):
         import time as rctime
diff --git a/pypy/module/select/__init__.py b/pypy/module/select/__init__.py
--- a/pypy/module/select/__init__.py
+++ b/pypy/module/select/__init__.py
@@ -2,6 +2,7 @@
 from pypy.interpreter.mixedmodule import MixedModule
 
 import sys
+import os
 
 
 class Module(MixedModule):
@@ -9,11 +10,13 @@
     }
 
     interpleveldefs = {
-        'poll'  : 'interp_select.poll',
         'select': 'interp_select.select',
         'error' : 'space.fromcache(interp_select.Cache).w_error'
     }
 
+    if os.name =='posix':
+        interpleveldefs['poll'] = 'interp_select.poll'
+
     if sys.platform.startswith('linux'):
         interpleveldefs['epoll'] = 'interp_epoll.W_Epoll'
         from pypy.module.select.interp_epoll import cconfig, public_symbols
diff --git a/pypy/module/select/test/test_select.py 
b/pypy/module/select/test/test_select.py
--- a/pypy/module/select/test/test_select.py
+++ b/pypy/module/select/test/test_select.py
@@ -214,6 +214,8 @@
 
     def test_poll(self):
         import select
+        if not hasattr(select, 'poll'):
+            skip("no select.poll() on this platform")
         readend, writeend = self.getpair()
         try:
             class A(object):
diff --git a/pypy/objspace/flow/operation.py b/pypy/objspace/flow/operation.py
--- a/pypy/objspace/flow/operation.py
+++ b/pypy/objspace/flow/operation.py
@@ -350,8 +350,8 @@
                     result = op(*args)
                 except Exception, e:
                     etype = e.__class__
-                    msg = "generated by a constant operation:  %s" % (
-                        name)
+                    msg = "generated by a constant operation:\n\t%s%r" % (
+                        name, tuple(args))
                     raise OperationThatShouldNotBePropagatedError(
                         self.wrap(etype), self.wrap(msg))
                 else:
diff --git a/pypy/rlib/debug.py b/pypy/rlib/debug.py
--- a/pypy/rlib/debug.py
+++ b/pypy/rlib/debug.py
@@ -1,10 +1,12 @@
 import sys, time
 from pypy.rpython.extregistry import ExtRegistryEntry
+from pypy.rlib.objectmodel import we_are_translated
 from pypy.rlib.rarithmetic import is_valid_int
 
 
 def ll_assert(x, msg):
     """After translation to C, this becomes an RPyAssert."""
+    assert type(x) is bool, "bad type! got %r" % (type(x),)
     assert x, msg
 
 class Entry(ExtRegistryEntry):
@@ -21,8 +23,13 @@
         hop.exception_cannot_occur()
         hop.genop('debug_assert', vlist)
 
+class FatalError(Exception):
+    pass
+
 def fatalerror(msg):
     # print the RPython traceback and abort with a fatal error
+    if not we_are_translated():
+        raise FatalError(msg)
     from pypy.rpython.lltypesystem import lltype
     from pypy.rpython.lltypesystem.lloperation import llop
     llop.debug_print_traceback(lltype.Void)
@@ -33,6 +40,8 @@
 
 def fatalerror_notb(msg):
     # a variant of fatalerror() that doesn't print the RPython traceback
+    if not we_are_translated():
+        raise FatalError(msg)
     from pypy.rpython.lltypesystem import lltype
     from pypy.rpython.lltypesystem.lloperation import llop
     llop.debug_fatalerror(lltype.Void, msg)
diff --git a/pypy/rlib/rposix.py b/pypy/rlib/rposix.py
--- a/pypy/rlib/rposix.py
+++ b/pypy/rlib/rposix.py
@@ -1,9 +1,11 @@
 import os
-from pypy.rpython.lltypesystem.rffi import CConstant, CExternVariable, INT
+from pypy.rpython.lltypesystem.rffi import (CConstant, CExternVariable,
+        INT, CCHARPP)
 from pypy.rpython.lltypesystem import lltype, ll2ctypes, rffi
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
 from pypy.rlib.rarithmetic import intmask
 from pypy.rlib.objectmodel import specialize
+from pypy.rlib import jit
 
 class CConstantErrno(CConstant):
     # these accessors are used when calling get_errno() or set_errno()
@@ -18,9 +20,69 @@
     def __setitem__(self, index, value):
         assert index == 0
         ll2ctypes.TLS.errno = value
+if os.name == 'nt':
+    separate_module_sources =['''
+        /* Lifted completely from CPython 3.3 Modules/posix_module.c */
+        #include <malloc.h> /* for _msize */
+        typedef struct {
+            intptr_t osfhnd;
+            char osfile;
+        } my_ioinfo;
+        extern __declspec(dllimport) char * __pioinfo[];
+        #define IOINFO_L2E 5
+        #define IOINFO_ARRAY_ELTS   (1 << IOINFO_L2E)
+        #define IOINFO_ARRAYS 64
+        #define _NHANDLE_           (IOINFO_ARRAYS * IOINFO_ARRAY_ELTS)
+        #define FOPEN 0x01
+        #define _NO_CONSOLE_FILENO (intptr_t)-2
 
+        /* This function emulates what the windows CRT
+            does to validate file handles */
+        int
+        _PyVerify_fd(int fd)
+        {
+            const int i1 = fd >> IOINFO_L2E;
+            const int i2 = fd & ((1 << IOINFO_L2E) - 1);
+
+            static size_t sizeof_ioinfo = 0;
+
+            /* Determine the actual size of the ioinfo structure,
+             * as used by the CRT loaded in memory
+             */
+            if (sizeof_ioinfo == 0 && __pioinfo[0] != NULL) {
+                sizeof_ioinfo = _msize(__pioinfo[0]) / IOINFO_ARRAY_ELTS;
+            }
+            if (sizeof_ioinfo == 0) {
+                /* This should not happen... */
+                goto fail;
+            }
+
+            /* See that it isn't a special CLEAR fileno */
+                if (fd != _NO_CONSOLE_FILENO) {
+                /* Microsoft CRT would check that 0<=fd<_nhandle but we can't 
do that.  Instead
+                 * we check pointer validity and other info
+                 */
+                if (0 <= i1 && i1 < IOINFO_ARRAYS && __pioinfo[i1] != NULL) {
+                    /* finally, check that the file is open */
+                    my_ioinfo* info = (my_ioinfo*)(__pioinfo[i1] + i2 * 
sizeof_ioinfo);
+                    if (info->osfile & FOPEN) {
+                        return 1;
+                    }
+                }
+            }
+          fail:
+            errno = EBADF;
+            return 0;
+        }
+    ''',]
+    export_symbols = ['_PyVerify_fd']
+else:
+    separate_module_sources = []
+    export_symbols = []
 errno_eci = ExternalCompilationInfo(
-    includes=['errno.h']
+    includes=['errno.h','stdio.h'],
+    separate_module_sources = separate_module_sources,
+    export_symbols = export_symbols,
 )
 
 _get_errno, _set_errno = CExternVariable(INT, 'errno', errno_eci,
@@ -35,6 +97,21 @@
 def set_errno(errno):
     _set_errno(rffi.cast(INT, errno))
 
+if os.name == 'nt':
+    _validate_fd = rffi.llexternal(
+        "_PyVerify_fd", [rffi.INT], rffi.INT,
+        compilation_info=errno_eci,
+        )
+    @jit.dont_look_inside
+    def validate_fd(fd):
+        if not _validate_fd(fd):
+            raise OSError(get_errno(), 'Bad file descriptor')
+else:
+    def _validate_fd(fd):
+        return 1
+
+    def validate_fd(fd):
+        return 1
 
 def closerange(fd_low, fd_high):
     # this behaves like os.closerange() from Python 2.6.
diff --git a/pypy/rlib/test/test_rposix.py b/pypy/rlib/test/test_rposix.py
--- a/pypy/rlib/test/test_rposix.py
+++ b/pypy/rlib/test/test_rposix.py
@@ -131,3 +131,15 @@
                 os.rmdir(self.ufilename)
             except Exception:
                 pass
+
+    def test_validate_fd(self):
+        if os.name != 'nt':
+            skip('relevant for windows only')
+        assert rposix._validate_fd(0) == 1
+        fid = open(str(udir.join('validate_test.txt')), 'w')
+        fd = fid.fileno()
+        assert rposix._validate_fd(fd) == 1
+        fid.close()
+        assert rposix._validate_fd(fd) == 0
+
+
diff --git a/pypy/rpython/annlowlevel.py b/pypy/rpython/annlowlevel.py
--- a/pypy/rpython/annlowlevel.py
+++ b/pypy/rpython/annlowlevel.py
@@ -488,6 +488,8 @@
     else:
         TO = PTR
     if not hasattr(object, '_carry_around_for_tests'):
+        if object is None:
+            return lltype.nullptr(PTR.TO)
         assert not hasattr(object, '_TYPE')
         object._carry_around_for_tests = True
         object._TYPE = TO
@@ -557,6 +559,8 @@
     """NOT_RPYTHON: hack. Reverse the hacking done in cast_object_to_ptr()."""
     if isinstance(lltype.typeOf(ptr), lltype.Ptr):
         ptr = ptr._as_obj()
+        if ptr is None:
+            return None
     if not isinstance(ptr, Class):
         raise NotImplementedError("cast_base_ptr_to_instance: casting %r to %r"
                                   % (ptr, Class))
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
@@ -1167,7 +1167,7 @@
         try:
             return self._lookup_adtmeth(field_name)
         except AttributeError:
-            raise AttributeError("%r instance has no field %r" % 
(self._T._name,
+            raise AttributeError("%r instance has no field %r" % (self._T,
                                                                   field_name))
 
     def __setattr__(self, field_name, val):
diff --git a/pypy/rpython/memory/gc/minimark.py 
b/pypy/rpython/memory/gc/minimark.py
--- a/pypy/rpython/memory/gc/minimark.py
+++ b/pypy/rpython/memory/gc/minimark.py
@@ -916,7 +916,7 @@
         ll_assert(not self.is_in_nursery(obj),
                   "object in nursery after collection")
         # similarily, all objects should have this flag:
-        ll_assert(self.header(obj).tid & GCFLAG_TRACK_YOUNG_PTRS,
+        ll_assert(self.header(obj).tid & GCFLAG_TRACK_YOUNG_PTRS != 0,
                   "missing GCFLAG_TRACK_YOUNG_PTRS")
         # the GCFLAG_VISITED should not be set between collections
         ll_assert(self.header(obj).tid & GCFLAG_VISITED == 0,
diff --git a/pypy/rpython/memory/gc/semispace.py 
b/pypy/rpython/memory/gc/semispace.py
--- a/pypy/rpython/memory/gc/semispace.py
+++ b/pypy/rpython/memory/gc/semispace.py
@@ -640,7 +640,7 @@
         between collections."""
         tid = self.header(obj).tid
         if tid & GCFLAG_EXTERNAL:
-            ll_assert(tid & GCFLAG_FORWARDED, "bug: external+!forwarded")
+            ll_assert(tid & GCFLAG_FORWARDED != 0, "bug: external+!forwarded")
             ll_assert(not (self.tospace <= obj < self.free),
                       "external flag but object inside the semispaces")
         else:
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
@@ -8,7 +8,6 @@
 from pypy.rpython.memory.gcheader import GCHeaderBuilder
 from pypy.rlib.rarithmetic import ovfcheck
 from pypy.rlib import 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
diff --git a/pypy/rpython/test/test_llann.py b/pypy/rpython/test/test_llann.py
--- a/pypy/rpython/test/test_llann.py
+++ b/pypy/rpython/test/test_llann.py
@@ -9,6 +9,7 @@
 from pypy.rpython.annlowlevel import MixLevelHelperAnnotator
 from pypy.rpython.annlowlevel import PseudoHighLevelCallable
 from pypy.rpython.annlowlevel import llhelper, cast_instance_to_base_ptr
+from pypy.rpython.annlowlevel import cast_base_ptr_to_instance
 from pypy.rpython.annlowlevel import base_ptr_lltype
 from pypy.rpython.llinterp import LLInterpreter
 from pypy.rpython.test.test_llinterp import interpret
@@ -502,7 +503,10 @@
             self.y = y
 
     def f(x, y):
-        a = A(x, y)
+        if x > 20:
+            a = None
+        else:
+            a = A(x, y)
         a1 = cast_instance_to_base_ptr(a)
         return a1
 
@@ -510,3 +514,30 @@
     assert typeOf(res) == base_ptr_lltype()
     assert fishllattr(res, 'x') == 5
     assert fishllattr(res, 'y') == 10
+
+    res = interpret(f, [25, 10])
+    assert res == nullptr(base_ptr_lltype().TO)
+
+
+def test_cast_base_ptr_to_instance():
+    class A:
+        def __init__(self, x, y):
+            self.x = x
+            self.y = y
+
+    def f(x, y):
+        if x > 20:
+            a = None
+        else:
+            a = A(x, y)
+        a1 = cast_instance_to_base_ptr(a)
+        b = cast_base_ptr_to_instance(A, a1)
+        return a is b
+
+    assert f(5, 10) is True
+    assert f(25, 10) is True
+
+    res = interpret(f, [5, 10])
+    assert res is True
+    res = interpret(f, [25, 10])
+    assert res is True
diff --git a/pypy/rpython/tool/rffi_platform.py 
b/pypy/rpython/tool/rffi_platform.py
--- a/pypy/rpython/tool/rffi_platform.py
+++ b/pypy/rpython/tool/rffi_platform.py
@@ -379,7 +379,7 @@
         self.name = name
 
     def prepare_code(self):
-        yield 'if ((%s) < 0) {' % (self.name,)
+        yield 'if ((%s) <= 0) {' % (self.name,)
         yield '    long long x = (long long)(%s);' % (self.name,)
         yield '    printf("value: %lld\\n", x);'
         yield '} else {'
@@ -401,7 +401,7 @@
     def prepare_code(self):
         yield '#ifdef %s' % self.macro
         yield 'dump("defined", 1);'
-        yield 'if ((%s) < 0) {' % (self.macro,)
+        yield 'if ((%s) <= 0) {' % (self.macro,)
         yield '    long long x = (long long)(%s);' % (self.macro,)
         yield '    printf("value: %lld\\n", x);'
         yield '} else {'
diff --git a/pypy/tool/compare_last_builds.py b/pypy/tool/compare_last_builds.py
new file mode 100644
--- /dev/null
+++ b/pypy/tool/compare_last_builds.py
@@ -0,0 +1,122 @@
+import os
+import urllib2
+import json
+import sys
+import md5
+
+wanted = sys.argv[1:]
+if not wanted:
+    wanted = ['default']
+base = "http://buildbot.pypy.org/json/builders/";
+
+cachedir = os.environ.get('PYPY_BUILDS_CACHE')
+if cachedir and not os.path.exists(cachedir):
+    os.makedirs(cachedir)
+
+
+
+def get_json(url, cache=cachedir):
+    return json.loads(get_data(url, cache))
+
+
+def get_data(url, cache=cachedir):
+    url = str(url)
+    if cache:
+        digest = md5.md5()
+        digest.update(url)
+        digest = digest.hexdigest()
+        cachepath = os.path.join(cachedir, digest)
+        if os.path.exists(cachepath):
+            with open(cachepath) as fp:
+                return fp.read()
+
+    print 'GET', url
+    fp = urllib2.urlopen(url)
+    try:
+        data = fp.read()
+        if cache:
+            with open(cachepath, 'wb') as cp:
+                cp.write(data)
+        return data
+    finally:
+        fp.close()
+
+def parse_log(log):
+    items = []
+    for v in log.splitlines(1):
+        if not v[0].isspace() and v[1].isspace():
+            items.append(v)
+    return sorted(items) #sort cause testrunner order is non-deterministic
+
+def gather_logdata(build):
+    logdata = get_data(str(build['log']) + '?as_text=1')
+    logdata = logdata.replace('</span><span class="stdout">', '')
+    logdata = logdata.replace('</span></pre>', '')
+    del build['log']
+    build['log'] = parse_log(logdata)
+
+
+def branch_mapping(l):
+    keep = 3 - len(wanted)
+    d = {}
+    for x in reversed(l):
+        gather_logdata(x)
+        if not x['log']:
+            continue
+        b = x['branch']
+        if b not in d:
+            d[b] = []
+        d[b].insert(0, x)
+        if len(d[b]) > keep:
+            d[b].pop()
+    return d
+
+def cleanup_build(d):
+    for a in 'times eta steps slave reason sourceStamp blame currentStep 
text'.split():
+        del d[a]
+
+    props = d.pop(u'logs')
+    for name, val in props:
+        if name == u'pytestLog':
+            d['log'] = val
+    props = d.pop(u'properties')
+    for name, val, _ in props:
+        if name == u'branch':
+            d['branch'] = val or 'default'
+    return d
+
+def collect_builds(d):
+    name = str(d['basedir'])
+    builds = d['cachedBuilds']
+    l = []
+    for build in builds:
+        d = get_json(base + '%s/builds/%s' % (name, build))
+        cleanup_build(d)
+        l.append(d)
+
+    l = [x for x in l if x['branch'] in wanted and 'log' in x]
+    d = branch_mapping(l)
+    return [x for lst in d.values() for x in lst]
+
+
+def only_linux32(d):
+    return d['own-linux-x86-32']
+
+
+own_builds = get_json(base, cache=False)['own-linux-x86-32']
+
+builds = collect_builds(own_builds)
+
+
+builds.sort(key=lambda x: (wanted.index(x['branch']), x['number']))
+logs = [x.pop('log') for x in builds]
+for b, s in zip(builds, logs):
+    b['resultset'] = len(s)
+import pprint
+pprint.pprint(builds)
+
+from difflib import Differ
+
+for x in Differ().compare(*logs):
+    if x[0]!=' ':
+        sys.stdout.write(x)
diff --git a/pypy/translator/c/src/cjkcodecs/cjkcodecs.h 
b/pypy/translator/c/src/cjkcodecs/cjkcodecs.h
--- a/pypy/translator/c/src/cjkcodecs/cjkcodecs.h
+++ b/pypy/translator/c/src/cjkcodecs/cjkcodecs.h
@@ -210,15 +210,15 @@
 
 #define BEGIN_CODECS_LIST /* empty */
 #define _CODEC(name)                                                    \
-  static const MultibyteCodec _pypy_cjkcodec_##name;                    \
-  const MultibyteCodec *pypy_cjkcodec_##name(void) {                    \
+  static MultibyteCodec _pypy_cjkcodec_##name;                          \
+  MultibyteCodec *pypy_cjkcodec_##name(void) {                          \
     if (_pypy_cjkcodec_##name.codecinit != NULL) {                      \
       int r = _pypy_cjkcodec_##name.codecinit(_pypy_cjkcodec_##name.config); \
       assert(r == 0);                                                   \
     }                                                                   \
     return &_pypy_cjkcodec_##name;                                      \
   }                                                                     \
-  static const MultibyteCodec _pypy_cjkcodec_##name
+  static MultibyteCodec _pypy_cjkcodec_##name
 #define _STATEFUL_METHODS(enc)          \
     enc##_encode,                       \
     enc##_encode_init,                  \
diff --git a/pypy/translator/c/src/cjkcodecs/multibytecodec.h 
b/pypy/translator/c/src/cjkcodecs/multibytecodec.h
--- a/pypy/translator/c/src/cjkcodecs/multibytecodec.h
+++ b/pypy/translator/c/src/cjkcodecs/multibytecodec.h
@@ -131,7 +131,7 @@
 /* list of codecs defined in the .c files */
 
 #define DEFINE_CODEC(name)                              \
-    const MultibyteCodec *pypy_cjkcodec_##name(void);
+    MultibyteCodec *pypy_cjkcodec_##name(void);
 
 // _codecs_cn
 DEFINE_CODEC(gb2312)
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to