Author: David Schneider <david.schnei...@picle.org> Branch: arm-backend-2 Changeset: r45216:fbc58902cd0d Date: 2011-06-30 18:24 +0200 http://bitbucket.org/pypy/pypy/changeset/fbc58902cd0d/
Log: start implementing support for out of line guards diff --git a/pypy/jit/backend/arm/assembler.py b/pypy/jit/backend/arm/assembler.py --- a/pypy/jit/backend/arm/assembler.py +++ b/pypy/jit/backend/arm/assembler.py @@ -25,7 +25,7 @@ from pypy.rpython.annlowlevel import llhelper from pypy.rpython.lltypesystem import lltype, rffi, llmemory from pypy.rpython.lltypesystem.lloperation import llop -from pypy.jit.backend.arm.opassembler import ResOpAssembler +from pypy.jit.backend.arm.opassembler import ResOpAssembler, GuardToken from pypy.rlib.debug import (debug_print, debug_start, debug_stop, have_debug_prints) @@ -76,7 +76,7 @@ self.malloc_str_func_addr = 0 self.malloc_unicode_func_addr = 0 self.memcpy_addr = 0 - self.guard_descrs = None + self.pending_guards = None self._exit_code_addr = 0 self.current_clt = None self.malloc_slowpath = 0 @@ -88,7 +88,7 @@ assert self.memcpy_addr != 0, 'setup_once() not called?' self.current_clt = looptoken.compiled_loop_token self.mc = ARMv7Builder() - self.guard_descrs = [] + self.pending_guards = [] assert self.datablockwrapper is None allblocks = self.get_asmmemmgr_blocks(looptoken) self.datablockwrapper = MachineDataBlockWrapper(self.cpu.asmmemmgr, @@ -98,7 +98,7 @@ self.current_clt = None self._regalloc = None self.mc = None - self.guard_descrs = None + self.pending_guards = None def setup_once(self): # Addresses of functions called by new_xxx operations @@ -300,7 +300,7 @@ return mc.materialize(self.cpu.asmmemmgr, [], self.cpu.gc_ll_descr.gcrootmap) - def _gen_path_to_exit_path(self, op, args, arglocs, fcond=c.AL, save_exc=False): + def gen_descr_encoding(self, op, args, arglocs): descr = op.getdescr() if op.getopnum() != rop.FINISH: assert isinstance(descr, AbstractFailDescr) @@ -357,15 +357,21 @@ n = self.cpu.get_fail_descr_number(descr) encode32(mem, j+1, n) - self.mc.LDR_ri(r.ip.value, r.pc.value, imm=WORD) + return memaddr + + def _gen_path_to_exit_path(self, op, args, arglocs, fcond=c.AL, save_exc=False): + memaddr = self.gen_descr_encoding(op, args, arglocs) + self.gen_exit_code(self.mc, memaddr, fcond, save_exc) + return memaddr + + def gen_exit_code(self, mc, memaddr, fcond=c.AL, save_exc=False): + mc.LDR_ri(r.ip.value, r.pc.value, imm=WORD) if save_exc: path = self._leave_jitted_hook_save_exc else: path = self._leave_jitted_hook - self.mc.B(path) - self.mc.write32(memaddr) - - return memaddr + mc.B(path) + mc.write32(memaddr) def align(self): while(self.mc.currpos() % FUNC_ALIGN != 0): @@ -583,7 +589,7 @@ loop_start = self.materialize_loop(looptoken) looptoken._arm_bootstrap_code = loop_start looptoken._arm_direct_bootstrap_code = loop_start + direct_bootstrap_code - self.update_descrs_for_bridges(loop_start) + self.process_pending_guards(loop_start) if log and not we_are_translated(): print 'Loop', inputargs, operations self.mc._dump_trace(loop_start, 'loop_%s.asm' % self.cpu.total_compiled_loops) @@ -612,7 +618,7 @@ self._patch_sp_offset(sp_patch_location, regalloc.frame_manager.frame_depth) bridge_start = self.materialize_loop(original_loop_token) - self.update_descrs_for_bridges(bridge_start) + self.process_pending_guards(bridge_start) self.patch_trace(faildescr, original_loop_token, bridge_start, regalloc) if log and not we_are_translated(): @@ -628,10 +634,17 @@ return self.mc.materialize(self.cpu.asmmemmgr, allblocks, self.cpu.gc_ll_descr.gcrootmap) - def update_descrs_for_bridges(self, block_start): - for descr in self.guard_descrs: + def process_pending_guards(self, block_start): + clt = self.current_clt + for tok in self.pending_guards: + descr = tok.descr + #XXX _arm_block_start should go in the looptoken descr._arm_block_start = block_start - + descr._failure_recovery_code = tok.encoded_args + descr._arm_guard_pos = tok.offset + if tok.is_invalidate: + clt.invalidate_positions.append( + (block_start + tok.offset, tok.encoded_args)) def get_asmmemmgr_blocks(self, looptoken): clt = looptoken.compiled_loop_token diff --git a/pypy/jit/backend/arm/opassembler.py b/pypy/jit/backend/arm/opassembler.py --- a/pypy/jit/backend/arm/opassembler.py +++ b/pypy/jit/backend/arm/opassembler.py @@ -33,6 +33,13 @@ NO_FORCE_INDEX = -1 +class GuardToken(object): + def __init__(self, descr, offset=0, encoded_args=0, is_invalidate=False): + self.descr = descr + self.offset = offset + self.encoded_args = encoded_args + self.is_invalidate = is_invalidate + class IntOpAsslember(object): _mixin_ = True @@ -161,16 +168,17 @@ def _emit_guard(self, op, arglocs, fcond, save_exc=False): descr = op.getdescr() assert isinstance(descr, AbstractFailDescr) - self.guard_descrs.append(descr) + + if not we_are_translated() and hasattr(op, 'getfailargs'): print 'Failargs: ', op.getfailargs() self.mc.ADD_ri(r.pc.value, r.pc.value, self.guard_size-PC_OFFSET, cond=fcond) - descr._arm_guard_pos = self.mc.currpos() + pos = self.mc.currpos() memaddr = self._gen_path_to_exit_path(op, op.getfailargs(), arglocs, save_exc=save_exc) - descr._failure_recovery_code = memaddr + self.pending_guards.append(GuardToken(op.getdescr(), pos=pos, memaddr=memaddr)) return c.AL def _emit_guard_overflow(self, guard, failargs, fcond): @@ -238,6 +246,11 @@ self._cmp_guard_class(op, arglocs, regalloc, fcond) return fcond + def emit_op_guard_not_invalidated(self, op, locs, regalloc, fcond): + pos = self.mc.currpos() # after potential jmp + memaddr = self.gen_descr_encoding(op, op.getfailargs(), locs) + self.pending_guards.append(GuardToken(op.getdescr(), pos, memaddr, True)) + def _cmp_guard_class(self, op, locs, regalloc, fcond): offset = locs[2] if offset is not None: diff --git a/pypy/jit/backend/arm/regalloc.py b/pypy/jit/backend/arm/regalloc.py --- a/pypy/jit/backend/arm/regalloc.py +++ b/pypy/jit/backend/arm/regalloc.py @@ -509,6 +509,8 @@ return locs prepare_op_guard_overflow = prepare_op_guard_no_overflow + prepare_op_guard_not_invalidated = prepare_op_guard_no_overflow + def prepare_op_guard_exception(self, op, fcond): boxes = list(op.getarglist()) diff --git a/pypy/jit/backend/arm/runner.py b/pypy/jit/backend/arm/runner.py --- a/pypy/jit/backend/arm/runner.py +++ b/pypy/jit/backend/arm/runner.py @@ -128,3 +128,20 @@ def redirect_call_assembler(self, oldlooptoken, newlooptoken): self.assembler.redirect_call_assembler(oldlooptoken, newlooptoken) + + def invalidate_loop(self, looptoken): + """Activate all GUARD_NOT_INVALIDATED in the loop and its attached + bridges. Before this call, all GUARD_NOT_INVALIDATED do nothing; + after this call, they all fail. Note that afterwards, if one such + guard fails often enough, it has a bridge attached to it; it is + possible then to re-call invalidate_loop() on the same looptoken, + which must invalidate all newer GUARD_NOT_INVALIDATED, but not the + old one that already has a bridge attached to it.""" + from pypy.jit.backend.arm.codebuilder import ARMv7Builder + + for tgt, memaddr in looptoken.compiled_loop_token.invalidate_positions: + mc = ARMv7Builder() + self.assembler.gen_exit_code(mc, memaddr) + mc.copy_to_raw_memory(tgt) + # positions invalidated + looptoken.compiled_loop_token.invalidate_positions = [] _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit