[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