Author: David Schneider <[email protected]>
Branch: jitframe-on-heap
Changeset: r62320:5c95268a7e45
Date: 2013-03-12 17:42 +0100
http://bitbucket.org/pypy/pypy/changeset/5c95268a7e45/
Log: pass test_shadowstack_call and
test_shadowstack_collecting_call_float
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
@@ -52,7 +52,7 @@
self._exit_code_addr = 0
self.current_clt = None
self.malloc_slowpath = 0
- self.wb_slowpath = [0, 0, 0, 0]
+ self.wb_slowpath = [0, 0, 0, 0, 0]
self._regalloc = None
self.datablockwrapper = None
self.propagate_exception_path = 0
@@ -400,10 +400,10 @@
def _reload_frame_if_necessary(self, mc, align_stack=False, can_collect=0):
gcrootmap = self.cpu.gc_ll_descr.gcrootmap
if gcrootmap and gcrootmap.is_shadow_stack:
- import pdb; pdb.set_trace()
rst = gcrootmap.get_root_stack_top_addr()
- mc.MOV(ecx, heap(rst))
- mc.MOV(ebp, mem(ecx, -WORD))
+ mc.gen_load_int(r.ip.value, rst)
+ self.load_reg(mc, r.ip, r.ip)
+ self.load_reg(mc, r.fp, r.ip, ofs=-WORD)
wbdescr = self.cpu.gc_ll_descr.write_barrier_descr
if gcrootmap and wbdescr:
# frame never uses card marking, so we enforce this is not
@@ -558,25 +558,24 @@
def gen_shadowstack_header(self, gcrootmap):
# we need to put two words into the shadowstack: the MARKER_FRAME
# and the address of the frame (fp, actually)
+ # lr = rst addr
+ # ip = *lr
rst = gcrootmap.get_root_stack_top_addr()
- self.mc.gen_load_int(r.ip.value, rst)
- self.mc.LDR_ri(r.r4.value, r.ip.value) # LDR r4, [rootstacktop]
+ self.mc.gen_load_int(r.lr.value, rst)
+ self.load_reg(self.mc, r.ip, r.lr)
+ # *ip = r.fp
+ self.store_reg(self.mc, r.fp, r.ip)
#
- MARKER = gcrootmap.MARKER_FRAME
- self.mc.ADD_ri(r.r5.value, r.r4.value,
- imm=2 * WORD) # ADD r5, r4 [2*WORD]
- self.mc.gen_load_int(r.r6.value, MARKER)
- self.mc.STR_ri(r.r6.value, r.r4.value, WORD) # STR MARKER, r4 [WORD]
- self.mc.STR_ri(r.fp.value, r.r4.value) # STR fp, r4
- #
- self.mc.STR_ri(r.r5.value, r.ip.value) # STR r5 [rootstacktop]
+ self.mc.ADD_ri(r.ip.value, r.ip.value, WORD)
+ # *lr = ip + WORD
+ self.store_reg(self.mc, r.ip, r.lr)
def gen_footer_shadowstack(self, gcrootmap, mc):
rst = gcrootmap.get_root_stack_top_addr()
mc.gen_load_int(r.ip.value, rst)
- mc.LDR_ri(r.r4.value, r.ip.value) # LDR r4, [rootstacktop]
- mc.SUB_ri(r.r5.value, r.r4.value, imm=2 * WORD) # ADD r5, r4 [2*WORD]
- mc.STR_ri(r.r5.value, r.ip.value)
+ self.load_reg(mc, r.r4, r.ip)
+ mc.SUB_ri(r.r4.value, r.r4.value, WORD)
+ self.store_reg(mc, r.r4, r.ip)
def _dump(self, ops, type='loop'):
debug_start('jit-backend-ops')
@@ -854,8 +853,8 @@
def _load_shadowstack_top(self, mc, reg, gcrootmap):
rst = gcrootmap.get_root_stack_top_addr()
- self.mc.gen_load_int(reg.value, rst)
- self.mc.gen_load_int(reg.value, reg.value)
+ mc.gen_load_int(reg.value, rst)
+ mc.gen_load_int(reg.value, reg.value)
return rst
def fixup_target_tokens(self, rawstart):
@@ -1012,7 +1011,7 @@
mc.VLDR(target.value, helper.value, cond=cond)
def _load_core_reg(self, mc, target, base, ofs, cond=c.AL, helper=r.ip):
- if check_imm_arg(ofs):
+ if check_imm_arg(abs(ofs)):
mc.LDR_ri(target.value, base.value, imm=ofs, cond=cond)
else:
mc.gen_load_int(helper.value, ofs, cond=cond)
@@ -1295,7 +1294,9 @@
def pop_gcmap(self, mc):
ofs = self.cpu.get_ofs_of_frame_field('jf_gcmap')
- mc.MOV_bi(ofs, 0)
+ assert check_imm_arg(ofs)
+ mc.gen_load_int(r.ip.value, 0)
+ self.store_reg(mc, r.ip, r.fp, ofs)
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
@@ -349,14 +349,19 @@
return cond
def _emit_call(self, adr, arglocs, fcond=c.AL, resloc=None,
- result_info=(-1, -1)):
+ result_info=(-1, -1),
+ can_collect=1):
if self.cpu.use_hf_abi:
- stack_args, adr = self._setup_call_hf(adr,
- arglocs, fcond, resloc, result_info)
+ stack_args, adr = self._setup_call_hf(adr, arglocs, fcond,
+ resloc, result_info)
else:
- stack_args, adr = self._setup_call_sf(adr,
- arglocs, fcond, resloc, result_info)
+ stack_args, adr = self._setup_call_sf(adr, arglocs, fcond,
+ resloc, result_info)
+ if can_collect:
+ noregs = self.cpu.gc_ll_descr.is_shadow_stack()
+ gcmap = self._regalloc.get_gcmap([r.r0], noregs=noregs)
+ self.push_gcmap(self.mc, gcmap, store=True)
#the actual call
#self.mc.BKPT()
if adr.is_imm():
@@ -378,6 +383,9 @@
elif resloc.is_reg() and result_info != (-1, -1):
self._ensure_result_bit_extension(resloc, result_info[0],
result_info[1])
+ if can_collect:
+ self._reload_frame_if_necessary(self.mc, can_collect=can_collect)
+ self.pop_gcmap(self.mc)
return fcond
def _restore_sp(self, stack_args, fcond):
@@ -573,7 +581,7 @@
self._write_barrier_fastpath(self.mc, op.getdescr(), arglocs,
fcond, array=True)
- def _write_barrier_fastpath(self, mc, descr, arglocs, fcond, array=False,
+ def _write_barrier_fastpath(self, mc, descr, arglocs, fcond=c.AL,
array=False,
is_frame=False):
# Write code equivalent to write_barrier() in the GC: it checks
# a flag in the object at arglocs[0], and if set, it calls a
@@ -596,22 +604,21 @@
loc_base = arglocs[0]
if is_frame:
assert loc_base is r.fp
- else:
- self.mc.LDRB_ri(r.ip.value, loc_base.value,
- imm=descr.jit_wb_if_flag_byteofs)
+ mc.LDRB_ri(r.ip.value, loc_base.value,
+ imm=descr.jit_wb_if_flag_byteofs)
mask &= 0xFF
- self.mc.TST_ri(r.ip.value, imm=mask)
- jz_location = self.mc.currpos()
- self.mc.BKPT()
+ mc.TST_ri(r.ip.value, imm=mask)
+ jz_location = mc.currpos()
+ mc.BKPT()
# 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:
# GCFLAG_CARDS_SET is in this byte at 0x80
- self.mc.TST_ri(r.ip.value, imm=0x80)
+ mc.TST_ri(r.ip.value, imm=0x80)
- js_location = self.mc.currpos()
- self.mc.BKPT()
+ js_location = mc.currpos()
+ mc.BKPT()
else:
js_location = 0
@@ -619,7 +626,7 @@
# argument the address of the structure we are writing into
# (the first argument to COND_CALL_GC_WB).
helper_num = card_marking
- if self._regalloc.vfprm.reg_bindings:
+ if self._regalloc is not None and self._regalloc.vfprm.reg_bindings:
helper_num += 2
if self.wb_slowpath[helper_num] == 0: # tests only
assert not we_are_translated()
@@ -628,24 +635,24 @@
bool(self._regalloc.vfprm.reg_bindings))
assert self.wb_slowpath[helper_num] != 0
#
- if loc_base is not r.r0:
+ if not is_frame and loc_base is not r.r0:
# push two registers to keep stack aligned
- self.mc.PUSH([r.r0.value, loc_base.value])
+ mc.PUSH([r.r0.value, loc_base.value])
remap_frame_layout(self, [loc_base], [r.r0], r.ip)
- self.mc.BL(self.wb_slowpath[helper_num])
- if loc_base is not r.r0:
- self.mc.POP([r.r0.value, loc_base.value])
+ mc.BL(self.wb_slowpath[helper_num])
+ if not is_frame and loc_base is not r.r0:
+ mc.POP([r.r0.value, loc_base.value])
if card_marking:
# The helper ends again with a check of the flag in the object. So
# here, we can simply write again a conditional jump, which will be
# taken if GCFLAG_CARDS_SET is still not set.
- jns_location = self.mc.currpos()
- self.mc.BKPT()
+ jns_location = mc.currpos()
+ mc.BKPT()
#
# patch the JS above
- offset = self.mc.currpos()
- pmc = OverwritingBuilder(self.mc, js_location, WORD)
+ offset = mc.currpos()
+ pmc = OverwritingBuilder(mc, js_location, WORD)
pmc.B_offs(offset, c.NE) # We want to jump if the z flag isn't set
#
# case GCFLAG_CARDS_SET: emit a few instructions to do
@@ -653,36 +660,36 @@
loc_index = arglocs[1]
assert loc_index.is_reg()
# must save the register loc_index before it is mutated
- self.mc.PUSH([loc_index.value])
+ mc.PUSH([loc_index.value])
tmp1 = loc_index
tmp2 = arglocs[-1] # the last item is a preallocated tmp
# lr = byteofs
s = 3 + descr.jit_wb_card_page_shift
- self.mc.MVN_rr(r.lr.value, loc_index.value,
+ mc.MVN_rr(r.lr.value, loc_index.value,
imm=s, shifttype=shift.LSR)
# tmp1 = byte_index
- self.mc.MOV_ri(r.ip.value, imm=7)
- self.mc.AND_rr(tmp1.value, r.ip.value, loc_index.value,
+ mc.MOV_ri(r.ip.value, imm=7)
+ mc.AND_rr(tmp1.value, r.ip.value, loc_index.value,
imm=descr.jit_wb_card_page_shift, shifttype=shift.LSR)
# set the bit
- self.mc.MOV_ri(tmp2.value, imm=1)
- self.mc.LDRB_rr(r.ip.value, loc_base.value, r.lr.value)
- self.mc.ORR_rr_sr(r.ip.value, r.ip.value, tmp2.value,
+ mc.MOV_ri(tmp2.value, imm=1)
+ mc.LDRB_rr(r.ip.value, loc_base.value, r.lr.value)
+ mc.ORR_rr_sr(r.ip.value, r.ip.value, tmp2.value,
tmp1.value, shifttype=shift.LSL)
- self.mc.STRB_rr(r.ip.value, loc_base.value, r.lr.value)
+ mc.STRB_rr(r.ip.value, loc_base.value, r.lr.value)
# done
- self.mc.POP([loc_index.value])
+ mc.POP([loc_index.value])
#
#
# patch the JNS above
- offset = self.mc.currpos()
- pmc = OverwritingBuilder(self.mc, jns_location, WORD)
+ offset = mc.currpos()
+ pmc = OverwritingBuilder(mc, jns_location, WORD)
pmc.B_offs(offset, c.EQ) # We want to jump if the z flag is set
- offset = self.mc.currpos()
- pmc = OverwritingBuilder(self.mc, jz_location, WORD)
+ offset = mc.currpos()
+ pmc = OverwritingBuilder(mc, jz_location, WORD)
pmc.B_offs(offset, c.EQ)
return fcond
@@ -1044,7 +1051,8 @@
# call memcpy()
regalloc.before_call()
self._emit_call(imm(self.memcpy_addr),
- [dstaddr_loc, srcaddr_loc, length_loc])
+ [dstaddr_loc, srcaddr_loc, length_loc],
+ can_collect=False)
regalloc.possibly_free_var(length_box)
regalloc.possibly_free_var(dstaddr_box)
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
@@ -349,7 +349,7 @@
for box, loc in self.fm.bindings.iteritems():
if box.type == REF and self.rm.is_still_alive(box):
assert loc.is_stack()
- val = loc.value // WORD
+ val = loc.position + JITFRAME_FIXED_SIZE
gcmap[val // WORD // 8] |= r_uint(1) << (val % (WORD * 8))
return gcmap
diff --git a/rpython/jit/backend/llsupport/test/test_gc_integration.py
b/rpython/jit/backend/llsupport/test/test_gc_integration.py
--- a/rpython/jit/backend/llsupport/test/test_gc_integration.py
+++ b/rpython/jit/backend/llsupport/test/test_gc_integration.py
@@ -552,6 +552,9 @@
gcmap = unpack_gcmap(frame)
if self.cpu.IS_64_BIT:
assert gcmap == [28, 29, 30]
+ elif self.cpu.backend_name.startswith('arm'):
+ assert gcmap == [44, 45, 46]
+ pass
else:
assert gcmap == [22, 23, 24]
for item, s in zip(gcmap, new_items):
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit