Author: Richard Plangger <[email protected]>
Branch: s390x-backend
Changeset: r81347:a0e464a31d7f
Date: 2015-12-16 15:48 +0100
http://bitbucket.org/pypy/pypy/changeset/a0e464a31d7f/
Log: copied stubs to assemble write barrier and exception path, pushed
forward the assembly of cond_call_gc_wb (+array)
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
@@ -142,7 +142,129 @@
return startpos
def _build_wb_slowpath(self, withcards, withfloats=False, for_frame=False):
- pass # TODO
+ descr = self.cpu.gc_ll_descr.write_barrier_descr
+ if descr is None:
+ return
+ if not withcards:
+ func = descr.get_write_barrier_fn(self.cpu)
+ else:
+ if descr.jit_wb_cards_set == 0:
+ return
+ func = descr.get_write_barrier_from_array_fn(self.cpu)
+ if func == 0:
+ return
+ #
+ # This builds a helper function called from the slow path of
+ # write barriers. It must save all registers, and optionally
+ # all fp registers. It takes its single argument in r0
+ # (or in SPP if 'for_frame').
+ if for_frame:
+ argument_loc = r.SPP
+ else:
+ argument_loc = r.r0
+
+ mc = PPCBuilder()
+ old_mc = self.mc
+ self.mc = mc
+
+ extra_stack_size = LOCAL_VARS_OFFSET + 4 * WORD + 8
+ extra_stack_size = (extra_stack_size + 15) & ~15
+ if for_frame:
+ # NOTE: don't save registers on the jitframe here! It might
+ # override already-saved values that will be restored
+ # later...
+ #
+ # This 'for_frame' version is called after a CALL. It does not
+ # need to save many registers: the registers that are anyway
+ # destroyed by the call can be ignored (VOLATILES), and the
+ # non-volatile registers won't be changed here. It only needs
+ # to save r.RCS1 (used below), r3 and f1 (possible results of
+ # the call), and two more non-volatile registers (used to store
+ # the RPython exception that occurred in the CALL, if any).
+ #
+ # We need to increase our stack frame size a bit to store them.
+ #
+ self.mc.load(r.SCRATCH.value, r.SP.value, 0) # SP back chain
+ self.mc.store_update(r.SCRATCH.value, r.SP.value,
-extra_stack_size)
+ self.mc.std(r.RCS1.value, r.SP.value, LOCAL_VARS_OFFSET + 0 * WORD)
+ self.mc.std(r.RCS2.value, r.SP.value, LOCAL_VARS_OFFSET + 1 * WORD)
+ self.mc.std(r.RCS3.value, r.SP.value, LOCAL_VARS_OFFSET + 2 * WORD)
+ self.mc.std(r.r3.value, r.SP.value, LOCAL_VARS_OFFSET + 3 * WORD)
+ self.mc.stfd(r.f1.value, r.SP.value, LOCAL_VARS_OFFSET + 4 * WORD)
+ saved_regs = None
+ saved_fp_regs = None
+
+ else:
+ # push all volatile registers, push RCS1, and sometimes push RCS2
+ if withcards:
+ saved_regs = r.VOLATILES + [r.RCS1, r.RCS2]
+ else:
+ saved_regs = r.VOLATILES + [r.RCS1]
+ if withfloats:
+ saved_fp_regs = r.MANAGED_FP_REGS
+ else:
+ saved_fp_regs = []
+
+ self._push_core_regs_to_jitframe(mc, saved_regs)
+ self._push_fp_regs_to_jitframe(mc, saved_fp_regs)
+
+ if for_frame:
+ # note that it's safe to store the exception in register,
+ # since the call to write barrier can't collect
+ # (and this is assumed a bit left and right here, like lack
+ # of _reload_frame_if_necessary)
+ # This trashes r0 and r2, which is fine in this case
+ assert argument_loc is not r.r0
+ self._store_and_reset_exception(mc, r.RCS2, r.RCS3)
+
+ if withcards:
+ mc.mr(r.RCS2.value, argument_loc.value)
+ #
+ # Save the lr into r.RCS1
+ mc.mflr(r.RCS1.value)
+ #
+ func = rffi.cast(lltype.Signed, func)
+ # Note: if not 'for_frame', argument_loc is r0, which must carefully
+ # not be overwritten above
+ mc.mr(r.r3.value, argument_loc.value)
+ mc.load_imm(mc.RAW_CALL_REG, func)
+ mc.raw_call()
+ #
+ # Restore lr
+ mc.mtlr(r.RCS1.value)
+
+ if for_frame:
+ self._restore_exception(mc, r.RCS2, r.RCS3)
+
+ if withcards:
+ # A final andix before the blr, for the caller. Careful to
+ # not follow this instruction with another one that changes
+ # the status of cr0!
+ card_marking_mask = descr.jit_wb_cards_set_singlebyte
+ mc.lbz(r.RCS2.value, r.RCS2.value, descr.jit_wb_if_flag_byteofs)
+ mc.andix(r.RCS2.value, r.RCS2.value, card_marking_mask & 0xFF)
+
+ if for_frame:
+ self.mc.ld(r.RCS1.value, r.SP.value, LOCAL_VARS_OFFSET + 0 * WORD)
+ self.mc.ld(r.RCS2.value, r.SP.value, LOCAL_VARS_OFFSET + 1 * WORD)
+ self.mc.ld(r.RCS3.value, r.SP.value, LOCAL_VARS_OFFSET + 2 * WORD)
+ self.mc.ld(r.r3.value, r.SP.value, LOCAL_VARS_OFFSET + 3 * WORD)
+ self.mc.lfd(r.f1.value, r.SP.value, LOCAL_VARS_OFFSET + 4 * WORD)
+ self.mc.addi(r.SP.value, r.SP.value, extra_stack_size)
+
+ else:
+ self._pop_core_regs_from_jitframe(mc, saved_regs)
+ self._pop_fp_regs_from_jitframe(mc, saved_fp_regs)
+
+ mc.blr()
+
+ self.mc = old_mc
+ rawstart = mc.materialize(self.cpu, [])
+ if for_frame:
+ self.wb_slowpath[4] = rawstart
+ else:
+ self.wb_slowpath[withcards + 2 * withfloats] = rawstart
+
def build_frame_realloc_slowpath(self):
# this code should do the following steps
@@ -154,10 +276,78 @@
# f) store the address of the new jitframe in the shadowstack
# c) set the gcmap field to 0 in the new jitframe
# g) restore registers and return
- pass # TODO
+ mc = PPCBuilder()
+ self.mc = mc
+
+ # signature of this _frame_realloc_slowpath function:
+ # * on entry, r0 is the new size
+ # * on entry, r2 is the gcmap
+ # * no managed register must be modified
+
+ ofs2 = self.cpu.get_ofs_of_frame_field('jf_gcmap')
+ mc.store(r.r2.value, r.SPP.value, ofs2)
+
+ self._push_core_regs_to_jitframe(mc)
+ self._push_fp_regs_to_jitframe(mc)
+
+ # Save away the LR inside r30
+ mc.mflr(r.RCS1.value)
+
+ # First argument is SPP (= r31), which is the jitframe
+ mc.mr(r.r3.value, r.SPP.value)
+
+ # Second argument is the new size, which is still in r0 here
+ mc.mr(r.r4.value, r.r0.value)
+
+ # This trashes r0 and r2
+ self._store_and_reset_exception(mc, r.RCS2, r.RCS3)
+
+ # Do the call
+ adr = rffi.cast(lltype.Signed, self.cpu.realloc_frame)
+ mc.load_imm(mc.RAW_CALL_REG, adr)
+ mc.raw_call()
+
+ # The result is stored back into SPP (= r31)
+ mc.mr(r.SPP.value, r.r3.value)
+
+ self._restore_exception(mc, r.RCS2, r.RCS3)
+
+ gcrootmap = self.cpu.gc_ll_descr.gcrootmap
+ if gcrootmap and gcrootmap.is_shadow_stack:
+ diff = mc.load_imm_plus(r.r5, gcrootmap.get_root_stack_top_addr())
+ mc.load(r.r5.value, r.r5.value, diff)
+ mc.store(r.r3.value, r.r5.value, -WORD)
+
+ mc.mtlr(r.RCS1.value) # restore LR
+ self._pop_core_regs_from_jitframe(mc)
+ self._pop_fp_regs_from_jitframe(mc)
+ mc.blr()
+
+ self._frame_realloc_slowpath = mc.materialize(self.cpu, [])
+ self.mc = None
def _build_propagate_exception_path(self):
- pass # TODO
+ if not self.cpu.propagate_exception_descr:
+ return
+
+ self.mc = PPCBuilder()
+ #
+ # read and reset the current exception
+
+ propagate_exception_descr = rffi.cast(lltype.Signed,
+ cast_instance_to_gcref(self.cpu.propagate_exception_descr))
+ ofs3 = self.cpu.get_ofs_of_frame_field('jf_guard_exc')
+ ofs4 = self.cpu.get_ofs_of_frame_field('jf_descr')
+
+ self._store_and_reset_exception(self.mc, r.r3)
+ self.mc.load_imm(r.r4, propagate_exception_descr)
+ self.mc.std(r.r3.value, r.SPP.value, ofs3)
+ self.mc.std(r.r4.value, r.SPP.value, ofs4)
+ #
+ self._call_footer()
+ rawstart = self.mc.materialize(self.cpu, [])
+ self.propagate_exception_path = rawstart
+ self.mc = None
def _build_cond_call_slowpath(self, supports_floats, callee_only):
""" This builds a general call slowpath, for whatever call happens to
diff --git a/rpython/jit/backend/zarch/helper/regalloc.py
b/rpython/jit/backend/zarch/helper/regalloc.py
--- a/rpython/jit/backend/zarch/helper/regalloc.py
+++ b/rpython/jit/backend/zarch/helper/regalloc.py
@@ -3,6 +3,9 @@
from rpython.jit.backend.llsupport.regalloc import TempVar
import rpython.jit.backend.zarch.registers as r
+def check_imm_value(value, lower_bound=-2**15, upper_bound=2**15-1):
+ return lower_bound <= value <= upper_bound
+
def check_imm(arg, lower_bound=-2**15, upper_bound=2**15-1):
if isinstance(arg, ConstInt):
i = arg.getint()
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
@@ -1,8 +1,10 @@
+from rpython.jit.backend.llsupport.jump import remap_frame_layout
from rpython.jit.backend.zarch.arch import THREADLOCAL_ADDR_OFFSET
from rpython.jit.backend.zarch.helper.assembler import (gen_emit_cmp_op,
gen_emit_rr_or_rpool, gen_emit_shift, gen_emit_pool_or_rr_evenodd,
gen_emit_imm_pool_rr)
-from rpython.jit.backend.zarch.helper.regalloc import (check_imm,)
+from rpython.jit.backend.zarch.helper.regalloc import (check_imm,
+ check_imm_value)
from rpython.jit.backend.zarch.codebuilder import ZARCHGuardToken, InstrBuilder
import rpython.jit.backend.zarch.conditions as c
import rpython.jit.backend.zarch.registers as r
@@ -17,7 +19,7 @@
from rpython.jit.metainterp.resoperation import rop
from rpython.rtyper.lltypesystem import rstr, rffi, lltype
from rpython.rtyper.annlowlevel import cast_instance_to_gcref
-from rpython.jit.backend.llsupport.jump import remap_frame_layout
+from rpython.rlib.objectmodel import we_are_translated
class IntOpAssembler(object):
_mixin_ = True
@@ -407,21 +409,24 @@
assert loc_base.is_reg()
if is_frame:
assert loc_base is r.SPP
- assert check_imm(descr.jit_wb_if_flag_byteofs)
- mc.lbz(r.SCRATCH2.value, loc_base.value, descr.jit_wb_if_flag_byteofs)
- mc.andix(r.SCRATCH.value, r.SCRATCH2.value, mask & 0xFF)
+ assert check_imm_value(descr.jit_wb_if_flag_byteofs)
+ mc.LGB(r.SCRATCH2, l.addr(descr.jit_wb_if_flag_byteofs, loc_base))
+ mc.LGR(r.SCRATCH, r.SCRATCH2)
+ mc.NILL(r.SCRATCH, l.imm(mask & 0xFF))
jz_location = mc.get_relative_pos()
mc.trap() # patched later with 'beq'
+ mc.write('\x00' * 4)
# for cond_call_gc_wb_array, also add another fast path:
# if GCFLAG_CARDS_SET, then we can just set one bit and be done
if card_marking_mask:
# GCFLAG_CARDS_SET is in the same byte, loaded in r2 already
- mc.andix(r.SCRATCH.value, r.SCRATCH2.value,
- card_marking_mask & 0xFF)
+ mc.LGR(r.SCRATCH, r.SCRATCH2)
+ mc.NILL(r.SCRATCH, l.imm(card_marking_mask & 0xFF))
js_location = mc.get_relative_pos()
mc.trap() # patched later with 'bne'
+ mc.write('\x00' * 4)
else:
js_location = 0
@@ -491,7 +496,7 @@
byte_index = loc_index.value >> descr.jit_wb_card_page_shift
byte_ofs = ~(byte_index >> 3)
byte_val = 1 << (byte_index & 7)
- assert check_imm(byte_ofs)
+ assert check_imm_value(byte_ofs)
mc.lbz(r.SCRATCH.value, loc_base.value, byte_ofs)
mc.ori(r.SCRATCH.value, r.SCRATCH.value, byte_val)
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
@@ -10,23 +10,24 @@
from rpython.jit.metainterp.history import JitCellToken, TargetToken
from rpython.jit.metainterp.resoperation import rop
from rpython.jit.backend.zarch import locations as l
-from rpython.rtyper.lltypesystem import rffi, lltype, rstr, llmemory
-from rpython.rtyper.lltypesystem.lloperation import llop
-from rpython.rtyper.annlowlevel import cast_instance_to_gcref
from rpython.jit.backend.llsupport import symbolic
from rpython.jit.backend.llsupport.descr import ArrayDescr
-import rpython.jit.backend.zarch.registers as r
-import rpython.jit.backend.zarch.conditions as c
-import rpython.jit.backend.zarch.helper.regalloc as helper
from rpython.jit.backend.llsupport.descr import unpack_arraydescr
from rpython.jit.backend.llsupport.descr import unpack_fielddescr
from rpython.jit.backend.llsupport.descr import unpack_interiorfielddescr
from rpython.jit.backend.llsupport.gcmap import allocate_gcmap
+import rpython.jit.backend.zarch.registers as r
+import rpython.jit.backend.zarch.conditions as c
+import rpython.jit.backend.zarch.helper.regalloc as helper
+from rpython.jit.backend.zarch.helper.regalloc import (check_imm,)
+from rpython.jit.codewriter.effectinfo import EffectInfo
from rpython.rlib.objectmodel import we_are_translated
from rpython.rlib.debug import debug_print
-from rpython.jit.codewriter.effectinfo import EffectInfo
from rpython.rlib import rgc
from rpython.rlib.rarithmetic import r_uint
+from rpython.rtyper.lltypesystem import rffi, lltype, rstr, llmemory
+from rpython.rtyper.lltypesystem.lloperation import llop
+from rpython.rtyper.annlowlevel import cast_instance_to_gcref
LIMIT_LOOP_BREAK = 15000 # should be much smaller than 32 KB
@@ -98,7 +99,7 @@
forbidden_vars=self.temp_boxes)
return loc
- def get_scratch_reg(self):
+ def get_scratch_reg(self,):
box = TempFloat()
reg = self.force_allocate_reg(box, forbidden_vars=self.temp_boxes)
self.temp_boxes.append(box)
@@ -898,6 +899,18 @@
locs.append(loc)
return locs
+ def prepare_cond_call_gc_wb(self, op):
+ arglocs = [self.ensure_reg(op.getarg(0))]
+ return arglocs
+
+ def prepare_cond_call_gc_wb_array(self, op):
+ arglocs = [self.ensure_reg(op.getarg(0)),
+ self.ensure_reg_or_16bit_imm(op.getarg(1)),
+ None]
+ if arglocs[1].is_reg():
+ arglocs[2] = self.get_scratch_reg(INT)
+ return arglocs
+
def _prepare_math_sqrt(self, op):
loc = self.ensure_reg(op.getarg(1), force_in_reg=True)
self.free_op_vars()
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit