[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