[pypy-commit] pypy ppc-jit-backend: (bivab, arigo, hager): implemented COND_CALL_GC_WB

hager noreply at buildbot.pypy.org
Thu Dec 15 17:28:52 CET 2011


Author: hager <sven.hager at uni-duesseldorf.de>
Branch: ppc-jit-backend
Changeset: r50585:3167c1547eef
Date: 2011-12-15 17:28 +0100
http://bitbucket.org/pypy/pypy/changeset/3167c1547eef/

Log:	(bivab, arigo, hager): implemented COND_CALL_GC_WB

diff --git a/pypy/jit/backend/ppc/ppcgen/opassembler.py b/pypy/jit/backend/ppc/ppcgen/opassembler.py
--- a/pypy/jit/backend/ppc/ppcgen/opassembler.py
+++ b/pypy/jit/backend/ppc/ppcgen/opassembler.py
@@ -10,12 +10,13 @@
                                          INT)
 from pypy.rlib.objectmodel import we_are_translated
 from pypy.jit.backend.ppc.ppcgen.helper.assembler import (count_reg_args,
-                                                          saved_registers)
+                                                          Saved_Volatiles)
 from pypy.jit.backend.ppc.ppcgen.jump import remap_frame_layout
 from pypy.jit.backend.ppc.ppcgen.codebuilder import OverwritingBuilder
 from pypy.jit.backend.ppc.ppcgen.regalloc import TempPtr, TempInt
 from pypy.jit.backend.llsupport import symbolic
 from pypy.rpython.lltypesystem import rstr, rffi, lltype
+from pypy.jit.metainterp.resoperation import rop
 
 NO_FORCE_INDEX = -1
 
@@ -868,6 +869,78 @@
 
     emit_jit_debug = emit_debug_merge_point
 
+    def emit_cond_call_gc_wb(self, op, arglocs, regalloc):
+        # Write code equivalent to write_barrier() in the GC: it checks
+        # a flag in the object at arglocs[0], and if set, it calls the
+        # function remember_young_pointer() from the GC.  The two arguments
+        # to the call are in arglocs[:2].  The rest, arglocs[2:], contains
+        # registers that need to be saved and restored across the call.
+        descr = op.getdescr()
+        if we_are_translated():
+            cls = self.cpu.gc_ll_descr.has_write_barrier_class()
+            assert cls is not None and isinstance(descr, cls)
+
+        opnum = op.getopnum()
+        if opnum == rop.COND_CALL_GC_WB:
+            N = 2
+            addr = descr.get_write_barrier_fn(self.cpu)
+        elif opnum == rop.COND_CALL_GC_WB_ARRAY:
+            N = 3
+            addr = descr.get_write_barrier_from_array_fn(self.cpu)
+            assert addr != 0
+        else:
+            raise AssertionError(opnum)
+        loc_base = arglocs[0]
+
+        self.mc.alloc_scratch_reg()
+        if IS_PPC_32:
+            self.mc.lwz(r.SCRATCH.value, loc_base.value, 0)
+        else:
+            self.mc.ld(r.SCRATCH.value, loc_base.value, 0)
+
+        # offset to the byte we are interested in
+        byte_offset = descr.jit_wb_if_flag_byteofs
+        single_byte = descr.jit_wb_if_flag_singlebyte
+
+        # examine which bit in the byte is set
+        for i in range(8):
+            if 1 << i == single_byte:
+                n = i
+                break
+
+        if IS_PPC_32:
+            # compute the position of the bit we want to test
+            bitpos = (3 - byte_offset) * 8 + n
+            # put this bit to the rightmost bitposition of r0
+            self.mc.rlwinm(r.SCRATCH.value, r.SCRATCH.value, 32 - bitpos, 31, 31)
+            # test whether this bit is set
+            self.mc.cmpwi(0, r.SCRATCH.value, 1)
+        else:
+            assert 0, "not implemented yet"
+        self.mc.free_scratch_reg()
+
+        jz_location = self.mc.currpos()
+        self.mc.nop()
+
+        # the following is supposed to be the slow path, so whenever possible
+        # we choose the most compact encoding over the most efficient one.
+        with Saved_Volatiles(self.mc):
+            if N == 2:
+                callargs = [r.r3, r.r4]
+            else:
+                callargs = [r.r3, r.r4, r.r5]
+            remap_frame_layout(self, arglocs, callargs, r.SCRATCH)
+            func = rffi.cast(lltype.Signed, addr)
+            #
+            # misaligned stack in the call, but it's ok because the write barrier
+            # is not going to call anything more.  
+            self.mc.bl_abs(func)
+
+        # patch the JZ above
+        offset = self.mc.currpos() - jz_location
+        pmc = OverwritingBuilder(self.mc, jz_location, 1)
+        pmc.bc(4, 2, offset) # jump if the two values are equal
+        pmc.overwrite()
 
 class ForceOpAssembler(object):
 
diff --git a/pypy/jit/backend/ppc/ppcgen/regalloc.py b/pypy/jit/backend/ppc/ppcgen/regalloc.py
--- a/pypy/jit/backend/ppc/ppcgen/regalloc.py
+++ b/pypy/jit/backend/ppc/ppcgen/regalloc.py
@@ -755,6 +755,21 @@
     prepare_debug_merge_point = void
     prepare_jit_debug = void
 
+    def prepare_cond_call_gc_wb(self, op):
+        assert op.result is None
+        N = op.numargs()
+        # we force all arguments in a reg (unless they are Consts),
+        # because it will be needed anyway by the following setfield_gc
+        # or setarrayitem_gc. It avoids loading it twice from the memory.
+        arglocs = []
+        argboxes = []
+        for i in range(N):
+            loc, box = self._ensure_value_is_boxed(op.getarg(i), argboxes)
+            arglocs.append(loc)
+            argboxes.append(box)
+        self.rm.possibly_free_vars(argboxes)
+        return arglocs
+
     def prepare_force_token(self, op):
         res_loc = self.force_allocate_reg(op.result)
         self.possibly_free_var(op.result)


More information about the pypy-commit mailing list