Author: Maciej Fijalkowski <[email protected]>
Branch:
Changeset: r66189:b5fe11be23c0
Date: 2013-08-17 18:04 +0200
http://bitbucket.org/pypy/pypy/changeset/b5fe11be23c0/
Log: merge default
diff --git a/rpython/jit/backend/llsupport/rewrite.py
b/rpython/jit/backend/llsupport/rewrite.py
--- a/rpython/jit/backend/llsupport/rewrite.py
+++ b/rpython/jit/backend/llsupport/rewrite.py
@@ -26,10 +26,11 @@
- 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
@@ -42,7 +43,7 @@
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
@@ -221,18 +222,18 @@
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, ...).
@@ -315,7 +316,7 @@
[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):
@@ -327,7 +328,7 @@
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.
@@ -360,7 +361,7 @@
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):
@@ -382,45 +383,42 @@
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
@@ -430,13 +428,15 @@
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:
diff --git a/rpython/jit/backend/llsupport/test/test_gc.py
b/rpython/jit/backend/llsupport/test/test_gc.py
--- a/rpython/jit/backend/llsupport/test/test_gc.py
+++ b/rpython/jit/backend/llsupport/test/test_gc.py
@@ -202,13 +202,11 @@
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)
diff --git a/rpython/jit/backend/llsupport/test/test_rewrite.py
b/rpython/jit/backend/llsupport/test/test_rewrite.py
--- a/rpython/jit/backend/llsupport/test/test_rewrite.py
+++ b/rpython/jit/backend/llsupport/test/test_rewrite.py
@@ -561,8 +561,8 @@
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()
""")
@@ -575,8 +575,8 @@
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()
""")
@@ -595,8 +595,8 @@
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()
""")
@@ -616,8 +616,8 @@
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()
""")
@@ -628,8 +628,8 @@
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()
""")
@@ -647,8 +647,8 @@
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()
""")
@@ -666,8 +666,8 @@
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)
@@ -733,8 +733,8 @@
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()
""")
@@ -750,11 +750,25 @@
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]
diff --git a/rpython/jit/backend/test/runner_test.py
b/rpython/jit/backend/test/runner_test.py
--- a/rpython/jit/backend/test/runner_test.py
+++ b/rpython/jit/backend/test/runner_test.py
@@ -2140,11 +2140,9 @@
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)]
@@ -2179,7 +2177,7 @@
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)]
@@ -2244,7 +2242,7 @@
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)]
diff --git a/rpython/jit/metainterp/resoperation.py
b/rpython/jit/metainterp/resoperation.py
--- a/rpython/jit/metainterp/resoperation.py
+++ b/rpython/jit/metainterp/resoperation.py
@@ -502,8 +502,8 @@
'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
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit