[pypy-commit] pypy arm-backend-2: start implementing support for out of line guards
bivab
noreply at buildbot.pypy.org
Fri Jul 1 14:18:33 CEST 2011
Author: David Schneider <david.schneider at 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 = []
More information about the pypy-commit
mailing list