[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