[pypy-commit] pypy gc_no_cleanup_nursery: implement zero_ptr_field and eager clearing of fields
fijal
noreply at buildbot.pypy.org
Mon Sep 15 02:05:18 CEST 2014
Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: gc_no_cleanup_nursery
Changeset: r73539:b1948ec73a81
Date: 2014-09-14 18:03 -0600
http://bitbucket.org/pypy/pypy/changeset/b1948ec73a81/
Log: implement zero_ptr_field and eager clearing of fields
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
@@ -61,7 +61,8 @@
continue
elif op.getopnum() == rop.CLEAR_ARRAY_CONTENTS:
if not self.gc_ll_descr.malloc_zero_filled:
- self.handle_clear_array_contents(op)
+ self.handle_clear_array_contents(op.getdescr(),
+ op.getarg(0))
continue
elif op.can_malloc():
self.emitting_an_operation_that_can_collect()
@@ -115,6 +116,18 @@
else:
raise NotImplementedError(op.getopname())
+ def clear_gc_fields(self, descr, result):
+ if self.gc_ll_descr.malloc_zero_filled:
+ return
+ for ofs in descr.offsets_of_gcfields:
+ o = ResOperation(rop.ZERO_PTR_FIELD, [result, ConstInt(ofs)], None)
+ self.newops.append(o)
+
+ def clear_varsize_gc_fields(self, descr, result, v_length=None):
+ if self.gc_ll_descr.malloc_zero_filled:
+ return
+ self.handle_clear_array_contents(descr, result, v_length)
+
def handle_new_fixedsize(self, descr, op):
assert isinstance(descr, SizeDescr)
size = descr.size
@@ -122,6 +135,7 @@
self.gen_initialize_tid(op.result, descr.tid)
else:
self.gen_malloc_fixedsize(size, descr.tid, op.result)
+ self.clear_gc_fields(descr, op.result)
def handle_new_array(self, arraydescr, op, kind=FLAG_ARRAY):
v_length = op.getarg(0)
@@ -143,6 +157,7 @@
# might end up being allocated by malloc_external or some
# stuff that initializes GC header fields differently
self.gen_initialize_len(op.result, v_length, arraydescr.lendescr)
+ self.clear_varsize_gc_fields(op.getdescr(), op.result, v_length)
return
if (total_size >= 0 and
self.gen_malloc_nursery(total_size, op.result)):
@@ -160,19 +175,24 @@
self.gen_malloc_unicode(v_length, op.result)
else:
raise NotImplementedError(op.getopname())
+ self.clear_varsize_gc_fields(op.getdescr(), op.result, v_length)
- def handle_clear_array_contents(self, op):
+ def handle_clear_array_contents(self, arraydescr, v_arr, v_arrsize=None):
# XXX this maybe should go to optimizer, so we can remove extra ops?
- arraydescr = op.getdescr()
ofs, size, _ = self.cpu.unpack_arraydescr_size(arraydescr)
- v_arr = op.getarg(0)
v_arr_plus_ofs = BoxInt()
v_arrsize = BoxInt()
v_totalsize = BoxInt()
gcdescr = self.gc_ll_descr
ops = [
ResOperation(rop.INT_ADD, [v_arr, ConstInt(size)], v_arr_plus_ofs),
- ResOperation(rop.ARRAYLEN_GC, [v_arr], v_arrsize, descr=arraydescr),
+ ]
+
+ if v_arrsize is None:
+ o = ResOperation(rop.ARRAYLEN_GC, [v_arr], v_arrsize,
+ descr=arraydescr)
+ ops.append(o)
+ ops += [
ResOperation(rop.INT_MUL, [v_arrsize, ConstInt(size)], v_totalsize),
ResOperation(rop.CALL, [ConstInt(gcdescr.memset_ptr_as_int),
v_arr_plus_ofs,
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
@@ -144,7 +144,7 @@
def setup_method(self, meth):
class FakeCPU(BaseFakeCPU):
def sizeof(self, STRUCT):
- return SizeDescrWithVTable(102)
+ return SizeDescrWithVTable(102, offsets_of_gcfields=[])
self.cpu = FakeCPU()
self.gc_ll_descr = GcLLDescr_boehm(None, None, None)
@@ -277,10 +277,11 @@
really_not_translated=True)
self.gc_ll_descr.write_barrier_descr.has_write_barrier_from_array = (
lambda cpu: True)
+ self.gc_ll_descr.malloc_zero_filled = False
#
class FakeCPU(BaseFakeCPU):
def sizeof(self, STRUCT):
- descr = SizeDescrWithVTable(104)
+ descr = SizeDescrWithVTable(104, offsets_of_gcfields=[])
descr.tid = 9315
return descr
self.cpu = FakeCPU()
@@ -311,6 +312,7 @@
setfield_gc(p0, 1234, descr=tiddescr)
p1 = int_add(p0, %(sdescr.size)d)
setfield_gc(p1, 5678, descr=tiddescr)
+ zero_ptr_field(p1, %(tdescr.offsets_of_gcfields[0])s)
p2 = int_add(p1, %(tdescr.size)d)
setfield_gc(p2, 1234, descr=tiddescr)
jump()
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
@@ -4457,3 +4457,24 @@
assert a[1] == 0
finally:
self.cpu.gc_ll_descr.malloc_zero_filled = oldval
+
+ def test_zero_ptr_field(self):
+ T = lltype.GcStruct('T')
+ S = lltype.GcStruct('S', ('x', lltype.Ptr(T)))
+ tdescr = self.cpu.sizeof(T)
+ sdescr = self.cpu.sizeof(S)
+ fielddescr = self.cpu.fielddescrof(S, 'x')
+ loop = parse("""
+ []
+ p0 = new(descr=tdescr)
+ p1 = new(descr=sdescr)
+ setfield_gc(p1, p0, descr=fielddescr)
+ zero_ptr_field(p1, %d)
+ finish(p1)
+ """ % fielddescr.offset, namespace=locals())
+ looptoken = JitCellToken()
+ self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken)
+ deadframe = self.cpu.execute_token(looptoken)
+ ref = self.cpu.get_ref_value(deadframe, 0)
+ s = lltype.cast_opaque_ptr(lltype.Ptr(S), ref)
+ assert not s.x
diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py
--- a/rpython/jit/backend/x86/assembler.py
+++ b/rpython/jit/backend/x86/assembler.py
@@ -1486,6 +1486,8 @@
dest_addr = AddressLoc(base_loc, ofs_loc)
self.save_into_mem(dest_addr, value_loc, size_loc)
+ genop_discard_zero_ptr_field = genop_discard_setfield_gc
+
def genop_discard_setinteriorfield_gc(self, op, arglocs):
(base_loc, ofs_loc, itemsize_loc, fieldsize_loc,
index_loc, temp_loc, value_loc) = arglocs
diff --git a/rpython/jit/backend/x86/regalloc.py b/rpython/jit/backend/x86/regalloc.py
--- a/rpython/jit/backend/x86/regalloc.py
+++ b/rpython/jit/backend/x86/regalloc.py
@@ -959,6 +959,13 @@
need_lower_byte=need_lower_byte)
self.perform_discard(op, [base_loc, ofs_loc, size_loc, value_loc])
+ def consider_zero_ptr_field(self, op):
+ ofs_loc = imm(op.getarg(1).getint())
+ size_loc = imm(WORD)
+ base_loc = self.rm.make_sure_var_in_reg(op.getarg(0), [])
+ value_loc = imm(0)
+ self.perform_discard(op, [base_loc, ofs_loc, size_loc, value_loc])
+
consider_setfield_raw = consider_setfield_gc
def consider_setinteriorfield_gc(self, op):
diff --git a/rpython/jit/codewriter/heaptracker.py b/rpython/jit/codewriter/heaptracker.py
--- a/rpython/jit/codewriter/heaptracker.py
+++ b/rpython/jit/codewriter/heaptracker.py
@@ -139,6 +139,6 @@
res.append(offset)
elif isinstance(FIELD, lltype.Struct):
offsets_of_gcfields(gccache, FIELD, res)
- if not we_are_translated():
+ if not gccache.translate_support_code:
res.sort()
return res
diff --git a/rpython/jit/metainterp/executor.py b/rpython/jit/metainterp/executor.py
--- a/rpython/jit/metainterp/executor.py
+++ b/rpython/jit/metainterp/executor.py
@@ -325,6 +325,7 @@
rop.INCREMENT_DEBUG_COUNTER,
rop.COND_CALL_GC_WB,
rop.COND_CALL_GC_WB_ARRAY,
+ rop.ZERO_PTR_FIELD,
rop.DEBUG_MERGE_POINT,
rop.JIT_DEBUG,
rop.SETARRAYITEM_RAW,
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
@@ -504,6 +504,8 @@
'SETINTERIORFIELD_RAW/3d', # right now, only used by tests
'RAW_STORE/3d',
'SETFIELD_GC/2d',
+ 'ZERO_PTR_FIELD/2', # only emitted by the rewrite, sets a pointer field
+ # at a given offset, no descr
'SETFIELD_RAW/2d',
'STRSETITEM/3',
'UNICODESETITEM/3',
More information about the pypy-commit
mailing list