Author: Armin Rigo <ar...@tunes.org> Branch: jit-constptr-2 Changeset: r83502:646421afc5c5 Date: 2016-04-01 19:14 +0200 http://bitbucket.org/pypy/pypy/changeset/646421afc5c5/
Log: (untested) ARM support 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 @@ -14,7 +14,7 @@ CoreRegisterManager, check_imm_arg, VFPRegisterManager, operations as regalloc_operations) from rpython.jit.backend.llsupport import jitframe, rewrite -from rpython.jit.backend.llsupport.assembler import DEBUG_COUNTER, debug_bridge, BaseAssembler +from rpython.jit.backend.llsupport.assembler import DEBUG_COUNTER, BaseAssembler from rpython.jit.backend.llsupport.regalloc import get_scale, valid_addressing_size from rpython.jit.backend.llsupport.asmmemmgr import MachineDataBlockWrapper from rpython.jit.backend.model import CompiledLoopToken @@ -481,8 +481,9 @@ def generate_quick_failure(self, guardtok): startpos = self.mc.currpos() - fail_descr, target = self.store_info_on_descr(startpos, guardtok) - self.regalloc_push(imm(fail_descr)) + faildescrindex, target = self.store_info_on_descr(startpos, guardtok) + self.load_from_gc_table(r.ip.value, faildescrindex) + self.regalloc_push(r.ip) self.push_gcmap(self.mc, gcmap=guardtok.gcmap, push=True) self.mc.BL(target) return startpos @@ -596,20 +597,22 @@ frame_info = self.datablockwrapper.malloc_aligned( jitframe.JITFRAMEINFO_SIZE, alignment=WORD) clt.frame_info = rffi.cast(jitframe.JITFRAMEINFOPTR, frame_info) - clt.allgcrefs = [] clt.frame_info.clear() # for now if log: operations = self._inject_debugging_code(looptoken, operations, 'e', looptoken.number) + regalloc = Regalloc(assembler=self) + allgcrefs = [] + operations = regalloc.prepare_loop(inputargs, operations, looptoken, + allgcrefs) + self.reserve_gcref_table(allgcrefs) + functionpos = self.mc.get_relative_pos() + self._call_header_with_stack_check() self._check_frame_depth_debug(self.mc) - regalloc = Regalloc(assembler=self) - operations = regalloc.prepare_loop(inputargs, operations, looptoken, - clt.allgcrefs) - loop_head = self.mc.get_relative_pos() looptoken._ll_loop_code = loop_head # @@ -620,9 +623,11 @@ self.write_pending_failure_recoveries() + full_size = self.mc.get_relative_pos() rawstart = self.materialize_loop(looptoken) - looptoken._function_addr = looptoken._ll_function_addr = rawstart + looptoken._ll_function_addr = rawstart + functionpos + self.patch_gcref_table(looptoken, rawstart) self.process_pending_guards(rawstart) self.fixup_target_tokens(rawstart) @@ -641,7 +646,13 @@ looptoken.number, loopname, r_uint(rawstart + loop_head), r_uint(rawstart + size_excluding_failure_stuff), - r_uint(rawstart))) + r_uint(rawstart + functionpos))) + debug_print(" gc table: 0x%x" % r_uint(rawstart)) + debug_print(" function: 0x%x" % r_uint(rawstart + functionpos)) + debug_print(" resops: 0x%x" % r_uint(rawstart + loop_head)) + debug_print(" failures: 0x%x" % r_uint(rawstart + + size_excluding_failure_stuff)) + debug_print(" end: 0x%x" % r_uint(rawstart + full_size)) debug_stop("jit-backend-addr") return AsmInfo(ops_offset, rawstart + loop_head, @@ -678,27 +689,43 @@ arglocs = self.rebuild_faillocs_from_descr(faildescr, inputargs) regalloc = Regalloc(assembler=self) - startpos = self.mc.get_relative_pos() + allgcrefs = [] operations = regalloc.prepare_bridge(inputargs, arglocs, operations, - self.current_clt.allgcrefs, + allgcrefs, self.current_clt.frame_info) + self.reserve_gcref_table(allgcrefs) + startpos = self.mc.get_relative_pos() self._check_frame_depth(self.mc, regalloc.get_gcmap()) + bridgestartpos = self.mc.get_relative_pos() frame_depth_no_fixed_size = self._assemble(regalloc, inputargs, operations) codeendpos = self.mc.get_relative_pos() self.write_pending_failure_recoveries() + fullsize = self.mc.get_relative_pos() rawstart = self.materialize_loop(original_loop_token) + self.patch_gcref_table(original_loop_token, rawstart) self.process_pending_guards(rawstart) + debug_start("jit-backend-addr") + debug_print("bridge out of Guard 0x%x has address 0x%x to 0x%x" % + (r_uint(descr_number), r_uint(rawstart + startpos), + r_uint(rawstart + codeendpos))) + debug_print(" gc table: 0x%x" % r_uint(rawstart)) + debug_print(" jump target: 0x%x" % r_uint(rawstart + startpos)) + debug_print(" resops: 0x%x" % r_uint(rawstart + bridgestartpos)) + debug_print(" failures: 0x%x" % r_uint(rawstart + codeendpos)) + debug_print(" end: 0x%x" % r_uint(rawstart + fullsize)) + debug_stop("jit-backend-addr") + # patch the jump from original guard self.patch_trace(faildescr, original_loop_token, - rawstart, regalloc) + rawstart + startpos, regalloc) self.patch_stack_checks(frame_depth_no_fixed_size + JITFRAME_FIXED_SIZE, rawstart) @@ -716,9 +743,53 @@ ops_offset=ops_offset) self.teardown() - debug_bridge(descr_number, rawstart, codeendpos) + return AsmInfo(ops_offset, startpos + rawstart, codeendpos - startpos) - return AsmInfo(ops_offset, startpos + rawstart, codeendpos - startpos) + def reserve_gcref_table(self, allgcrefs): + gcref_table_size = len(allgcrefs) * WORD + # align to a multiple of 16 and reserve space at the beginning + # of the machine code for the gc table. This lets us write + # machine code with relative addressing (see load_from_gc_table()) + gcref_table_size = (gcref_table_size + 15) & ~15 + mc = self.mc + assert mc.get_relative_pos() == 0 + for i in range(gcref_table_size): + mc.writechar('\x00') + self.setup_gcrefs_list(allgcrefs) + + def patch_gcref_table(self, looptoken, rawstart): + # the gc table is at the start of the machine code. Fill it now + tracer = self.cpu.gc_ll_descr.make_gcref_tracer(rawstart, + self._allgcrefs) + gcreftracers = self.get_asmmemmgr_gcreftracers(looptoken) + gcreftracers.append(tracer) # keepalive + self.teardown_gcrefs_list() + + def load_from_gc_table(self, regnum, index): + """emits either: + LDR Rt, [PC, #offset] if -4095 <= offset + or: + gen_load_int(Rt, offset) + LDR Rt, [PC, Rt] for larger offsets + """ + mc = self.mc + address_in_buffer = index * WORD # at the start of the buffer + offset = address_in_buffer - (mc.get_relative_pos() + 8) # negative + if offset >= -4095: + mc.LDR_ri(regnum, r.pc.value, offset) + else: + # The offset we're loading is negative: right now, + # gen_load_int() will always use exactly + # get_max_size_of_gen_load_int() instructions. No point + # in optimizing in case we get less. Just in case though, + # we check and pad with nops. + extra_bytes = mc.get_max_size_of_gen_load_int() * 2 + offset -= extra_bytes + start = mc.get_relative_pos() + mc.gen_load_int(regnum, offset) + while mc.get_relative_pos() != start + extra_bytes: + mc.NOP() + mc.LDR_rr(regnum, r.pc.value, regnum) def new_stack_loc(self, i, tp): base_ofs = self.cpu.get_baseofs_of_frame_field() @@ -929,6 +1000,12 @@ clt.asmmemmgr_blocks = [] return clt.asmmemmgr_blocks + def get_asmmemmgr_gcreftracers(self, looptoken): + clt = looptoken.compiled_loop_token + if clt.asmmemmgr_gcreftracers is None: + clt.asmmemmgr_gcreftracers = [] + return clt.asmmemmgr_gcreftracers + def _walk_operations(self, inputargs, operations, regalloc): fcond = c.AL self._regalloc = regalloc 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 @@ -35,9 +35,9 @@ class ArmGuardToken(GuardToken): def __init__(self, cpu, gcmap, faildescr, failargs, fail_locs, - offset, guard_opnum, frame_depth, fcond=c.AL): + offset, guard_opnum, frame_depth, faildescrindex, fcond=c.AL): GuardToken.__init__(self, cpu, gcmap, faildescr, failargs, fail_locs, - guard_opnum, frame_depth) + guard_opnum, frame_depth, faildescrindex) self.fcond = fcond self.offset = offset @@ -178,6 +178,7 @@ assert isinstance(descr, AbstractFailDescr) gcmap = allocate_gcmap(self, frame_depth, JITFRAME_FIXED_SIZE) + faildescrindex = self.get_gcref_from_faildescr(descr) token = ArmGuardToken(self.cpu, gcmap, descr, failargs=op.getfailargs(), @@ -185,6 +186,7 @@ offset=offset, guard_opnum=op.getopnum(), frame_depth=frame_depth, + faildescrindex=faildescrindex, fcond=fcond) return token @@ -398,14 +400,13 @@ def emit_op_finish(self, op, arglocs, regalloc, fcond): base_ofs = self.cpu.get_baseofs_of_frame_field() - if len(arglocs) == 2: - [return_val, fail_descr_loc] = arglocs + if len(arglocs) > 0: + [return_val] = arglocs self.store_reg(self.mc, return_val, r.fp, base_ofs) - else: - [fail_descr_loc] = arglocs ofs = self.cpu.get_ofs_of_frame_field('jf_descr') - self.mc.gen_load_int(r.ip.value, fail_descr_loc.value) + faildescrindex = self.get_gcref_from_faildescr(op.getdescr()) + self.load_from_gc_table(r.ip.value, faildescrindex) # XXX self.mov(fail_descr_loc, RawStackLoc(ofs)) self.store_reg(self.mc, r.ip, r.fp, ofs, helper=r.lr) if op.numargs() > 0 and op.getarg(0).type == REF: @@ -1035,9 +1036,9 @@ assert (guard_op.getopnum() == rop.GUARD_NOT_FORCED or guard_op.getopnum() == rop.GUARD_NOT_FORCED_2) faildescr = guard_op.getdescr() + faildescrindex = self.get_gcref_from_faildescr(faildescr) ofs = self.cpu.get_ofs_of_frame_field('jf_force_descr') - value = rffi.cast(lltype.Signed, cast_instance_to_gcref(faildescr)) - self.mc.gen_load_int(r.ip.value, value) + self.load_from_gc_table(r.ip.value, faildescrindex) self.store_reg(self.mc, r.ip, r.fp, ofs) def _find_nearby_operation(self, delta): @@ -1250,3 +1251,9 @@ self._load_from_mem(res_loc, res_loc, ofs_loc, imm(scale), signed, fcond) return fcond + + def emit_op_load_from_gc_table(self, op, arglocs, regalloc, fcond): + res_loc, = arglocs + index = op.getarg(0).getint() + self.load_from_gc_table(res_loc.value, index) + return 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 @@ -1,5 +1,4 @@ from rpython.rtyper.annlowlevel import cast_instance_to_gcref -from rpython.rlib import rgc from rpython.rlib.debug import debug_print, debug_start, debug_stop from rpython.jit.backend.llsupport.regalloc import FrameManager, \ RegisterManager, TempVar, compute_vars_longevity, BaseRegalloc, \ @@ -627,16 +626,11 @@ def prepare_op_finish(self, op, fcond): # the frame is in fp, but we have to point where in the frame is # the potential argument to FINISH - 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() == 1: loc = self.make_sure_var_in_reg(op.getarg(0)) - locs = [loc, imm(fail_descr)] + locs = [loc] else: - locs = [imm(fail_descr)] + locs = [] return locs def load_condition_into_cc(self, box): @@ -892,6 +886,10 @@ prepare_op_same_as_r = _prepare_op_same_as prepare_op_same_as_f = _prepare_op_same_as + def prepare_op_load_from_gc_table(self, op, fcond): + resloc = self.force_allocate_reg(op) + return [resloc] + def prepare_op_call_malloc_nursery(self, op, fcond): size_box = op.getarg(0) assert isinstance(size_box, ConstInt) _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit