[pypy-commit] pypy s390x-backend: added save/restore exception impl

plan_rich pypy.commits at gmail.com
Tue Dec 29 10:37:04 EST 2015


Author: Richard Plangger <planrichi at gmail.com>
Branch: s390x-backend
Changeset: r81492:4fbd38846596
Date: 2015-12-29 16:36 +0100
http://bitbucket.org/pypy/pypy/changeset/4fbd38846596/

Log:	added save/restore exception impl

diff --git a/rpython/jit/backend/zarch/assembler.py b/rpython/jit/backend/zarch/assembler.py
--- a/rpython/jit/backend/zarch/assembler.py
+++ b/rpython/jit/backend/zarch/assembler.py
@@ -423,7 +423,42 @@
         return mc.materialize(self.cpu, [])
 
     def _build_stack_check_slowpath(self):
-        pass # TODO
+        _, _, slowpathaddr = self.cpu.insert_stack_check()
+        if slowpathaddr == 0 or not self.cpu.propagate_exception_descr:
+            return      # no stack check (for tests, or non-translated)
+        #
+        # make a regular function that is called from a point near the start
+        # of an assembler function (after it adjusts the stack and saves
+        # registers).
+        mc = InstrBuilder()
+        #
+        mc.STG(r.r14, l.addr(14*WORD, r.SP))
+        # Do the call
+        # use SP as single parameter for the call
+        mc.STG(r.SP, l.addr(0, r.SP)) # store the backchain
+        mc.AGHI(r.SP, l.imm(-STD_FRAME_SIZE_IN_BYTES))
+        mc.LGR(r.r2, r.SP)
+        mc.load_imm(mc.RAW_CALL_REG, slowpathaddr)
+        mc.raw_call()
+        mc.AGHI(r.SP, l.imm(STD_FRAME_SIZE_IN_BYTES))
+        #
+        # Check if it raised StackOverflow
+        mc.load_imm(r.SCRATCH, self.cpu.pos_exception())
+        mc.LG(r.SCRATCH, l.addr(0, r.SCRATCH))
+        # if this comparison is true, then everything is ok,
+        # else we have an exception
+        mc.cmp_op(r.SCRATCH, 0, imm=True)
+        #
+        # So we return to our caller, conditionally if "EQ"
+        mc.LG(r.r14, l.addr(14*WORD, r.SP))
+        mc.BCR(c.EQ, r.r14)
+        #
+        # Else, jump to propagate_exception_path
+        assert self.propagate_exception_path
+        mc.b_abs(self.propagate_exception_path)
+        #
+        rawstart = mc.materialize(self.cpu, [])
+        self.stack_check_slowpath = rawstart
 
     def new_stack_loc(self, i, tp):
         base_ofs = self.cpu.get_baseofs_of_frame_field()
@@ -573,7 +608,7 @@
         self.write_pending_failure_recoveries()
         fullsize = self.mc.get_relative_pos()
         #
-        # TODO self.patch_stack_checks(frame_depth_no_fixed_size + JITFRAME_FIXED_SIZE)
+        self.patch_stack_checks(frame_depth_no_fixed_size + JITFRAME_FIXED_SIZE)
         rawstart = self.materialize_loop(original_loop_token)
         debug_bridge(descr_number, rawstart, codeendpos)
         self.patch_pending_failure_recoveries(rawstart)
@@ -628,7 +663,7 @@
     def propagate_memoryerror_if_r2_is_null(self):
         # if self.propagate_exception_path == 0 (tests), this may jump to 0
         # and segfaults.  too bad.  the alternative is to continue anyway
-        # with r3==0, but that will segfault too.
+        # with r2==0, but that will segfault too.
         self.mc.cmp_op(r.r2, l.imm(0), imm=True)
         self.mc.load_imm(r.RETURN, self.propagate_exception_path)
         self.mc.BCR(c.EQ, r.RETURN)
@@ -1048,6 +1083,29 @@
         # exit function
         self._call_footer()
 
+    def _store_and_reset_exception(self, mc, excvalloc, exctploc=None):
+        """Reset the exception, after fetching it inside the two regs.
+        """
+        mc.load_imm(r.r2, self.cpu.pos_exc_value())
+        diff = self.cpu.pos_exception() - self.cpu.pos_exc_value()
+        assert check_imm_value(diff)
+        # Load the exception fields into the two registers
+        mc.load(excvalloc, r.r2, 0)
+        if exctploc is not None:
+            mc.load(exctploc, r.r2, diff)
+        # Zero out the exception fields
+        mc.LGHI(r.r0, l.imm(0))
+        mc.STG(r.r0, l.addr(0, r.r2))
+        mc.STG(r.r0, l.addr(diff, r.r2))
+
+    def _restore_exception(self, mc, excvalloc, exctploc):
+        mc.load_imm(r.r2, self.cpu.pos_exc_value())
+        diff = self.cpu.pos_exception() - self.cpu.pos_exc_value()
+        assert check_imm_value(diff)
+        # Store the exception fields from the two registers
+        mc.STG(excvalloc, l.addr(0, r.r2))
+        mc.STG(exctploc, l.addr(diff, r.r2))
+
     def load_gcmap(self, mc, reg, gcmap):
         # load the current gcmap into register 'reg'
         ptr = rffi.cast(lltype.Signed, gcmap)
diff --git a/rpython/jit/backend/zarch/callbuilder.py b/rpython/jit/backend/zarch/callbuilder.py
--- a/rpython/jit/backend/zarch/callbuilder.py
+++ b/rpython/jit/backend/zarch/callbuilder.py
@@ -126,6 +126,7 @@
             if gcrootmap.is_shadow_stack and self.is_call_release_gil:
                 # in this mode, RSHADOWOLD happens to contain the shadowstack
                 # top at this point, so reuse it instead of loading it again
+                xxx
                 ssreg = self.RSHADOWOLD
         self.asm._reload_frame_if_necessary(self.mc, shadowstack_reg=ssreg)
 
diff --git a/rpython/jit/backend/zarch/codebuilder.py b/rpython/jit/backend/zarch/codebuilder.py
--- a/rpython/jit/backend/zarch/codebuilder.py
+++ b/rpython/jit/backend/zarch/codebuilder.py
@@ -175,6 +175,16 @@
             self.LGFI(dest_reg, l.imm(word & 0xFFFFffff))
             self.IIHF(dest_reg, l.imm((word >> 32) & 0xFFFFffff))
 
+    def load_imm_plus(self, dest_reg, word):
+        """Like load_imm(), but with one instruction less, and
+        leaves the loaded value off by some signed 16-bit difference.
+        Returns that difference."""
+        diff = rffi.cast(lltype.Signed, rffi.cast(rffi.SHORT, word))
+        word -= diff
+        assert word & 0xFFFF == 0
+        self.load_imm(dest_reg, word)
+        return diff
+
     def sync(self):
         # see sync. section of the zarch manual!
         self.BCR_rr(0xf,0)
diff --git a/rpython/jit/backend/zarch/opassembler.py b/rpython/jit/backend/zarch/opassembler.py
--- a/rpython/jit/backend/zarch/opassembler.py
+++ b/rpython/jit/backend/zarch/opassembler.py
@@ -739,10 +739,7 @@
         assert check_imm_value(diff)
 
         mc.LG(r.SCRATCH2, l.addr(diff, r.SCRATCH))
-        if not loc.is_in_pool() and loc.is_imm():
-            mc.cmp_op(r.SCRATCH2, loc, imm=True)
-        else:
-            mc.cmp_op(r.SCRATCH2, loc, pool=loc.is_in_pool())
+        mc.cmp_op(r.SCRATCH2, loc)
         self.guard_success_cc = c.EQ
         self._emit_guard(op, failargs)
 
@@ -752,6 +749,17 @@
         mc.SG(r.SCRATCH2, l.addr(0, r.SCRATCH))
         mc.SG(r.SCRATCH2, l.addr(diff, r.SCRATCH))
 
+    def emit_save_exc_class(self, op, arglocs, regalloc):
+        [resloc] = arglocs
+        diff = self.mc.load_imm_plus(r.r2, self.cpu.pos_exception())
+        self.mc.load(resloc, r.r2, diff)
+
+    def emit_save_exception(self, op, arglocs, regalloc):
+        [resloc] = arglocs
+        self._store_and_reset_exception(self.mc, resloc)
+
+    def emit_restore_exception(self, op, arglocs, regalloc):
+        self._restore_exception(self.mc, arglocs[1], arglocs[0])
 
 class MemoryOpAssembler(object):
     _mixin_ = True
diff --git a/rpython/jit/backend/zarch/regalloc.py b/rpython/jit/backend/zarch/regalloc.py
--- a/rpython/jit/backend/zarch/regalloc.py
+++ b/rpython/jit/backend/zarch/regalloc.py
@@ -1032,7 +1032,7 @@
         return locs
 
     def prepare_guard_exception(self, op):
-        loc = self.ensure_reg(op.getarg(0))
+        loc = self.ensure_reg(op.getarg(0), force_in_reg=True)
         if op in self.longevity:
             resloc = self.force_allocate_reg(op)
         else:
@@ -1040,6 +1040,16 @@
         arglocs = self._prepare_guard(op, [loc, resloc])
         return arglocs
 
+    def prepare_save_exception(self, op):
+        res = self.rm.force_allocate_reg(op)
+        return [res]
+    prepare_save_exc_class = prepare_save_exception
+
+    def prepare_restore_exception(self, op):
+        loc0 = self.ensure_reg(op.getarg(0), force_in_reg=True)
+        loc1 = self.ensure_reg(op.getarg(1), force_in_reg=True)
+        return [loc0, loc1]
+
     def prepare_copystrcontent(self, op):
         src_ptr_loc = self.ensure_reg(op.getarg(0), force_in_reg=True)
         dst_ptr_loc = self.ensure_reg(op.getarg(1), force_in_reg=True)


More information about the pypy-commit mailing list