Author: Richard Plangger <planri...@gmail.com> Branch: s390x-backend Changeset: r80466:85a292e8a0ad Date: 2015-10-27 11:20 +0100 http://bitbucket.org/pypy/pypy/changeset/85a292e8a0ad/
Log: adapted some arch details, added failure recovery, finish resop (partly) diff --git a/rpython/jit/backend/zarch/arch.py b/rpython/jit/backend/zarch/arch.py --- a/rpython/jit/backend/zarch/arch.py +++ b/rpython/jit/backend/zarch/arch.py @@ -1,4 +1,20 @@ +WORD = 8 -WORD = 4 +# +# OFFSET +# +------------------------------+ 0 +# | gpr save are (int+float) | +# +------------------------------+ 8 +# | local vars | +# +------------------------------+ 0 +# | | +# +------------------------------+ +# | | +# +------------------------------+ <- SP 0 (r15) +# -JITFRAME_FIXED_SIZE = 48 +GPR_STACK_SAVE_IN_BYTES = 120 +STD_FRAME_SIZE_IN_BYTES = 140 +THREADLOCAL_ADDR_OFFSET = 8 + +assert STD_FRAME_SIZE_IN_BYTES % 2 == 0 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 @@ -6,12 +6,16 @@ from rpython.jit.backend.zarch import registers as r from rpython.jit.backend.zarch import locations as loc from rpython.jit.backend.zarch.codebuilder import InstrBuilder -from rpython.jit.backend.zarch.arch import (WORD, JITFRAME_FIXED_SIZE) +from rpython.jit.backend.zarch.registers import JITFRAME_FIXED_SIZE +from rpython.jit.backend.zarch.arch import (WORD, + STD_FRAME_SIZE_IN_BYTES, GPR_STACK_SAVE_IN_BYTES, + THREADLOCAL_ADDR_OFFSET) from rpython.jit.backend.zarch.opassembler import IntOpAssembler from rpython.jit.backend.zarch.regalloc import Regalloc from rpython.jit.metainterp.resoperation import rop from rpython.rlib.debug import (debug_print, debug_start, debug_stop, have_debug_prints) +from rpython.jit.metainterp.history import (INT, REF, FLOAT) from rpython.rlib.rarithmetic import r_uint from rpython.rlib.objectmodel import we_are_translated, specialize, compute_unique_id from rpython.rlib import rgc @@ -30,6 +34,7 @@ self.stack_check_slowpath = 0 self.loop_run_counters = [] self.gcrootmap_retaddr_forced = 0 + self.failure_recovery_code = [0, 0, 0, 0] def setup(self, looptoken): BaseAssembler.setup(self, looptoken) @@ -62,12 +67,14 @@ return clt.asmmemmgr_blocks def gen_func_prolog(self): + """ NOT_RPYTHON """ STACK_FRAME_SIZE = 40 - self.mc.STMG(r.r11, r.r15, loc.addr(-STACK_FRAME_SIZE, r.sp)) + self.mc.STMG(r.r11, r.r15, loc.addr(-STACK_FRAME_SIZE, r.SP)) self.mc.AHI(r.sp, loc.imm(-STACK_FRAME_SIZE)) def gen_func_epilog(self): - self.mc.LMG(r.r11, r.r15, loc.addr(0, r.SPP)) + """ NOT_RPYTHON """ + self.mc.LMG(r.r11, r.r15, loc.addr(0, r.SP)) self.jmpto(r.r14) def jmpto(self, register): @@ -76,7 +83,42 @@ self.mc.BCR_rr(0xf, register.value) def _build_failure_recovery(self, exc, withfloats=False): - pass # TODO + mc = InstrBuilder() + self.mc = mc + # fill in the jf_descr and jf_gcmap fields of the frame according + # to which failure we are resuming from. These are set before + # this function is called (see generate_quick_failure()). + ofs = self.cpu.get_ofs_of_frame_field('jf_descr') + ofs2 = self.cpu.get_ofs_of_frame_field('jf_gcmap') + mc.STG(r.r2, loc.addr(ofs, r.SPP)) + mc.STG(r.r3, loc.addr(ofs2, r.SPP)) + + self._push_core_regs_to_jitframe(mc) + if withfloats: + self._push_fp_regs_to_jitframe(mc) + + if exc: + pass # TODO + #xxx + ## We might have an exception pending. + #mc.load_imm(r.r2, self.cpu.pos_exc_value()) + ## Copy it into 'jf_guard_exc' + #offset = self.cpu.get_ofs_of_frame_field('jf_guard_exc') + #mc.load(r.r0.value, r.r2.value, 0) + #mc.store(r.r0.value, r.SPP.value, offset) + ## Zero out the exception fields + #diff = self.cpu.pos_exception() - self.cpu.pos_exc_value() + #assert _check_imm_arg(diff) + #mc.li(r.r0.value, 0) + #mc.store(r.r0.value, r.r2.value, 0) + #mc.store(r.r0.value, r.r2.value, diff) + + # now we return from the complete frame, which starts from + # _call_header_with_stack_check(). The _call_footer below does it. + self._call_footer() + rawstart = mc.materialize(self.cpu, []) + self.failure_recovery_code[exc + 2 * withfloats] = rawstart + self.mc = None def _build_wb_slowpath(self, withcards, withfloats=False, for_frame=False): pass # TODO @@ -106,7 +148,23 @@ pass # TODO def _call_header_with_stack_check(self): - pass # TODO + self._call_header() + if self.stack_check_slowpath == 0: + pass # not translated + else: + endaddr, lengthaddr, _ = self.cpu.insert_stack_check() + diff = lengthaddr - endaddr + assert _check_imm_arg(diff) + + mc = self.mc + mc.load_imm(r.SCRATCH, self.stack_check_slowpath) + mc.load_imm(r.SCRATCH2, endaddr) # li r2, endaddr + mc.mtctr(r.SCRATCH.value) + mc.load(r.SCRATCH.value, r.SCRATCH2.value, 0) # ld r0, [end] + mc.load(r.SCRATCH2.value, r.SCRATCH2.value, diff)# ld r2, [length] + mc.subf(r.SCRATCH.value, r.SP.value, r.SCRATCH.value) # sub r0, SP + mc.cmp_op(0, r.SCRATCH.value, r.SCRATCH2.value, signed=False) + mc.bgtctrl() @rgc.no_release_gil def assemble_loop(self, jd_id, unique_id, logger, loopname, inputargs, @@ -322,7 +380,48 @@ clt.invalidate_positions.append((rawstart + relpos, relative_target)) + def _call_header(self): + # Reserve space for a function descriptor, 3 words + #self.mc.write64(0) + #self.mc.write64(0) + #self.mc.write64(0) + # Build a new stackframe of size STD_FRAME_SIZE_IN_BYTES + self.mc.STMG(r.r6, r.r15, loc.addr(-GPR_STACK_SAVE_IN_BYTES, r.SP)) + self.mc.AGHI(r.SP, loc.imm(-STD_FRAME_SIZE_IN_BYTES)) + + # save r4, the second argument, to THREADLOCAL_ADDR_OFFSET + self.mc.STG(r.r3, loc.addr(THREADLOCAL_ADDR_OFFSET, r.SP)) + + # move the first argument to SPP: the jitframe object + self.mc.LGR(r.SPP, r.r2) + + gcrootmap = self.cpu.gc_ll_descr.gcrootmap + if gcrootmap and gcrootmap.is_shadow_stack: + self._call_header_shadowstack(gcrootmap) + + def _call_footer(self): + # the return value is the jitframe + self.mc.LGR(r.r2, r.SPP) + + gcrootmap = self.cpu.gc_ll_descr.gcrootmap + if gcrootmap and gcrootmap.is_shadow_stack: + self._call_footer_shadowstack(gcrootmap) + + # restore registers r6-r15 + upoffset = STD_FRAME_SIZE_IN_BYTES-GPR_STACK_SAVE_IN_BYTES + self.mc.LMG(r.r6, r.r15, loc.addr(upoffset, r.SP)) + self.jmpto(r.r14) + + def _push_core_regs_to_jitframe(self, mc, includes=r.MANAGED_REGS): + base_ofs = self.cpu.get_baseofs_of_frame_field() + assert len(includes) == 16 + mc.STMG(r.r0, r.r15, loc.addr(base_ofs, r.SPP)) + + def _push_fp_regs_to_jitframe(self, mc, includes=r.MANAGED_FP_REGS): + base_ofs = self.cpu.get_baseofs_of_frame_field() + assert len(includes) == 16 + mc.LMG(r.r0, r.r15, loc.addr(base_ofs, r.SPP)) # ________________________________________ # ASSEMBLER EMISSION @@ -331,7 +430,52 @@ pass # TODO def emit_finish(self, op, arglocs, regalloc): - pass # TODO + base_ofs = self.cpu.get_baseofs_of_frame_field() + if len(arglocs) > 1: + [return_val, fail_descr_loc] = arglocs + if op.getarg(0).type == FLOAT: + raise NotImplementedError + #self.mc.stfd(return_val, loc.addr(base_ofs, r.SPP)) + else: + self.mc.STG(return_val, loc.addr(base_ofs, r.SPP)) + else: + [fail_descr_loc] = arglocs + + ofs = self.cpu.get_ofs_of_frame_field('jf_descr') + ofs2 = self.cpu.get_ofs_of_frame_field('jf_gcmap') + + # gcmap logic here: + arglist = op.getarglist() + if arglist and arglist[0].type == REF: + if self._finish_gcmap: + # we're returning with a guard_not_forced_2, and + # additionally we need to say that the result contains + # a reference too: + self._finish_gcmap[0] |= r_uint(1) + gcmap = self._finish_gcmap + else: + gcmap = self.gcmap_for_finish + elif self._finish_gcmap: + # we're returning with a guard_not_forced_2 + gcmap = self._finish_gcmap + else: + gcmap = lltype.nullptr(jitframe.GCMAP) + # TODO self.load_gcmap(self.mc, r.r2, gcmap) + + assert fail_descr_loc.getint() <= 2**12-1 + self.mc.LGHI(r.r5, fail_descr_loc) + self.mc.STG(r.r5, loc.addr(ofs, r.SPP)) + self.mc.XGR(r.r2, r.r2) + self.mc.STG(r.r2, loc.addr(ofs2, r.SPP)) + + # exit function + self._call_footer() + + def load_gcmap(self, mc, reg, gcmap): + # load the current gcmap into register 'reg' + ptr = rffi.cast(lltype.Signed, gcmap) + #mc.LGHI(mc.pool + #mc.load_imm(reg, ptr) def notimplemented_op(asm, op, arglocs, regalloc): print "[ZARCH/asm] %s not implemented" % op.getopname() diff --git a/rpython/jit/backend/zarch/instructions.py b/rpython/jit/backend/zarch/instructions.py --- a/rpython/jit/backend/zarch/instructions.py +++ b/rpython/jit/backend/zarch/instructions.py @@ -73,15 +73,23 @@ # load memory 'LMD': ('sse', ['\xEF']), 'LMG': ('rsy', ['\xEB','\x04']), + 'LHI': ('ri', ['\xA7','\x08']), 'LGHI': ('ri', ['\xA7','\x09']), 'LR': ('rr', ['\x18']), 'LGR': ('rre', ['\xB9','\x04']), 'LG': ('rxy', ['\xE3','\x04']), + # store memory + 'STMG': ('rsy', ['\xEB','\x24']), + 'ST': ('rx', ['\x50']), + 'STG': ('rxy', ['\xE3','\x24']), + 'STY': ('rxy', ['\xE3','\x50']), + # store float 'STE': ('rx', ['\x70']), 'STD': ('rx', ['\x60']), + # load binary float # E -> short (32bit), # D -> long (64bit), @@ -166,7 +174,6 @@ 'MVCK': ('ssd', ['\xD9']), 'PKA': ('ssf', ['\xE9']), - 'STMG': ('rsy', ['\xEB','\x24']), 'SVC': ('i', ['\x0A']), } diff --git a/rpython/jit/backend/zarch/locations.py b/rpython/jit/backend/zarch/locations.py --- a/rpython/jit/backend/zarch/locations.py +++ b/rpython/jit/backend/zarch/locations.py @@ -1,5 +1,5 @@ from rpython.jit.metainterp.history import INT, FLOAT -from rpython.jit.backend.zarch.arch import WORD, JITFRAME_FIXED_SIZE +from rpython.jit.backend.zarch.arch import WORD class AssemblerLocation(object): _immutable_ = True @@ -190,6 +190,7 @@ return ImmLocation(i) def get_fp_offset(base_ofs, position): + from rpython.jit.backend.zarch.registers import JITFRAME_FIXED_SIZE return base_ofs + WORD * (position + JITFRAME_FIXED_SIZE) 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 @@ -465,7 +465,17 @@ prepare_int_add = regallochelp._prepare_binary_arith def prepare_finish(self, op): - return [] + descr = op.getdescr() + fail_descr = cast_instance_to_gcref(descr) + # we know it does not move, but well + rgc._make_sure_does_not_move(fail_descr) + fail_descr = rffi.cast(lltype.Signed, fail_descr) + if op.numargs() > 0: + loc = self.ensure_reg(op.getarg(0)) + locs = [loc, imm(fail_descr)] + else: + locs = [imm(fail_descr)] + return locs def notimplemented(self, op): msg = '[S390X/regalloc] %s not implemented\n' % op.getopname() diff --git a/rpython/jit/backend/zarch/registers.py b/rpython/jit/backend/zarch/registers.py --- a/rpython/jit/backend/zarch/registers.py +++ b/rpython/jit/backend/zarch/registers.py @@ -1,5 +1,3 @@ - - from rpython.jit.backend.zarch.locations import FloatRegisterLocation from rpython.jit.backend.zarch.locations import RegisterLocation @@ -9,13 +7,28 @@ [r0,r1,r2,r3,r4,r5,r6,r7,r8, r9,r10,r11,r12,r13,r14,r15] = registers -MANAGED_REGS = [r0,r1,r2,r3,r4] -VOLATILES = [r0,r1,r2,r3,r4] -SPP = r15 +MANAGED_REGS = registers +VOLATILES = [r6,r7,r8,r9,r10,r11,r12,r13,r14,r15] +SP = r15 RETURN = r14 +POOL = r13 +SPP = r11 [f0,f1,f2,f3,f4,f5,f6,f7,f8, f9,f10,f11,f12,f13,f14,f15] = fpregisters MANAGED_FP_REGS = fpregisters VOLATILES_FLOAT = [] + +# The JITFRAME_FIXED_SIZE is measured in words, and should be the +# number of registers that need to be saved into the jitframe when +# failing a guard, for example. +ALL_REG_INDEXES = {} +for _r in MANAGED_REGS: + ALL_REG_INDEXES[_r] = len(ALL_REG_INDEXES) +for _r in MANAGED_FP_REGS: + ALL_REG_INDEXES[_r] = len(ALL_REG_INDEXES) + 1 + # we leave a never-used hole for f0 ^^^ in the jitframe + # to simplify store_info_on_descr(), which assumes that the + # register number N is at offset N after the non-fp regs +JITFRAME_FIXED_SIZE = len(ALL_REG_INDEXES) + 1 diff --git a/rpython/jit/backend/zarch/test/test_runner.py b/rpython/jit/backend/zarch/test/test_runner.py --- a/rpython/jit/backend/zarch/test/test_runner.py +++ b/rpython/jit/backend/zarch/test/test_runner.py @@ -15,7 +15,7 @@ class FakeStats(object): pass -class TestPPC(LLtypeBackendTest): +class TestZARCH(LLtypeBackendTest): # for the individual tests see # ====> ../../test/runner_test.py _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit