[pypy-svn] r47666 - in pypy/dist/pypy/rpython/memory: . gc gctransform

arigo at codespeak.net arigo at codespeak.net
Sun Oct 21 11:17:58 CEST 2007


Author: arigo
Date: Sun Oct 21 11:17:56 2007
New Revision: 47666

Modified:
   pypy/dist/pypy/rpython/memory/gc/base.py
   pypy/dist/pypy/rpython/memory/gc/generation.py
   pypy/dist/pypy/rpython/memory/gctransform/framework.py
   pypy/dist/pypy/rpython/memory/gcwrapper.py
Log:
For now, reduce the write_barrier() interface.
I don't know if I'm making some GCs impossible to write, but at
least it fixes a problematic crash -- and I could kill a page
of obscure code, probably not too bad :-)

The issue is that if the write barrier has to write the new
field value itself via the address, we get strange C code
manipulating "void* + offset".  The C compiler's strict
aliasing rules don't realize that it's a write to a field
of a structure and may reorder a subsequent read before
the write...  see gcc option -fno-strict-aliasing.
With this change, the write barrier is no longer responsible
for actually writing the field - we still emit a bare_setfield
which the C compiler understands correctly.


Modified: pypy/dist/pypy/rpython/memory/gc/base.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gc/base.py	(original)
+++ pypy/dist/pypy/rpython/memory/gc/base.py	Sun Oct 21 11:17:56 2007
@@ -23,8 +23,8 @@
         self.varsize_offsets_to_gcpointers_in_var_part = varsize_offsets_to_gcpointers_in_var_part
         self.weakpointer_offset = weakpointer_offset
 
-    def write_barrier(self, addr, addr_to, addr_struct):
-        addr_to.address[0] = addr
+    def write_barrier(self, oldvalue, newvalue, addr_struct):
+        pass
 
     def setup(self):
         pass

Modified: pypy/dist/pypy/rpython/memory/gc/generation.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gc/generation.py	(original)
+++ pypy/dist/pypy/rpython/memory/gc/generation.py	Sun Oct 21 11:17:56 2007
@@ -252,10 +252,9 @@
                 else:
                     (obj + offset).address[0] = NULL
 
-    def write_barrier(self, addr, addr_to, addr_struct):
+    def write_barrier(self, oldvalue, newvalue, addr_struct):
         if self.header(addr_struct).tid & GCFLAG_NO_YOUNG_PTRS:
-            self.remember_young_pointer(addr_struct, addr)
-        addr_to.address[0] = addr
+            self.remember_young_pointer(addr_struct, newvalue)
 
     def remember_young_pointer(self, addr_struct, addr):
         debug_assert(not self.is_in_nursery(addr_struct),

Modified: pypy/dist/pypy/rpython/memory/gctransform/framework.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform/framework.py	(original)
+++ pypy/dist/pypy/rpython/memory/gctransform/framework.py	Sun Oct 21 11:17:56 2007
@@ -587,58 +587,32 @@
 
     def transform_generic_set(self, hop):
         from pypy.objspace.flow.model import Constant
+        opname = hop.spaceop.opname
         v_struct = hop.spaceop.args[0]
         v_newvalue = hop.spaceop.args[-1]
+        assert opname in ('setfield', 'setarrayitem', 'setinteriorfield')
+        assert isinstance(v_newvalue.concretetype, lltype.Ptr)
         # XXX for some GCs the skipping if the newvalue is a constant won't be
         # ok
-        if (self.write_barrier_ptr is None or isinstance(v_newvalue, Constant)
-            or v_struct.concretetype.TO._gckind != "gc"):
-            super(FrameworkGCTransformer, self).transform_generic_set(hop)
-        else:
+        if (self.write_barrier_ptr is not None
+            and not isinstance(v_newvalue, Constant)
+            and v_struct.concretetype.TO._gckind == "gc"):
             self.write_barrier_calls += 1
-            assert isinstance(v_newvalue.concretetype, lltype.Ptr)
-            opname = hop.spaceop.opname
-            assert opname in ('setfield', 'setarrayitem', 'setinteriorfield')
-            offsets = hop.spaceop.args[1:-1]
-            CURTYPE = v_struct.concretetype.TO
-            v_currentofs = None
-            for ofs in offsets:
-                if ofs.concretetype is lltype.Void:
-                    # a field in a structure
-                    fieldname = ofs.value
-                    fieldofs = llmemory.offsetof(CURTYPE, fieldname)
-                    v_offset = rmodel.inputconst(lltype.Signed, fieldofs)
-                    CURTYPE = getattr(CURTYPE, fieldname)
-                else:
-                    # an index in an array
-                    assert ofs.concretetype is lltype.Signed
-                    firstitem = llmemory.ArrayItemsOffset(CURTYPE)
-                    itemsize  = llmemory.sizeof(CURTYPE.OF)
-                    c_firstitem = rmodel.inputconst(lltype.Signed, firstitem)
-                    c_itemsize  = rmodel.inputconst(lltype.Signed, itemsize)
-                    v_index = hop.spaceop.args[1]
-                    v_offset = hop.genop("int_mul", [c_itemsize, v_index],
-                                         resulttype = lltype.Signed)
-                    v_offset = hop.genop("int_add", [c_firstitem, v_offset],
-                                         resulttype = lltype.Signed)
-                    CURTYPE = CURTYPE.OF
-                if v_currentofs is None:
-                    v_currentofs = v_offset
-                else:
-                    v_currentofs = hop.genop("int_add",
-                                             [v_currentofs, v_offset],
-                                             resulttype = lltype.Signed)
+            v_oldvalue = hop.genop('g' + opname[1:],
+                                   hop.inputargs()[:-1],
+                                   resulttype=v_newvalue.concretetype)
+            v_oldvalue = hop.genop("cast_ptr_to_adr", [v_oldvalue],
+                                   resulttype = llmemory.Address)
             v_newvalue = hop.genop("cast_ptr_to_adr", [v_newvalue],
                                    resulttype = llmemory.Address)
             v_structaddr = hop.genop("cast_ptr_to_adr", [v_struct],
                                      resulttype = llmemory.Address)
-            v_fieldaddr = hop.genop("adr_add", [v_structaddr, v_currentofs],
-                                    resulttype = llmemory.Address)
             hop.genop("direct_call", [self.write_barrier_ptr,
                                       self.c_const_gc,
+                                      v_oldvalue,
                                       v_newvalue,
-                                      v_fieldaddr,
                                       v_structaddr])
+        hop.rename('bare_' + opname)
 
     def var_needs_set_transform(self, var):
         return var_needsgc(var)

Modified: pypy/dist/pypy/rpython/memory/gcwrapper.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gcwrapper.py	(original)
+++ pypy/dist/pypy/rpython/memory/gcwrapper.py	Sun Oct 21 11:17:56 2007
@@ -74,12 +74,11 @@
     def setinterior(self, toplevelcontainer, inneraddr, INNERTYPE, newvalue):
         if (lltype.typeOf(toplevelcontainer).TO._gckind == 'gc' and
             isinstance(INNERTYPE, lltype.Ptr) and INNERTYPE.TO._gckind == 'gc'):
-            self.gc.write_barrier(llmemory.cast_ptr_to_adr(newvalue),
-                                  inneraddr,
+            oldvalue = inneraddr.address[0]
+            self.gc.write_barrier(oldvalue,
+                                  llmemory.cast_ptr_to_adr(newvalue),
                                   llmemory.cast_ptr_to_adr(toplevelcontainer))
-        else:
-            llheap.setinterior(toplevelcontainer, inneraddr,
-                               INNERTYPE, newvalue)
+        llheap.setinterior(toplevelcontainer, inneraddr, INNERTYPE, newvalue)
 
     def collect(self):
         self.gc.collect()



More information about the Pypy-commit mailing list