[pypy-commit] pypy gc_no_cleanup_nursery: Kill clear_array_contents and replace with NEW_ARRAY_CLEAR *should* work
fijal
noreply at buildbot.pypy.org
Thu Sep 25 11:39:11 CEST 2014
Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: gc_no_cleanup_nursery
Changeset: r73695:906a0b752d1f
Date: 2014-09-25 11:38 +0200
http://bitbucket.org/pypy/pypy/changeset/906a0b752d1f/
Log: Kill clear_array_contents and replace with NEW_ARRAY_CLEAR *should*
work equally well and it's a cleaner concept
diff --git a/rpython/jit/backend/llgraph/runner.py b/rpython/jit/backend/llgraph/runner.py
--- a/rpython/jit/backend/llgraph/runner.py
+++ b/rpython/jit/backend/llgraph/runner.py
@@ -643,20 +643,7 @@
def bh_new_array(self, length, arraydescr):
array = lltype.malloc(arraydescr.A, length, zero=True)
return lltype.cast_opaque_ptr(llmemory.GCREF, array)
-
- def bh_clear_array_contents(self, a, descr):
- a = support.cast_arg(lltype.Ptr(descr.A), a)
- ITEM = descr.A.OF
- array = a._obj
- if isinstance(ITEM, lltype.Struct):
- for i in xrange(array.getlength()):
- for name, FIELD in ITEM._flds.iteritems():
- null = FIELD._defl()
- setattr(array.getitem(i), name, null)
- else:
- null = ITEM._defl()
- for i in xrange(array.getlength()):
- array.setitem(i, null)
+ bh_new_array_clear = bh_new_array
def bh_classof(self, struct):
struct = lltype.cast_opaque_ptr(rclass.OBJECTPTR, struct)
diff --git a/rpython/jit/backend/llsupport/llmodel.py b/rpython/jit/backend/llsupport/llmodel.py
--- a/rpython/jit/backend/llsupport/llmodel.py
+++ b/rpython/jit/backend/llsupport/llmodel.py
@@ -592,14 +592,6 @@
def bh_new(self, sizedescr):
return self.gc_ll_descr.gc_malloc(sizedescr)
- def bh_clear_array_contents(self, ref, arraydescr):
- ofs, size, _ = self.unpack_arraydescr_size(arraydescr)
- arraysize = self.bh_arraylen_gc(ref, arraydescr)
- totalsize = size * arraysize
- adr = rffi.cast(lltype.Signed, ref) + ofs
- memset_fn(rffi.cast(llmemory.Address, adr), rffi.cast(rffi.INT, 0),
- rffi.cast(rffi.SIZE_T, totalsize))
-
def bh_new_with_vtable(self, vtable, sizedescr):
res = self.gc_ll_descr.gc_malloc(sizedescr)
if self.vtable_offset is not None:
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
@@ -66,9 +66,6 @@
continue
if op.is_guard():
self.emit_pending_zeros()
- elif op.getopnum() == rop.CLEAR_ARRAY_CONTENTS:
- self.handle_clear_array_contents(op.getdescr(), op.getarg(0))
- continue
elif op.can_malloc():
self.emitting_an_operation_that_can_collect()
elif op.getopnum() == rop.LABEL:
@@ -117,7 +114,7 @@
[op.result, ConstInt(classint)], None,
descr=self.gc_ll_descr.fielddescr_vtable)
self.newops.append(op)
- elif opnum == rop.NEW_ARRAY:
+ elif opnum == rop.NEW_ARRAY or opnum == rop.NEW_ARRAY_CLEAR:
descr = op.getdescr()
assert isinstance(descr, ArrayDescr)
self.handle_new_array(descr, op)
@@ -150,14 +147,11 @@
except KeyError:
pass
- def clear_varsize_gc_fields(self, kind, descr, result, v_length):
+ def clear_varsize_gc_fields(self, kind, descr, result, v_length, opnum):
if self.gc_ll_descr.malloc_zero_filled:
return
if kind == FLAG_ARRAY:
- if descr.is_array_of_structs() or descr.is_array_of_pointers():
- # for the case of array of structs, this is for correctness
- # only, since in practice all GC arrays of structs are
- # allocated with malloc(zero=True)
+ if opnum == rop.NEW_ARRAY_CLEAR:
self.handle_clear_array_contents(descr, result, v_length)
return
if kind == FLAG_STR:
@@ -200,7 +194,7 @@
# stuff that initializes GC header fields differently
self.gen_initialize_len(op.result, v_length, arraydescr.lendescr)
self.clear_varsize_gc_fields(kind, op.getdescr(), op.result,
- v_length)
+ v_length, op.getopnum())
return
if (total_size >= 0 and
self.gen_malloc_nursery(total_size, op.result)):
@@ -218,7 +212,8 @@
self.gen_malloc_unicode(v_length, op.result)
else:
raise NotImplementedError(op.getopname())
- self.clear_varsize_gc_fields(kind, op.getdescr(), op.result, v_length)
+ self.clear_varsize_gc_fields(kind, op.getdescr(), op.result, v_length,
+ op.getopnum())
def handle_clear_array_contents(self, arraydescr, v_arr, v_length=None):
# XXX more work here to reduce or remove the ZERO_ARRAY in some cases
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
@@ -2036,6 +2036,14 @@
'ref', descr=arraydescr)
assert r1.value != r2.value
a = lltype.cast_opaque_ptr(lltype.Ptr(A), r1.value)
+ assert len(a) == 342
+
+ def test_new_array_clear(self):
+ A = lltype.GcArray(lltype.Signed)
+ arraydescr = self.cpu.arraydescrof(A)
+ r1 = self.execute_operation(rop.NEW_ARRAY_CLEAR, [BoxInt(342)],
+ 'ref', descr=arraydescr)
+ a = lltype.cast_opaque_ptr(lltype.Ptr(A), r1.value)
assert a[0] == 0
assert len(a) == 342
@@ -4440,24 +4448,6 @@
[boxfloat(12.5)], 'int')
assert res.getint() == struct.unpack("I", struct.pack("f", 12.5))[0]
- def test_clear_array_contents(self):
- from rpython.jit.backend.llsupport.llmodel import AbstractLLCPU
- if not isinstance(self.cpu, AbstractLLCPU):
- py.test.skip("pointless test on non-asm")
- oldval = self.cpu.gc_ll_descr.malloc_zero_filled
- self.cpu.gc_ll_descr.malloc_zero_filled = False
- try:
- A = lltype.GcArray(lltype.Signed)
- a = lltype.malloc(A, 3)
- a[1] = 13
- descr = self.cpu.arraydescrof(A)
- ref = lltype.cast_opaque_ptr(llmemory.GCREF, a)
- self.execute_operation(rop.CLEAR_ARRAY_CONTENTS,
- [BoxPtr(ref)], 'void', descr=descr)
- 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)))
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
@@ -316,8 +316,7 @@
self.assembler.mc.mark_op(op)
self.rm.position = i
self.xrm.position = i
- if (op.has_no_side_effect() and op.result not in self.longevity
- and op.opnum != rop.CLEAR_ARRAY_CONTENTS):
+ if op.has_no_side_effect() and op.result not in self.longevit:
i += 1
self.possibly_free_vars_for_op(op)
continue
diff --git a/rpython/jit/metainterp/blackhole.py b/rpython/jit/metainterp/blackhole.py
--- a/rpython/jit/metainterp/blackhole.py
+++ b/rpython/jit/metainterp/blackhole.py
@@ -1346,10 +1346,6 @@
vtable = heaptracker.descr2vtable(cpu, descr)
return cpu.bh_new_with_vtable(vtable, descr)
- @arguments("cpu", "r", "d")
- def bhimpl_clear_array_contents(cpu, ref, descr):
- cpu.bh_clear_array_contents(ref, descr)
-
@arguments("cpu", "r", returns="i")
def bhimpl_guard_class(cpu, struct):
return cpu.bh_classof(struct)
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
@@ -337,7 +337,6 @@
rop.CALL_MALLOC_NURSERY,
rop.CALL_MALLOC_NURSERY_VARSIZE,
rop.CALL_MALLOC_NURSERY_VARSIZE_FRAME,
- rop.CLEAR_ARRAY_CONTENTS,
rop.LABEL,
): # list of opcodes never executed by pyjitpl
continue
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_multilabel.py b/rpython/jit/metainterp/optimizeopt/test/test_multilabel.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_multilabel.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_multilabel.py
@@ -150,10 +150,10 @@
def test_nonmatching_arraystruct_1(self):
ops = """
[p1, f0]
- p2 = new_array(3, descr=complexarraydescr)
+ p2 = new_array_clear(3, descr=complexarraydescr)
setinteriorfield_gc(p2, 2, f0, descr=complexrealdescr)
label(p2, f0)
- p4 = new_array(3, descr=complexarraydescr)
+ p4 = new_array_clear(3, descr=complexarraydescr)
setinteriorfield_gc(p4, 2, f0, descr=compleximagdescr)
jump(p4, f0)
"""
@@ -163,10 +163,10 @@
def test_nonmatching_arraystruct_2(self):
ops = """
[p1, f0]
- p2 = new_array(3, descr=complexarraydescr)
+ p2 = new_array_clear(3, descr=complexarraydescr)
setinteriorfield_gc(p2, 2, f0, descr=complexrealdescr)
label(p2, f0)
- p4 = new_array(2, descr=complexarraydescr)
+ p4 = new_array_clear(2, descr=complexarraydescr)
setinteriorfield_gc(p4, 0, f0, descr=complexrealdescr)
jump(p4, f0)
"""
@@ -198,7 +198,7 @@
def test_not_virtual_arraystruct(self):
ops = """
[p1]
- p3 = new_array(3, descr=complexarraydescr)
+ p3 = new_array_clear(3, descr=complexarraydescr)
label(p3)
p4 = escape()
jump(p4)
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py
@@ -940,7 +940,7 @@
def test_virtual_array_of_struct(self):
ops = """
[f0, f1, f2, f3]
- p0 = new_array(2, descr=complexarraydescr)
+ p0 = new_array_clear(2, descr=complexarraydescr)
setinteriorfield_gc(p0, 0, f1, descr=compleximagdescr)
setinteriorfield_gc(p0, 0, f0, descr=complexrealdescr)
setinteriorfield_gc(p0, 1, f3, descr=compleximagdescr)
@@ -966,7 +966,7 @@
def test_virtual_array_of_struct_forced(self):
ops = """
[f0, f1]
- p0 = new_array(1, descr=complexarraydescr)
+ p0 = new_array_clear(1, descr=complexarraydescr)
setinteriorfield_gc(p0, 0, f0, descr=complexrealdescr)
setinteriorfield_gc(p0, 0, f1, descr=compleximagdescr)
f2 = getinteriorfield_gc(p0, 0, descr=complexrealdescr)
@@ -978,7 +978,7 @@
expected = """
[f0, f1]
f2 = float_mul(f0, f1)
- p0 = new_array(1, descr=complexarraydescr)
+ p0 = new_array_clear(1, descr=complexarraydescr)
setinteriorfield_gc(p0, 0, f1, descr=compleximagdescr)
setinteriorfield_gc(p0, 0, f0, descr=complexrealdescr)
i0 = escape(f2, p0)
@@ -989,7 +989,7 @@
def test_virtual_array_of_struct_len(self):
ops = """
[]
- p0 = new_array(2, descr=complexarraydescr)
+ p0 = new_array_clear(2, descr=complexarraydescr)
i0 = arraylen_gc(p0)
finish(i0)
"""
@@ -5466,33 +5466,6 @@
"""
self.optimize_loop(ops, expected)
- def test_virtual_clear_array_contents(self):
- ops = """
- []
- p0 = new_array(2, descr=arraydescr)
- clear_array_contents(p0, descr=arraydescr)
- """
- expected = """
- []
- """
- self.optimize_loop(ops, expected)
-
- def test_virtual_clear_array_contents_escape(self):
- ops = """
- []
- p0 = new_array(2, descr=arraydescr)
- clear_array_contents(p0, descr=arraydescr)
- escape(p0)
- """
- expected = """
- []
- p0 = new_array(2, descr=arraydescr)
- setarrayitem_gc(p0, 0, 0, descr=arraydescr)
- setarrayitem_gc(p0, 1, 0, descr=arraydescr)
- escape(p0)
- """
- self.optimize_loop(ops, expected)
-
class TestLLtype(BaseTestOptimizeBasic, LLtypeMixin):
pass
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
@@ -4023,8 +4023,7 @@
def test_arraycopy_dest_not_virtual(self):
ops = '''
[]
- p1 = new_array(3, descr=arraydescr)
- clear_array_contents(p1, descr=arraydescr)
+ p1 = new_array_clear(3, descr=arraydescr)
p2 = new_array(3, descr=arraydescr)
setarrayitem_gc(p1, 2, 10, descr=arraydescr)
setarrayitem_gc(p2, 2, 13, descr=arraydescr)
diff --git a/rpython/jit/metainterp/optimizeopt/virtualize.py b/rpython/jit/metainterp/optimizeopt/virtualize.py
--- a/rpython/jit/metainterp/optimizeopt/virtualize.py
+++ b/rpython/jit/metainterp/optimizeopt/virtualize.py
@@ -264,11 +264,16 @@
class VArrayValue(AbstractVArrayValue):
- def __init__(self, arraydescr, constvalue, size, keybox, source_op=None):
+ def __init__(self, arraydescr, constvalue, size, keybox, source_op=None,
+ clear=False):
AbstractVirtualValue.__init__(self, keybox, source_op)
self.arraydescr = arraydescr
self.constvalue = constvalue
- self._items = [None] * size
+ if clear:
+ self._items = [constvalue] * size
+ else:
+ self._items = [None] * size
+ self.clear = clear
def getlength(self):
return len(self._items)
@@ -279,10 +284,6 @@
def set_item_value(self, i, newval):
self._items[i] = newval
- def initialize_with_zeros(self, optimizer):
- for i in range(len(self._items)):
- self._items[i] = optimizer.new_const_item(self.arraydescr)
-
def getitem(self, index):
res = self._items[index]
return res
@@ -316,7 +317,11 @@
self.box = box = self.source_op.result
for index in range(len(self._items)):
subvalue = self._items[index]
- if subvalue is not None:
+ if subvalue is None:
+ continue
+ if subvalue is self.constvalue and self.clear:
+ continue
+ else:
subbox = subvalue.force_box(optforce)
op = ResOperation(rop.SETARRAYITEM_GC,
[box, ConstInt(index), subbox], None,
@@ -344,9 +349,6 @@
assert isinstance(itemvalue, optimizer.OptValue)
self._items[index][ofs] = itemvalue
- def initialize_with_zeros(self, optimizer):
- assert False, "should never happen"
-
def _really_force(self, optforce):
assert self.source_op is not None
if not we_are_translated():
@@ -497,12 +499,15 @@
self.make_equal_to(box, vvalue)
return vvalue
- def make_varray(self, arraydescr, size, box, source_op=None):
+ def make_varray(self, arraydescr, size, box, source_op=None,
+ clear=False):
if arraydescr.is_array_of_structs():
+ assert clear
vvalue = VArrayStructValue(arraydescr, size, box, source_op)
else:
constvalue = self.new_const_item(arraydescr)
- vvalue = VArrayValue(arraydescr, constvalue, size, box, source_op)
+ vvalue = VArrayValue(arraydescr, constvalue, size, box, source_op,
+ clear=clear)
self.make_equal_to(box, vvalue)
return vvalue
@@ -674,13 +679,13 @@
else:
self.emit_operation(op)
- def optimize_CLEAR_ARRAY_CONTENTS(self, op):
- v = self.getvalue(op.getarg(0))
- if v.is_virtual():
- # initialize the items, since we need to store zeros
- v.initialize_with_zeros(self.optimizer)
- return
- self.emit_operation(op)
+ def optimize_NEW_ARRAY_CLEAR(self, op):
+ sizebox = self.get_constant_box(op.getarg(0))
+ if sizebox is not None:
+ self.make_varray(op.getdescr(), sizebox.getint(), op.result, op,
+ clear=True)
+ else:
+ self.emit_operation(op)
def optimize_CALL(self, op):
effectinfo = op.getdescr().get_extra_info()
diff --git a/rpython/jit/metainterp/pyjitpl.py b/rpython/jit/metainterp/pyjitpl.py
--- a/rpython/jit/metainterp/pyjitpl.py
+++ b/rpython/jit/metainterp/pyjitpl.py
@@ -396,10 +396,6 @@
def opimpl_new(self, sizedescr):
return self.metainterp.execute_new(sizedescr)
- @arguments("box", "descr")
- def opimpl_clear_array_contents(self, box, descr):
- self.metainterp.execute_and_record(rop.CLEAR_ARRAY_CONTENTS, descr, box)
-
@arguments("descr")
def opimpl_new_with_vtable(self, sizedescr):
cpu = self.metainterp.cpu
@@ -410,6 +406,10 @@
def opimpl_new_array(self, lengthbox, itemsizedescr):
return self.metainterp.execute_new_array(itemsizedescr, lengthbox)
+ @arguments("box", "descr")
+ def opimpl_new_array_clear(self, lengthbox, itemsizedescr):
+ return self.metainterp.execute_new_array_clear(itemsizedescr, lengthbox)
+
@specialize.arg(1)
def _do_getarrayitem_gc_any(self, op, arraybox, indexbox, arraydescr):
tobox = self.metainterp.heapcache.getarrayitem(
@@ -1917,6 +1917,12 @@
self.heapcache.new_array(resbox, lengthbox)
return resbox
+ def execute_new_array_clear(self, itemsizedescr, lengthbox):
+ resbox = self.execute_and_record(rop.NEW_ARRAY_CLEAR, itemsizedescr,
+ lengthbox)
+ self.heapcache.new_array(resbox, lengthbox)
+ return resbox
+
def execute_setfield_gc(self, fielddescr, box, valuebox):
self.execute_and_record(rop.SETFIELD_GC, fielddescr, box, valuebox)
self.heapcache.setfield(box, valuebox, fielddescr)
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
@@ -493,9 +493,6 @@
'MARK_OPAQUE_PTR/1b',
# this one has no *visible* side effect, since the virtualizable
# must be forced, however we need to execute it anyway
- 'CLEAR_ARRAY_CONTENTS/1d',
- # this one does not *really* have a side effect since it's equivalent
- # to array just coming zeroed
'_NOSIDEEFFECT_LAST', # ----- end of no_side_effect operations -----
'INCREMENT_DEBUG_COUNTER/1',
diff --git a/rpython/jit/metainterp/resume.py b/rpython/jit/metainterp/resume.py
--- a/rpython/jit/metainterp/resume.py
+++ b/rpython/jit/metainterp/resume.py
@@ -981,7 +981,11 @@
def allocate_array(self, length, arraydescr):
lengthbox = ConstInt(length)
- return self.metainterp.execute_new_array(arraydescr, lengthbox)
+ if (arraydescr.is_array_of_structs() or
+ arraydescr.is_array_of_pointers()):
+ return self.metainterp.execute_new_array_clear(arraydescr,
+ lengthbox)
+ return self.metainterp.execute_new_array(arraydescr, lengthbox)
def allocate_raw_buffer(self, size):
cic = self.metainterp.staticdata.callinfocollection
More information about the pypy-commit
mailing list