[pypy-commit] pypy jitframe-on-heap: support for new guards handling
bivab
noreply at buildbot.pypy.org
Tue Jan 29 15:16:33 CET 2013
Author: David Schneider <david.schneider at picle.org>
Branch: jitframe-on-heap
Changeset: r60682:f40c4e68b860
Date: 2013-01-29 14:56 +0100
http://bitbucket.org/pypy/pypy/changeset/f40c4e68b860/
Log: support for new guards handling
diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py
--- a/rpython/jit/backend/arm/assembler.py
+++ b/rpython/jit/backend/arm/assembler.py
@@ -8,7 +8,7 @@
N_REGISTERS_SAVED_BY_MALLOC, \
JITFRAME_FIXED_SIZE, FRAME_FIXED_SIZE
from rpython.jit.backend.arm.codebuilder import ARMv7Builder, OverwritingBuilder
-from rpython.jit.backend.arm.locations import get_fp_offset
+from rpython.jit.backend.arm.locations import get_fp_offset, imm
from rpython.jit.backend.arm.regalloc import (Regalloc, ARMFrameManager,
CoreRegisterManager, check_imm_arg,
operations as regalloc_operations,
@@ -372,48 +372,63 @@
# see ../x86/assembler.py:propagate_memoryerror_if_eax_is_null
self.mc.CMP_ri(r.r0.value, 0)
self.mc.B(self.propagate_exception_path, c=c.EQ)
+
+ def _push_all_regs_to_jitframe(self, mc, ignored_regs, withfloats,
+ callee_only=False):
+ if callee_only:
+ regs = CoreRegisterManager.save_around_call_regs
+ else:
+ regs = CoreRegisterManager.all_regs
+ # use STMDB ops here
+ for i, gpr in enumerate(regs):
+ if gpr in ignored_regs:
+ continue
+ mc.STR_ri(gpr.value, r.fp.value, i * WORD)
+ if withfloats:
+ assert 0, 'implement me'
def _build_failure_recovery(self, exc, withfloats=False):
mc = ARMv7Builder()
- failure_recovery = llhelper(self._FAILURE_RECOVERY_FUNC,
- self.failure_recovery_func)
+ self._push_all_regs_to_jitframe(mc, [], withfloats)
self._insert_checks(mc)
- if withfloats:
- f = r.all_vfp_regs
- else:
- f = []
- with saved_registers(mc, r.all_regs, f):
- if exc:
- # We might have an exception pending. Load it into r4
- # (this is a register saved across calls)
- mc.gen_load_int(r.r5.value, self.cpu.pos_exc_value())
- mc.LDR_ri(r.r4.value, r.r5.value)
- # clear the exc flags
- mc.gen_load_int(r.r6.value, 0)
- mc.STR_ri(r.r6.value, r.r5.value)
- mc.gen_load_int(r.r5.value, self.cpu.pos_exception())
- mc.STR_ri(r.r6.value, r.r5.value)
- # move mem block address, to r0 to pass as
- mc.MOV_rr(r.r0.value, r.lr.value)
- # pass the current frame pointer as second param
- mc.MOV_rr(r.r1.value, r.fp.value)
- # pass the current stack pointer as third param
- mc.MOV_rr(r.r2.value, r.sp.value)
- self._insert_checks(mc)
- mc.BL(rffi.cast(lltype.Signed, failure_recovery))
- if exc:
- # save ebx into 'jf_guard_exc'
- from rpython.jit.backend.llsupport.descr import unpack_fielddescr
- descrs = self.cpu.gc_ll_descr.getframedescrs(self.cpu)
- offset, size, _ = unpack_fielddescr(descrs.jf_guard_exc)
- mc.STR_rr(r.r4.value, r.r0.value, offset, cond=c.AL)
- mc.MOV_rr(r.ip.value, r.r0.value)
- mc.MOV_rr(r.r0.value, r.ip.value)
- self.gen_func_epilog(mc=mc)
- rawstart = mc.materialize(self.cpu.asmmemmgr, [],
- self.cpu.gc_ll_descr.gcrootmap)
+
+ if exc:
+ # We might have an exception pending. Load it into r4
+ # (this is a register saved across calls)
+ mc.gen_load_int(r.r5.value, self.cpu.pos_exc_value())
+ mc.LDR_ri(r.r4.value, r.r5.value)
+ # clear the exc flags
+ mc.gen_load_int(r.r6.value, 0)
+ mc.STR_ri(r.r6.value, r.r5.value) # pos_exc_value is still in r5
+ mc.gen_load_int(r.r5.value, self.cpu.pos_exception())
+ mc.STR_ri(r.r6.value, r.r5.value)
+ # save r4 into 'jf_guard_exc'
+ offset = self.cpu.get_ofs_of_frame_field('jf_guard_exc')
+ assert check_imm_arg(abs(offset))
+ mc.STR_ri(r.r4.value, r.fp.value, imm=offset)
+ # now we return from the complete frame, which starts from
+ # _call_header_with_stack_check(). The LEA in _call_footer below
+ # throws away most of the frame, including all the PUSHes that we
+ # did just above.
+ ofs = self.cpu.get_ofs_of_frame_field('jf_descr')
+ assert check_imm_arg(abs(ofs))
+ ofs2 = self.cpu.get_ofs_of_frame_field('jf_gcmap')
+ assert check_imm_arg(abs(ofs2))
+ base_ofs = self.cpu.get_baseofs_of_frame_field()
+ # store the gcmap
+ mc.POP([r.ip.value])
+ mc.STR_ri(r.ip.value, r.fp.value, imm=ofs2)
+ # store the descr
+ mc.POP([r.ip.value])
+ mc.STR_ri(r.ip.value, r.fp.value, imm=ofs)
+
+ # set return value
+ assert check_imm_arg(base_ofs)
+ mc.SUB_ri(r.r0.value, r.fp.value, base_ofs)
+
+ self.gen_func_epilog(mc)
+ rawstart = mc.materialize(self.cpu.asmmemmgr, [])
self.failure_recovery_code[exc + 2 * withfloats] = rawstart
- self.mc = None
DESCR_REF = 0x00
DESCR_INT = 0x01
@@ -459,30 +474,37 @@
def generate_quick_failure(self, guardtok, fcond=c.AL):
- assert isinstance(guardtok.save_exc, bool)
- fail_index = self.cpu.get_fail_descr_number(guardtok.descr)
+ assert isinstance(guardtok.exc, bool)
startpos = self.mc.currpos()
withfloats = False
for box in guardtok.failargs:
if box is not None and box.type == FLOAT:
withfloats = True
break
- exc = guardtok.save_exc
+ exc = guardtok.exc
target = self.failure_recovery_code[exc + 2 * withfloats]
- assert target != 0
+ fail_descr = cast_instance_to_gcref(guardtok.faildescr)
+ fail_descr = rffi.cast(lltype.Signed, fail_descr)
+ positions = [0] * len(guardtok.fail_locs)
+ for i, loc in enumerate(guardtok.fail_locs):
+ if loc is None:
+ positions[i] = -1
+ elif loc.is_stack():
+ positions[i] = loc.value
+ else:
+ if loc.is_reg():
+ assert loc is not r.fp # for now
+ v = loc.value
+ else:
+ assert 0, 'fix for floats'
+ assert loc.is_vfp_reg()
+ #v = len(VFPRegisterManager.all_regs) + loc.value
+ positions[i] = v * WORD
+ # write down the positions of locs
+ guardtok.faildescr.rd_locs = positions
+ self.regalloc_push(imm(fail_descr))
+ self.push_gcmap(self.mc, gcmap=guardtok.gcmap, push=True)
self.mc.BL(target)
- # write tight data that describes the failure recovery
- if guardtok.is_guard_not_forced:
- self.mc.writechar(chr(self.CODE_FORCED))
- self.write_failure_recovery_description(guardtok.descr,
- guardtok.failargs, guardtok.faillocs[1:])
- self.mc.write32(fail_index)
- # for testing the decoding, write a final byte 0xCC
- if not we_are_translated():
- self.mc.writechar('\xCC')
- faillocs = [loc for loc in guardtok.faillocs if loc is not None]
- guardtok.descr._arm_debug_faillocs = faillocs
- self.align()
return startpos
def align(self):
@@ -747,13 +769,11 @@
for tok in self.pending_guards:
#generate the exit stub and the encoded representation
tok.pos_recovery_stub = self.generate_quick_failure(tok)
- # store info on the descr
- tok.descr._arm_current_frame_depth = tok.faillocs[0].getint()
def process_pending_guards(self, block_start):
clt = self.current_clt
for tok in self.pending_guards:
- descr = tok.descr
+ descr = tok.faildescr
assert isinstance(descr, AbstractFailDescr)
failure_recovery_pos = block_start + tok.pos_recovery_stub
descr._arm_failure_recovery_block = failure_recovery_pos
@@ -1213,16 +1233,18 @@
# keep the ref alive
self.current_clt.allgcrefs.append(gcmapref)
rgc._make_sure_does_not_move(gcmapref)
- pass
- #if push:
- # mc.PUSH(imm(rffi.cast(lltype.Signed, gcmapref)))
- #elif mov:
- # mc.MOV(RawEspLoc(0, REF),
- # imm(rffi.cast(lltype.Signed, gcmapref)))
- #else:
- # assert store
- # ofs = self.cpu.get_ofs_of_frame_field('jf_gcmap')
- # mc.MOV(raw_stack(ofs), imm(rffi.cast(lltype.Signed, gcmapref)))
+ if push:
+ mc.gen_load_int(r.ip.value, rffi.cast(lltype.Signed, gcmapref))
+ mc.PUSH([r.ip.value])
+ elif mov:
+ assert 0
+ mc.MOV(RawEspLoc(0, REF),
+ imm(rffi.cast(lltype.Signed, gcmapref)))
+ else:
+ assert store
+ ofs = self.cpu.get_ofs_of_frame_field('jf_gcmap')
+ mc.gen_load_int(r.ip.value, rffi.cast(lltype.Signed, gcmapref))
+ mc.STR_ri(r.ip.value, r.fp.value, imm=ofs)
def pop_gcmap(self, mc):
ofs = self.cpu.get_ofs_of_frame_field('jf_gcmap')
diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py
--- a/rpython/jit/backend/arm/opassembler.py
+++ b/rpython/jit/backend/arm/opassembler.py
@@ -2,7 +2,7 @@
from rpython.jit.backend.arm import conditions as c
from rpython.jit.backend.arm import registers as r
from rpython.jit.backend.arm import shift
-from rpython.jit.backend.arm.arch import WORD, DOUBLE_WORD
+from rpython.jit.backend.arm.arch import WORD, DOUBLE_WORD, JITFRAME_FIXED_SIZE
from rpython.jit.backend.arm.helper.assembler import (gen_emit_op_by_helper_call,
gen_emit_op_unary_cmp,
@@ -21,7 +21,7 @@
from rpython.jit.backend.arm.jump import remap_frame_layout
from rpython.jit.backend.arm.regalloc import TempInt, TempPtr
from rpython.jit.backend.arm.locations import imm
-from rpython.jit.backend.llsupport import symbolic
+from rpython.jit.backend.llsupport import symbolic, jitframe
from rpython.jit.backend.llsupport.descr import InteriorFieldDescr
from rpython.jit.metainterp.history import (Box, AbstractFailDescr,
INT, FLOAT, REF)
@@ -35,18 +35,43 @@
class GuardToken(object):
- def __init__(self, descr, failargs, faillocs, offset, save_exc, fcond=c.AL,
+ def __init__(self, faildescr, failargs, fail_locs, offset, exc, fcond=c.AL,
is_guard_not_invalidated=False, is_guard_not_forced=False):
- assert isinstance(save_exc, bool)
- self.descr = descr
+ assert isinstance(exc, bool)
+ self.faildescr = faildescr
+ self.failargs = failargs
+ self.fail_locs = fail_locs[1:]
self.offset = offset
+ self.gcmap = self.compute_gcmap(failargs, fail_locs, fail_locs[0].value)
+ self.exc = exc
self.is_guard_not_invalidated = is_guard_not_invalidated
self.is_guard_not_forced = is_guard_not_forced
- self.failargs = failargs
- self.faillocs = faillocs
- self.save_exc = save_exc
self.fcond = fcond
+ def compute_gcmap(self, failargs, fail_locs, frame_depth):
+ # note that regalloc has a very similar compute, but
+ # one that does iteration over all bindings, so slightly different,
+ # eh
+ size = frame_depth + JITFRAME_FIXED_SIZE
+ gcmap = lltype.malloc(jitframe.GCMAP, size // WORD // 8 + 1,
+ zero=True)
+ input_i = 0
+ for i in range(len(failargs)):
+ arg = failargs[i]
+ if arg is None:
+ continue
+ loc = fail_locs[input_i]
+ input_i += 1
+ if arg.type == REF:
+ loc = fail_locs[i]
+ if loc.is_reg():
+ val = loc.value
+ else:
+ assert 0, 'ffuu, implement'
+ val = loc.value // WORD
+ gcmap[val // WORD // 8] |= r_uint(1) << (val % (WORD * 8))
+ return gcmap
+
class ResOpAssembler(object):
@@ -211,9 +236,9 @@
self.mc.BKPT()
self.pending_guards.append(GuardToken(descr,
failargs=op.getfailargs(),
- faillocs=arglocs,
+ fail_locs=arglocs,
offset=pos,
- save_exc=save_exc,
+ exc=save_exc,
is_guard_not_invalidated=is_guard_not_invalidated,
is_guard_not_forced=is_guard_not_forced,
fcond=fcond))
diff --git a/rpython/jit/backend/arm/regalloc.py b/rpython/jit/backend/arm/regalloc.py
--- a/rpython/jit/backend/arm/regalloc.py
+++ b/rpython/jit/backend/arm/regalloc.py
@@ -709,6 +709,7 @@
# optimization only: fill in the 'hint_frame_locations' dictionary
# of rm and xrm based on the JUMP at the end of the loop, by looking
# at where we would like the boxes to be after the jump.
+ return # XXX disabled for now
op = operations[-1]
if op.getopnum() != rop.JUMP:
return
More information about the pypy-commit
mailing list