Commits

Manuel Jacob  committed ee8c966 Merge

hg merge default

  • Participants
  • Parent commits ef7c915, 3e3517a
  • Branches refactor-str-types

Comments (0)

Files changed (28)

File pypy/doc/cppyy.rst

 the selection of scientific software) will also work for a build with the
 builtin backend.
 
-.. _`download`: http://cern.ch/wlav/reflex-2013-04-23.tar.bz2
+.. _`download`: http://cern.ch/wlav/reflex-2013-08-14.tar.bz2
 .. _`ROOT`: http://root.cern.ch/
 
 Besides Reflex, you probably need a version of `gccxml`_ installed, which is
 
 To install the standalone version of Reflex, after download::
 
-    $ tar jxf reflex-2013-04-23.tar.bz2
-    $ cd reflex-2013-04-23
+    $ tar jxf reflex-2013-08-14.tar.bz2
+    $ cd reflex-2013-08-14
     $ ./build/autogen
     $ ./configure <usual set of options such as --prefix>
     $ make && make install

File pypy/interpreter/app_main.py

     except:
         try:
             stderr = sys.stderr
-        except AttributeError:
-            pass   # too bad
-        else:
             print >> stderr, 'Error calling sys.excepthook:'
             originalexcepthook(*sys.exc_info())
             print >> stderr
             print >> stderr, 'Original exception was:'
+        except:
+            pass   # too bad
 
     # we only get here if sys.excepthook didn't do its job
     originalexcepthook(etype, evalue, etraceback)

File pypy/module/__pypy__/test/test_signal.py

         import __pypy__, thread, signal, time, sys
 
         def subthread():
+            print('subthread started')
             try:
                 with __pypy__.thread.signals_enabled:
                     thread.interrupt_main()
                     for i in range(10):
-                        print 'x'
+                        print('x')
                         time.sleep(0.1)
             except BaseException, e:
                 interrupted.append(e)
             finally:
-                print 'subthread stops, interrupted=%r' % (interrupted,)
+                print('subthread stops, interrupted=%r' % (interrupted,))
                 done.append(None)
 
         # This is normally called by app_main.py
             try:
                 done = []
                 interrupted = []
-                print '--- start ---'
+                print('--- start ---')
                 thread.start_new_thread(subthread, ())
                 for j in range(10):
                     if len(done): break
-                    print '.'
+                    print('.')
                     time.sleep(0.1)
-                print 'main thread loop done'
+                print('main thread loop done')
                 assert len(done) == 1
                 assert len(interrupted) == 1
                 assert 'KeyboardInterrupt' in interrupted[0].__class__.__name__
         def threadfunction():
             pid = fork()
             if pid == 0:
-                print 'in child'
+                print('in child')
                 # signal() only works from the 'main' thread
                 signal.signal(signal.SIGUSR1, signal.SIG_IGN)
                 os._exit(42)

File pypy/module/_file/interp_file.py

         return self.getrepr(self.space, info)
 
     def getdisplayname(self):
+        space = self.space
         w_name = self.w_name
         if w_name is None:
             return '?'
-        elif self.space.is_true(self.space.isinstance(w_name,
-                                                      self.space.w_str)):
-            return "'%s'" % self.space.str_w(w_name)
+        elif space.isinstance_w(w_name, space.w_str):
+            return "'%s'" % space.str_w(w_name)
         else:
-            return self.space.str_w(self.space.repr(w_name))
+            return space.str_w(space.repr(w_name))
 
     def file_writelines(self, w_lines):
         """writelines(sequence_of_strings) -> None.  Write the strings to the file.

File pypy/module/array/interp_array.py

 from rpython.rlib.unroll import unrolling_iterable
 from rpython.rlib.objectmodel import keepalive_until_here
 from rpython.rtyper.lltypesystem import lltype, rffi
-
+from pypy.objspace.std.floatobject import W_FloatObject
 
 @unwrap_spec(typecode=str)
 def w_array(space, w_cls, typecode, __args__):
 
 
 class TypeCode(object):
-    def __init__(self, itemtype, unwrap, canoverflow=False, signed=False):
+    def __init__(self, itemtype, unwrap, canoverflow=False, signed=False, method='__int__'):
         self.itemtype = itemtype
         self.bytes = rffi.sizeof(itemtype)
         self.arraytype = lltype.Array(itemtype, hints={'nolength': True})
         self.signed = signed
         self.canoverflow = canoverflow
         self.w_class = None
+        self.method = method
 
         if self.canoverflow:
             assert self.bytes <= rffi.sizeof(rffi.ULONG)
         return True
 
 types = {
-    'c': TypeCode(lltype.Char,        'str_w'),
-    'u': TypeCode(lltype.UniChar,     'unicode_w'),
+    'c': TypeCode(lltype.Char,        'str_w', method=''),
+    'u': TypeCode(lltype.UniChar,     'unicode_w', method=''),
     'b': TypeCode(rffi.SIGNEDCHAR,    'int_w', True, True),
     'B': TypeCode(rffi.UCHAR,         'int_w', True),
     'h': TypeCode(rffi.SHORT,         'int_w', True, True),
                                                     # rbigint.touint() which
                                                     # corresponds to the
                                                     # C-type unsigned long
-    'f': TypeCode(lltype.SingleFloat, 'float_w'),
-    'd': TypeCode(lltype.Float,       'float_w'),
+    'f': TypeCode(lltype.SingleFloat, 'float_w', method='__float__'),
+    'd': TypeCode(lltype.Float,       'float_w', method='__float__'),
     }
 for k, v in types.items():
     v.typecode = k
         def item_w(self, w_item):
             space = self.space
             unwrap = getattr(space, mytype.unwrap)
-            item = unwrap(w_item)
+            try:
+                item = unwrap(w_item)
+            except OperationError, e:
+                if isinstance(w_item, W_FloatObject): # Odd special case from cpython
+                    raise
+                if mytype.method != '' and e.match(space, space.w_TypeError):
+                    try:
+                        item = unwrap(space.call_method(w_item, mytype.method))
+                    except OperationError:
+                        msg = 'array item must be ' + mytype.unwrap[:-2]
+                        raise OperationError(space.w_TypeError, space.wrap(msg))                        
+                else:
+                    raise
             if mytype.unwrap == 'bigint_w':
                 try:
                     item = item.touint()

File pypy/module/array/test/test_array.py

         assert l
         assert l[0] is None or len(l[0]) == 0
 
+    def test_assign_object_with_special_methods(self):
+        from array import array
+        
+        class Num(object):
+            def __float__(self):
+                return 5.25
+                
+            def __int__(self):
+                return 7
+                
+        class NotNum(object):
+            pass
+        
+        class Silly(object):
+            def __float__(self):
+                return None
+                
+            def __int__(self):
+                return None         
+
+        class OldNum:
+            def __float__(self):
+                return 6.25
+                
+            def __int__(self):
+                return 8
+                
+        class OldNotNum:
+            pass
+        
+        class OldSilly:
+            def __float__(self):
+                return None
+                
+            def __int__(self):
+                return None
+                
+        for tc in 'bBhHiIlL':
+            a = array(tc, [0])
+            raises(TypeError, a.__setitem__, 0, 1.0)
+            a[0] = 1
+            a[0] = Num()
+            assert a[0] == 7
+            raises(TypeError, a.__setitem__, NotNum())
+            a[0] = OldNum()
+            assert a[0] == 8
+            raises(TypeError, a.__setitem__, OldNotNum())
+            raises(TypeError, a.__setitem__, Silly())
+            raises(TypeError, a.__setitem__, OldSilly())
+
+        for tc in 'fd':
+            a = array(tc, [0])
+            a[0] = 1.0
+            a[0] = 1
+            a[0] = Num()        
+            assert a[0] == 5.25
+            raises(TypeError, a.__setitem__, NotNum())
+            a[0] = OldNum()
+            assert a[0] == 6.25
+            raises(TypeError, a.__setitem__, OldNotNum())
+            raises(TypeError, a.__setitem__, Silly())
+            raises(TypeError, a.__setitem__, OldSilly())
+            
+        a = array('c', 'hi')
+        a[0] = 'b'
+        assert a[0] == 'b'
+            
+        a = array('u', u'hi')
+        a[0] = u'b'
+        assert a[0] == u'b'
+        
 
 class TestCPythonsOwnArray(BaseArrayTests):
 

File pypy/module/cppyy/genreflex-methptrgetter.patch

      # The next is to avoid a known problem with gccxml that it generates a
      # references to id equal '_0' which is not defined anywhere
      self.xref['_0'] = {'elem':'Unknown', 'attrs':{'id':'_0','name':''}, 'subelems':[]}
-@@ -1306,6 +1307,8 @@
+@@ -1328,6 +1329,8 @@
      bases = self.getBases( attrs['id'] )
      if inner and attrs.has_key('demangled') and self.isUnnamedType(attrs['demangled']) :
        cls = attrs['demangled']
        clt = ''
      else:
        cls = self.genTypeName(attrs['id'],const=True,colon=True)
-@@ -1343,7 +1346,7 @@
+@@ -1365,7 +1368,7 @@
        # Inner class/struct/union/enum.
        for m in memList :
          member = self.xref[m]
             and member['attrs'].get('access') in ('private','protected') \
             and not self.isUnnamedType(member['attrs'].get('demangled')):
            cmem = self.genTypeName(member['attrs']['id'],const=True,colon=True)
-@@ -1981,8 +1984,15 @@
+@@ -2003,8 +2006,15 @@
      else    : params  = '0'
      s = '  .AddFunctionMember(%s, Reflex::Literal("%s"), %s%s, 0, %s, %s)' % (self.genTypeID(id), name, type, id, params, mod)
      s += self.genCommentProperty(attrs)
    def genMCODef(self, type, name, attrs, args):
      id       = attrs['id']
      cl       = self.genTypeName(attrs['context'],colon=True)
-@@ -2049,8 +2059,44 @@
+@@ -2071,8 +2081,44 @@
            if returns == 'void' : body += '  }\n'
            else :                 body += '  }\n'
      body += '}\n'
        -h, --help
           Print this help\n
       """ 
-@@ -127,7 +131,8 @@
-       opts, args = getopt.getopt(options, 'ho:s:c:I:U:D:PC', \
+@@ -128,7 +132,7 @@
        ['help','debug=', 'output=','selection_file=','pool','dataonly','interpreteronly','deep','gccxmlpath=',
         'capabilities=','rootmap=','rootmap-lib=','comments','iocomments','no_membertypedefs',
--       'fail_on_warnings', 'quiet', 'gccxmlopt=', 'reflex', 'split=','no_templatetypedefs','gccxmlpost='])
-+       'fail_on_warnings', 'quiet', 'gccxmlopt=', 'reflex', 'split=','no_templatetypedefs','gccxmlpost=',
-+       'with-methptrgetter'])
+        'fail_on_warnings', 'quiet', 'gccxmlopt=', 'reflex', 'split=','no_templatetypedefs','gccxmlpost=',
+-       'library='])
++       'library=', 'with-methptrgetter'])
      except getopt.GetoptError, e:
        print "--->> genreflex: ERROR:",e
        self.usage(2)
-@@ -186,6 +191,8 @@
+@@ -187,6 +191,8 @@
          self.rootmap = a
        if o in ('--rootmap-lib',):
          self.rootmaplib = a

File pypy/module/micronumpy/__init__.py

         ("deg2rad", "radians"),
         ("rad2deg", "degrees"),
         ("reciprocal", "reciprocal"),
+        ("rint", "rint"),
         ("sign", "sign"),
         ("signbit", "signbit"),
         ("sin", "sin"),
         ('logaddexp2', 'logaddexp2'),
         ('real', 'real'),
         ('imag', 'imag'),
+        ('ones_like', 'ones_like'),
+        ('zeros_like', 'zeros_like'),
     ]:
         interpleveldefs[exposed] = "interp_ufuncs.get(space).%s" % impl
 

File pypy/module/micronumpy/interp_ufuncs.py

             ("positive", "pos", 1),
             ("negative", "neg", 1),
             ("absolute", "abs", 1, {"complex_to_float": True}),
+            ("rint", "rint", 1),
             ("sign", "sign", 1, {"promote_bools": True}),
             ("signbit", "signbit", 1, {"bool_result": True,
                                        "allow_complex": False}),
                                        "allow_complex": False}),
             ("logaddexp2", "logaddexp2", 2, {"promote_to_float": True,
                                        "allow_complex": False}),
+            ("ones_like", "ones_like", 1),
+            ("zeros_like", "zeros_like", 1),
         ]:
             self.add_ufunc(space, *ufunc_def)
 

File pypy/module/micronumpy/test/test_complex.py

                                    msg=error_message)
                 sys.stderr.write('.')
             sys.stderr.write('\n')
+
+    def test_complexbox_to_pycomplex(self):
+        from numpypy import complex128
+        x = complex128(3.4j)
+        assert complex(x) == 3.4j

File pypy/module/micronumpy/test/test_ufuncs.py

         for i in range(3):
             assert c[i] == a[i] * b[i]
 
+    def test_rint(self):
+        from numpypy import array, complex, rint, isnan
+
+        nnan, nan, inf, ninf = float('-nan'), float('nan'), float('inf'), float('-inf')
+
+        reference = array([ninf, -2., -1., -0., 0., 0., 0., 1., 2., inf])
+        a = array([ninf, -1.5, -1., -0.5, -0., 0., 0.5, 1., 1.5, inf])
+        b = rint(a)
+        for i in range(len(a)):
+            assert b[i] == reference[i]
+        assert isnan(rint(nan))
+        assert isnan(rint(nnan))
+
+        assert rint(complex(inf, 1.5)) == complex(inf, 2.)
+        assert rint(complex(0.5, inf)) == complex(0., inf)
+
     def test_sign(self):
         from numpypy import array, sign, dtype
 
         assert logaddexp2(float('inf'), float('-inf')) == float('inf')
         assert logaddexp2(float('inf'), float('inf')) == float('inf')
 
+    def test_ones_like(self):
+        from numpypy import array, ones_like
 
+        assert ones_like(False) == array(True)
+        assert ones_like(2) == array(1)
+        assert ones_like(2.) == array(1.)
+        assert ones_like(complex(2)) == array(complex(1))
+
+    def test_zeros_like(self):
+        from numpypy import array, zeros_like
+
+        assert zeros_like(True) == array(False)
+        assert zeros_like(2) == array(0)
+        assert zeros_like(2.) == array(0.)
+        assert zeros_like(complex(2)) == array(complex(0))

File pypy/module/micronumpy/types.py

     def min(self, v1, v2):
         return min(v1, v2)
 
+    @simple_unary_op
+    def rint(self, v):
+        if isfinite(v):
+            return rfloat.round_double(v, 0, half_even=True)
+        else:
+            return v
+
+    @simple_unary_op
+    def ones_like(self, v):
+        return 1
+
+    @simple_unary_op
+    def zeros_like(self, v):
+        return 0
+
+
 class NonNativePrimitive(Primitive):
     _mixin_ = True
 
     def round(self, v, decimals=0):
         ans = list(self.for_computation(self.unbox(v)))
         if isfinite(ans[0]):
-            ans[0] = rfloat.round_double(ans[0], decimals,  half_even=True)
+            ans[0] = rfloat.round_double(ans[0], decimals, half_even=True)
         if isfinite(ans[1]):
-            ans[1] = rfloat.round_double(ans[1], decimals,  half_even=True)
+            ans[1] = rfloat.round_double(ans[1], decimals, half_even=True)
         return self.box_complex(ans[0], ans[1])
 
+    def rint(self, v):
+        return self.round(v)
+
     # No floor, ceil, trunc in numpy for complex
     #@simple_unary_op
     #def floor(self, v):
         except ValueError:
             return rfloat.NAN, rfloat.NAN
 
+    @complex_unary_op
+    def ones_like(self, v):
+        return 1, 0
+
+    @complex_unary_op
+    def zeros_like(self, v):
+        return 0, 0
+
+
 class Complex64(ComplexFloating, BaseType):
     _attrs_ = ()
 

File pypy/module/posix/interp_posix.py

     for hook in get_fork_hooks(where):
         hook(space)
 
-def fork(space):
+def _run_forking_function(space, kind):
     run_fork_hooks('before', space)
-
     try:
-        pid = os.fork()
+        if kind == "F":
+            pid = os.fork()
+            master_fd = -1
+        elif kind == "P":
+            pid, master_fd = os.forkpty()
+        else:
+            raise AssertionError
     except OSError, e:
         try:
             run_fork_hooks('parent', space)
             # Don't clobber the OSError if the fork failed
             pass
         raise wrap_oserror(space, e)
-
     if pid == 0:
         run_fork_hooks('child', space)
     else:
         run_fork_hooks('parent', space)
+    return pid, master_fd
 
+def fork(space):
+    pid, irrelevant = _run_forking_function(space, "F")
     return space.wrap(pid)
 
 def openpty(space):
     return space.newtuple([space.wrap(master_fd), space.wrap(slave_fd)])
 
 def forkpty(space):
-    try:
-        pid, master_fd = os.forkpty()
-    except OSError, e:
-        raise wrap_oserror(space, e)
+    pid, master_fd = _run_forking_function(space, "P")
     return space.newtuple([space.wrap(pid),
                            space.wrap(master_fd)])
 

File pypy/objspace/std/bytearrayobject.py

File contents unchanged.

File pypy/objspace/std/bytesobject.py

File contents unchanged.

File pypy/objspace/std/complextype.py

     if w_z is not None:
         # __complex__() must return a complex or (float,int,long) object
         # (XXX should not use isinstance here)
-        if not strict_typing and (space.isinstance_w(w_z, space.w_int) or 
+        if not strict_typing and (space.isinstance_w(w_z, space.w_int) or
                                   space.isinstance_w(w_z, space.w_long) or
                                   space.isinstance_w(w_z, space.w_float)):
             return (space.float_w(w_z), 0.0)
     #
     # no '__complex__' method, so we assume it is a float,
     # unless it is an instance of some subclass of complex.
-    if isinstance(w_complex, W_ComplexObject):
-        return (w_complex.realval, w_complex.imagval)
+    if space.isinstance_w(w_complex, space.gettypefor(W_ComplexObject)):
+        real = space.float(space.getattr(w_complex, space.wrap("real")))
+        imag = space.float(space.getattr(w_complex, space.wrap("imag")))
+        return (space.float_w(real), space.float_w(imag))
     #
     # Check that it is not a string (on which space.float() would succeed).
     if (space.isinstance_w(w_complex, space.w_str) or

File pypy/objspace/std/intobject.py

 from pypy.interpreter.error import OperationError
 from pypy.objspace.std import newformat
-from pypy.objspace.std.inttype import wrapint, W_AbstractIntObject
+from pypy.objspace.std.inttype import W_AbstractIntObject
 from pypy.objspace.std.model import registerimplementation, W_Object
 from pypy.objspace.std.multimethod import FailedToImplementArgs
 from pypy.objspace.std.noneobject import W_NoneObject
         if space.is_w(space.type(self), space.w_int):
             return self
         a = self.intval
-        return wrapint(space, a)
+        return space.newint(a)
 
 registerimplementation(W_IntObject)
 
     except OverflowError:
         raise FailedToImplementArgs(space.w_OverflowError,
                                 space.wrap("integer addition"))
-    return wrapint(space, z)
+    return space.newint(z)
 
 def sub__Int_Int(space, w_int1, w_int2):
     x = w_int1.intval
     except OverflowError:
         raise FailedToImplementArgs(space.w_OverflowError,
                                 space.wrap("integer substraction"))
-    return wrapint(space, z)
+    return space.newint(z)
 
 def mul__Int_Int(space, w_int1, w_int2):
     x = w_int1.intval
     except OverflowError:
         raise FailedToImplementArgs(space.w_OverflowError,
                                 space.wrap("integer multiplication"))
-    return wrapint(space, z)
+    return space.newint(z)
 
 def floordiv__Int_Int(space, w_int1, w_int2):
     x = w_int1.intval
     except OverflowError:
         raise FailedToImplementArgs(space.w_OverflowError,
                                 space.wrap("integer division"))
-    return wrapint(space, z)
+    return space.newint(z)
 div__Int_Int = floordiv__Int_Int
 
 def truediv__Int_Int(space, w_int1, w_int2):
     except OverflowError:
         raise FailedToImplementArgs(space.w_OverflowError,
                                 space.wrap("integer modulo"))
-    return wrapint(space, z)
+    return space.newint(z)
 
 def divmod__Int_Int(space, w_int1, w_int2):
     x = w_int1.intval
     except OverflowError:
         raise FailedToImplementArgs(space.w_OverflowError,
                                 space.wrap("integer negation"))
-    return wrapint(space, x)
+    return space.newint(x)
 get_negint = neg__Int
 
 
 def invert__Int(space, w_int1):
     x = w_int1.intval
     a = ~x
-    return wrapint(space, a)
+    return space.newint(a)
 
 def lshift__Int_Int(space, w_int1, w_int2):
     a = w_int1.intval
         except OverflowError:
             raise FailedToImplementArgs(space.w_OverflowError,
                                     space.wrap("integer left shift"))
-        return wrapint(space, c)
+        return space.newint(c)
     if b < 0:
         raise OperationError(space.w_ValueError,
                              space.wrap("negative shift count"))
                 a = 0
     else:
         a = a >> b
-    return wrapint(space, a)
+    return space.newint(a)
 
 def and__Int_Int(space, w_int1, w_int2):
     a = w_int1.intval
     b = w_int2.intval
     res = a & b
-    return wrapint(space, res)
+    return space.newint(res)
 
 def xor__Int_Int(space, w_int1, w_int2):
     a = w_int1.intval
     b = w_int2.intval
     res = a ^ b
-    return wrapint(space, res)
+    return space.newint(res)
 
 def or__Int_Int(space, w_int1, w_int2):
     a = w_int1.intval
     b = w_int2.intval
     res = a | b
-    return wrapint(space, res)
+    return space.newint(res)
 
 def pos__Int(self, space):
     return self.int(space)
     return space.wrap(hex(w_int1.intval))
 
 def getnewargs__Int(space, w_int1):
-    return space.newtuple([wrapint(space, w_int1.intval)])
+    return space.newtuple([space.newint(w_int1.intval)])
 
 
 register_all(vars())

File pypy/objspace/std/listobject.py

 from pypy.objspace.std.bytesobject import W_BytesObject
 from pypy.objspace.std.floatobject import W_FloatObject
 from pypy.objspace.std.intobject import W_IntObject
-from pypy.objspace.std.inttype import wrapint
 from pypy.objspace.std.iterobject import (W_FastListIterObject,
     W_ReverseSeqIterObject)
 from pypy.objspace.std.sliceobject import W_SliceObject, normalize_simple_slice
 
     def descr_len(self, space):
         result = self.length()
-        return wrapint(space, result)
+        return space.newint(result)
 
     def descr_iter(self, space):
         return W_FastListIterObject(self)

File pypy/objspace/std/stringmethods.py

 from pypy.interpreter.error import OperationError, operationerrfmt
 from pypy.interpreter.gateway import unwrap_spec, WrappedDefault
 from pypy.objspace.std import slicetype
-from pypy.objspace.std.inttype import wrapint
 from pypy.objspace.std.sliceobject import W_SliceObject, normalize_simple_slice
 from rpython.rlib import jit
 from rpython.rlib.objectmodel import specialize
     @specialize.argtype(0)
     def descr_count(self, space, w_sub, w_start=None, w_end=None):
         value, start, end = self._convert_idx_params(space, w_start, w_end)
-        return wrapint(space, value.count(self._op_val(space, w_sub), start, end))
+        return space.newint(value.count(self._op_val(space, w_sub), start, end))
 
     @specialize.argtype(0)
     def descr_decode(self, space, w_encoding=None, w_errors=None):

File pypy/objspace/std/tupleobject.py

 from pypy.interpreter.gateway import (
     WrappedDefault, interp2app, interpindirect2app, unwrap_spec)
 from pypy.objspace.std import slicetype
-from pypy.objspace.std.inttype import wrapint
 from pypy.objspace.std.sliceobject import W_SliceObject, normalize_simple_slice
 from pypy.objspace.std.stdtypedef import StdTypeDef
 from pypy.objspace.std.util import negate
 
     def descr_len(self, space):
         result = self.length()
-        return wrapint(space, result)
+        return space.newint(result)
 
     def descr_iter(self, space):
         from pypy.objspace.std import iterobject

File pypy/tool/jitlogparser/parser.py

     from rpython.jit.backend.tool.viewcode import World
     world = World()
     for entry in extract_category(log, 'jit-backend-dump'):
-        world.parse(entry.splitlines(True), truncate_addr=False)
+        world.parse(entry.splitlines(True))
     dumps = {}
     for r in world.ranges:
         if r.addr in addrs and addrs[r.addr]:

File rpython/jit/backend/llsupport/rewrite.py

      - Add COND_CALLs to the write barrier before SETFIELD_GC and
        SETARRAYITEM_GC operations.
 
-    recent_mallocs contains a dictionary of variable -> None. If a variable
-    is in the dictionary, next setfields can be called without a write barrier,
-    because the variable got allocated after the last potentially collecting
-    resop
+    'write_barrier_applied' contains a dictionary of variable -> None.
+    If a variable is in the dictionary, next setfields can be called without
+    a write barrier.  The idea is that an object that was freshly allocated
+    or already write_barrier'd don't need another write_barrier if there
+    was no potentially collecting resop inbetween.
     """
 
     _previous_size = -1
         self.cpu = cpu
         self.newops = []
         self.known_lengths = {}
-        self.recent_mallocs = {}
+        self.write_barrier_applied = {}
 
     def rewrite(self, operations):
         # we can only remember one malloc since the next malloc can possibly
     def emitting_an_operation_that_can_collect(self):
         # must be called whenever we emit an operation that can collect:
         # forgets the previous MALLOC_NURSERY, if any; and empty the
-        # set 'recent_mallocs', so that future SETFIELDs will generate
+        # set 'write_barrier_applied', so that future SETFIELDs will generate
         # a write barrier as usual.
         self._op_malloc_nursery = None
-        self.recent_mallocs.clear()
+        self.write_barrier_applied.clear()
 
     def _gen_call_malloc_gc(self, args, v_result, descr):
         """Generate a CALL_MALLOC_GC with the given args."""
         self.emitting_an_operation_that_can_collect()
         op = ResOperation(rop.CALL_MALLOC_GC, args, v_result, descr)
         self.newops.append(op)
-        # mark 'v_result' as freshly malloced
-        self.recent_mallocs[v_result] = None
+        # mark 'v_result' as freshly malloced, so not needing a write barrier
+        self.write_barrier_applied[v_result] = None
 
     def gen_malloc_fixedsize(self, size, typeid, v_result):
         """Generate a CALL_MALLOC_GC(malloc_fixedsize_fn, ...).
                           [ConstInt(kind), ConstInt(itemsize), v_length],
                           v_result, descr=arraydescr)
         self.newops.append(op)
-        self.recent_mallocs[v_result] = None
+        self.write_barrier_applied[v_result] = None
         return True
 
     def gen_malloc_nursery_varsize_frame(self, sizebox, v_result):
                           v_result)
 
         self.newops.append(op)
-        self.recent_mallocs[v_result] = None
+        self.write_barrier_applied[v_result] = None
 
     def gen_malloc_nursery(self, size, v_result):
         """Try to generate or update a CALL_MALLOC_NURSERY.
         self.newops.append(op)
         self._previous_size = size
         self._v_last_malloced_nursery = v_result
-        self.recent_mallocs[v_result] = None
+        self.write_barrier_applied[v_result] = None
         return True
 
     def gen_initialize_tid(self, v_newgcobj, tid):
 
     def handle_write_barrier_setfield(self, op):
         val = op.getarg(0)
-        # no need for a write barrier in the case of previous malloc
-        if val not in self.recent_mallocs:
+        if val not in self.write_barrier_applied:
             v = op.getarg(1)
             if isinstance(v, BoxPtr) or (isinstance(v, ConstPtr) and
                                          bool(v.value)): # store a non-NULL
-                self.gen_write_barrier(op.getarg(0), v)
-                op = op.copy_and_change(rop.SETFIELD_RAW)
+                self.gen_write_barrier(val)
+                #op = op.copy_and_change(rop.SETFIELD_RAW)
         self.newops.append(op)
 
     def handle_write_barrier_setinteriorfield(self, op):
         val = op.getarg(0)
-        # no need for a write barrier in the case of previous malloc
-        if val not in self.recent_mallocs:
+        if val not in self.write_barrier_applied:
             v = op.getarg(2)
             if isinstance(v, BoxPtr) or (isinstance(v, ConstPtr) and
                                          bool(v.value)): # store a non-NULL
-                self.gen_write_barrier(op.getarg(0), v)
-                op = op.copy_and_change(rop.SETINTERIORFIELD_RAW)
+                self.gen_write_barrier(val)
+                #op = op.copy_and_change(rop.SETINTERIORFIELD_RAW)
         self.newops.append(op)
 
     def handle_write_barrier_setarrayitem(self, op):
         val = op.getarg(0)
-        # no need for a write barrier in the case of previous malloc
-        if val not in self.recent_mallocs:
+        if val not in self.write_barrier_applied:
             v = op.getarg(2)
             if isinstance(v, BoxPtr) or (isinstance(v, ConstPtr) and
                                          bool(v.value)): # store a non-NULL
-                self.gen_write_barrier_array(op.getarg(0),
-                                             op.getarg(1), v)
-                op = op.copy_and_change(rop.SETARRAYITEM_RAW)
+                self.gen_write_barrier_array(val, op.getarg(1))
+                #op = op.copy_and_change(rop.SETARRAYITEM_RAW)
         self.newops.append(op)
 
-    def gen_write_barrier(self, v_base, v_value):
+    def gen_write_barrier(self, v_base):
         write_barrier_descr = self.gc_ll_descr.write_barrier_descr
-        args = [v_base, v_value]
+        args = [v_base]
         self.newops.append(ResOperation(rop.COND_CALL_GC_WB, args, None,
                                         descr=write_barrier_descr))
+        self.write_barrier_applied[v_base] = None
 
-    def gen_write_barrier_array(self, v_base, v_index, v_value):
+    def gen_write_barrier_array(self, v_base, v_index):
         write_barrier_descr = self.gc_ll_descr.write_barrier_descr
         if write_barrier_descr.has_write_barrier_from_array(self.cpu):
             # If we know statically the length of 'v', and it is not too
             length = self.known_lengths.get(v_base, LARGE)
             if length >= LARGE:
                 # unknown or too big: produce a write_barrier_from_array
-                args = [v_base, v_index, v_value]
+                args = [v_base, v_index]
                 self.newops.append(
                     ResOperation(rop.COND_CALL_GC_WB_ARRAY, args, None,
                                  descr=write_barrier_descr))
+                # a WB_ARRAY is not enough to prevent any future write
+                # barriers, so don't add to 'write_barrier_applied'!
                 return
         # fall-back case: produce a write_barrier
-        self.gen_write_barrier(v_base, v_value)
+        self.gen_write_barrier(v_base)
 
     def round_up_for_allocation(self, size):
         if not self.gc_ll_descr.round_up:

File rpython/jit/backend/llsupport/test/test_gc.py

         rewriter = gc.GcRewriterAssembler(gc_ll_descr, None)
         newops = rewriter.newops
         v_base = BoxPtr()
-        v_value = BoxPtr()
-        rewriter.gen_write_barrier(v_base, v_value)
+        rewriter.gen_write_barrier(v_base)
         assert llop1.record == []
         assert len(newops) == 1
         assert newops[0].getopnum() == rop.COND_CALL_GC_WB
         assert newops[0].getarg(0) == v_base
-        assert newops[0].getarg(1) == v_value
         assert newops[0].result is None
         wbdescr = newops[0].getdescr()
         assert is_valid_int(wbdescr.jit_wb_if_flag)

File rpython/jit/backend/llsupport/test/test_rewrite.py

             jump()
         """, """
             [p1, p2]
-            cond_call_gc_wb(p1, p2, descr=wbdescr)
-            setfield_raw(p1, p2, descr=tzdescr)
+            cond_call_gc_wb(p1, descr=wbdescr)
+            setfield_gc(p1, p2, descr=tzdescr)
             jump()
         """)
 
             jump()
         """, """
             [p1, i2, p3]
-            cond_call_gc_wb(p1, p3, descr=wbdescr)
-            setarrayitem_raw(p1, i2, p3, descr=cdescr)
+            cond_call_gc_wb(p1, descr=wbdescr)
+            setarrayitem_gc(p1, i2, p3, descr=cdescr)
             jump()
         """)
 
             setfield_gc(p1, 8111, descr=tiddescr)
             setfield_gc(p1, 129, descr=clendescr)
             call(123456)
-            cond_call_gc_wb(p1, p3, descr=wbdescr)
-            setarrayitem_raw(p1, i2, p3, descr=cdescr)
+            cond_call_gc_wb(p1, descr=wbdescr)
+            setarrayitem_gc(p1, i2, p3, descr=cdescr)
             jump()
         """)
 
             setfield_gc(p1, 8111, descr=tiddescr)
             setfield_gc(p1, 130, descr=clendescr)
             call(123456)
-            cond_call_gc_wb_array(p1, i2, p3, descr=wbdescr)
-            setarrayitem_raw(p1, i2, p3, descr=cdescr)
+            cond_call_gc_wb_array(p1, i2, descr=wbdescr)
+            setarrayitem_gc(p1, i2, p3, descr=cdescr)
             jump()
         """)
 
             jump()
         """, """
             [p1, i2, p3]
-            cond_call_gc_wb_array(p1, i2, p3, descr=wbdescr)
-            setarrayitem_raw(p1, i2, p3, descr=cdescr)
+            cond_call_gc_wb_array(p1, i2, descr=wbdescr)
+            setarrayitem_gc(p1, i2, p3, descr=cdescr)
             jump()
         """)
 
             setfield_gc(p1, 8111, descr=tiddescr)
             setfield_gc(p1, 5, descr=clendescr)
             label(p1, i2, p3)
-            cond_call_gc_wb_array(p1, i2, p3, descr=wbdescr)
-            setarrayitem_raw(p1, i2, p3, descr=cdescr)
+            cond_call_gc_wb_array(p1, i2, descr=wbdescr)
+            setarrayitem_gc(p1, i2, p3, descr=cdescr)
             jump()
         """)
 
             jump(p1, p2)
         """, """
             [p1, p2]
-            cond_call_gc_wb(p1, p2, descr=wbdescr)
-            setinteriorfield_raw(p1, 0, p2, descr=interiorzdescr)
+            cond_call_gc_wb(p1, descr=wbdescr)
+            setinteriorfield_gc(p1, 0, p2, descr=interiorzdescr)
             jump(p1, p2)
         """, interiorzdescr=interiorzdescr)
 
             p1 = call_malloc_nursery_varsize(1, 1, i0, \
                                 descr=strdescr)
             setfield_gc(p1, i0, descr=strlendescr)
-            cond_call_gc_wb(p0, p1, descr=wbdescr)
-            setfield_raw(p0, p1, descr=tzdescr)
+            cond_call_gc_wb(p0, descr=wbdescr)
+            setfield_gc(p0, p1, descr=tzdescr)
             jump()
         """)
 
             p0 = call_malloc_nursery(%(tdescr.size)d)
             setfield_gc(p0, 5678, descr=tiddescr)
             label(p0, p1)
-            cond_call_gc_wb(p0, p1, descr=wbdescr)
-            setfield_raw(p0, p1, descr=tzdescr)
+            cond_call_gc_wb(p0, descr=wbdescr)
+            setfield_gc(p0, p1, descr=tzdescr)
             jump()
         """)
 
+    def test_multiple_writes(self):
+        self.check_rewrite("""
+            [p0, p1, p2]
+            setfield_gc(p0, p1, descr=tzdescr)
+            setfield_gc(p0, p2, descr=tzdescr)
+            jump(p1, p2, p0)
+        """, """
+            [p0, p1, p2]
+            cond_call_gc_wb(p0, descr=wbdescr)
+            setfield_gc(p0, p1, descr=tzdescr)
+            setfield_gc(p0, p2, descr=tzdescr)
+            jump(p1, p2, p0)
+        """)
+
     def test_rewrite_call_assembler(self):
         self.check_rewrite("""
         [i0, f0]

File rpython/jit/backend/test/runner_test.py

             s = lltype.malloc(S)
             s.tid = value
             sgcref = lltype.cast_opaque_ptr(llmemory.GCREF, s)
-            t = lltype.malloc(S)
-            tgcref = lltype.cast_opaque_ptr(llmemory.GCREF, t)
             del record[:]
             self.execute_operation(rop.COND_CALL_GC_WB,
-                                   [BoxPtr(sgcref), ConstPtr(tgcref)],
+                                   [BoxPtr(sgcref)],
                                    'void', descr=WriteBarrierDescr())
             if cond:
                 assert record == [rffi.cast(lltype.Signed, sgcref)]
             sgcref = lltype.cast_opaque_ptr(llmemory.GCREF, s)
             del record[:]
             self.execute_operation(rop.COND_CALL_GC_WB_ARRAY,
-                       [BoxPtr(sgcref), ConstInt(123), BoxPtr(sgcref)],
+                       [BoxPtr(sgcref), ConstInt(123)],
                        'void', descr=WriteBarrierDescr())
             if cond:
                 assert record == [rffi.cast(lltype.Signed, sgcref)]
                 del record[:]
                 box_index = BoxIndexCls((9<<7) + 17)
                 self.execute_operation(rop.COND_CALL_GC_WB_ARRAY,
-                           [BoxPtr(sgcref), box_index, BoxPtr(sgcref)],
+                           [BoxPtr(sgcref), box_index],
                            'void', descr=WriteBarrierDescr())
                 if cond in [0, 1]:
                     assert record == [rffi.cast(lltype.Signed, s.data)]

File rpython/jit/backend/tool/viewcode.py

     raise ObjdumpNotFound('(g)objdump was not found in PATH')
 
 def machine_code_dump(data, originaddr, backend_name, label_list=None):
-    objdump_backend_option = {
+    objdump_machine_option = {
         'x86': 'i386',
         'x86-without-sse2': 'i386',
         'x86_32': 'i386',
-        'x86_64': 'x86-64',
-        'x86-64': 'x86-64',
+        'x86_64': 'i386:x86-64',
+        'x86-64': 'i386:x86-64',
         'i386': 'i386',
         'arm': 'arm',
         'arm_32': 'arm',
     }
     cmd = find_objdump()
-    objdump = ('%(command)s -M %(backend)s -b binary -m %(machine)s '
+    objdump = ('%(command)s -b binary -m %(machine)s '
                '--disassembler-options=intel-mnemonics '
                '--adjust-vma=%(origin)d -D %(file)s')
     #
         'command': cmd,
         'file': tmpfile,
         'origin': originaddr,
-        'backend': objdump_backend_option[backend_name],
-        'machine': 'i386' if not backend_name.startswith('arm') else 'arm',
+        'machine': objdump_machine_option[backend_name],
     }, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
     stdout, stderr = p.communicate()
     assert not p.returncode, ('Encountered an error running objdump: %s' %
         self.backend_name = None
         self.executable_name = None
 
-    def parse(self, f, textonly=True, truncate_addr=True):
+    def parse(self, f, textonly=True):
         for line in f:
             if line.startswith('BACKEND '):
                 self.backend_name = line.split(' ')[1].strip()
                 if len(pieces) == 3:
                     continue     # empty line
                 baseaddr = long(pieces[1][1:], 16)
-                if truncate_addr:
-                    baseaddr &= 0xFFFFFFFFL
-                elif baseaddr < 0:
+                if baseaddr < 0:
                     baseaddr += (2 * sys.maxint + 2)
                 offset = int(pieces[2][1:])
                 addr = baseaddr + offset
                 assert pieces[1].startswith('@')
                 assert pieces[2].startswith('+')
                 baseaddr = long(pieces[1][1:], 16)
-                if truncate_addr:
-                    baseaddr &= 0xFFFFFFFFL
-                elif baseaddr < 0:
+                if baseaddr < 0:
                     baseaddr += (2 * sys.maxint + 2)
                 offset = int(pieces[2][1:])
                 addr = baseaddr + offset

File rpython/jit/metainterp/resoperation.py

     'SETFIELD_RAW/2d',
     'STRSETITEM/3',
     'UNICODESETITEM/3',
-    'COND_CALL_GC_WB/2d', # [objptr, newvalue] (for the write barrier)
-    'COND_CALL_GC_WB_ARRAY/3d', # [objptr, arrayindex, newvalue] (write barr.)
+    'COND_CALL_GC_WB/1d',       # [objptr] (for the write barrier)
+    'COND_CALL_GC_WB_ARRAY/2d', # [objptr, arrayindex] (write barr. for array)
     'DEBUG_MERGE_POINT/*',      # debugging only
     'JIT_DEBUG/*',              # debugging only
     'VIRTUAL_REF_FINISH/2',   # removed before it's passed to the backend

File rpython/rtyper/module/ll_os.py

                                   _nowrapper = True)
 
         def fork_llimpl():
+            # NB. keep forkpty() up-to-date, too
             opaqueaddr = rthread.gc_thread_before_fork()
             childpid = rffi.cast(lltype.Signed, os_fork())
             rthread.gc_thread_after_fork(childpid, opaqueaddr)
 
     @registering_if(os, 'forkpty')
     def register_os_forkpty(self):
+        from rpython.rlib import rthread
         os_forkpty = self.llexternal(
             'forkpty',
             [rffi.INTP, rffi.VOIDP, rffi.VOIDP, rffi.VOIDP],
             compilation_info=ExternalCompilationInfo(libraries=['util']))
         def forkpty_llimpl():
             master_p = lltype.malloc(rffi.INTP.TO, 1, flavor='raw')
-            childpid = os_forkpty(master_p, None, None, None)
+            master_p[0] = rffi.cast(rffi.INT, -1)
+            opaqueaddr = rthread.gc_thread_before_fork()
+            childpid = rffi.cast(lltype.Signed,
+                                 os_forkpty(master_p, None, None, None))
+            rthread.gc_thread_after_fork(childpid, opaqueaddr)
             master_fd = master_p[0]
             lltype.free(master_p, flavor='raw')
             if childpid == -1: