def test_frame_manager_basic(self): b0, b1 = newboxes(0, 1) fm = TFrameManager() loc0 = fm.loc(b0) assert fm.get_loc_index(loc0) == 0 # assert fm.get(b1) is None loc1 = fm.loc(b1) assert fm.get_loc_index(loc1) == 1 assert fm.get(b1) == loc1 # loc0b = fm.loc(b0) assert loc0b == loc0 # fm.loc(InputArgInt()) assert fm.get_frame_depth() == 3 # f0 = InputArgFloat() locf0 = fm.loc(f0) # can't be odd assert fm.get_loc_index(locf0) == 4 assert fm.get_frame_depth() == 6 # f1 = InputArgFloat() locf1 = fm.loc(f1) assert fm.get_loc_index(locf1) == 6 assert fm.get_frame_depth() == 8 fm.mark_as_free(b1) assert fm.freelist b2 = InputArgInt() fm.loc(b2) # should be in the same spot as b1 before assert fm.get(b1) is None assert fm.get(b2) == loc1 fm.mark_as_free(b0) p0 = InputArgRef() ploc = fm.loc(p0) assert fm.get_loc_index(ploc) == 0 assert fm.get_frame_depth() == 8 assert ploc != loc1 p1 = InputArgRef() p1loc = fm.loc(p1) assert fm.get_loc_index(p1loc) == 3 assert fm.get_frame_depth() == 8 fm.mark_as_free(p0) p2 = InputArgRef() p2loc = fm.loc(p2) assert p2loc == ploc assert len(fm.freelist) == 0 fm.mark_as_free(b2) f3 = InputArgFloat() fm.mark_as_free(p2) floc = fm.loc(f3) assert fm.get_loc_index(floc) == 0 for box in fm.bindings.keys(): fm.mark_as_free(box)
def __init__(self, cpu, builder_factory, r, startvars=None, output=None): self.cpu = cpu self.output = output if startvars is None: startvars = [] if cpu.supports_floats: # pick up a single threshold for the whole 'inputargs', so # that some loops have no or mostly no FLOATs while others # have a lot of them k = r.random() # but make sure there is at least one INT at_least_once = r.randrange(0, pytest.config.option.n_vars) else: k = -1 at_least_once = 0 for i in range(pytest.config.option.n_vars): if r.random() < k and i != at_least_once: startvars.append(InputArgFloat(r.random_float_storage())) else: startvars.append(InputArgInt(r.random_integer())) allow_delay = True else: allow_delay = False assert len(dict.fromkeys(startvars)) == len(startvars) self.startvars = startvars self.prebuilt_ptr_consts = [] self.r = r self.subloops = [] self.build_random_loop(cpu, builder_factory, r, startvars, allow_delay)
def test_call_many_float_args(self): from rpython.rtyper.annlowlevel import llhelper from rpython.jit.codewriter.effectinfo import EffectInfo seen = [] def func(*args): seen.append(args) return -42 F = lltype.Float I = lltype.Signed FUNC = self.FuncType([F] * 7 + [I] + [F] * 7 + [I] + [F], I) FPTR = self.Ptr(FUNC) func_ptr = llhelper(FPTR, func) cpu = self.cpu calldescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, EffectInfo.MOST_GENERAL) funcbox = self.get_funcbox(cpu, func_ptr) argvals = [.1 * i for i in range(15)] argvals.insert(7, 77) argvals.insert(15, 1515) argvals = tuple(argvals) argboxes = [] for x in argvals: if isinstance(x, float): argboxes.append(InputArgFloat(x)) else: argboxes.append(InputArgInt(x)) res = self.execute_operation(rop.CALL_I, [funcbox] + argboxes, 'int', descr=calldescr) assert res == -42 assert seen == [argvals]
def get_runtime_field(self, box, descr): struct = box.getref_base() if descr.is_pointer_field(): return InputArgRef(self.cpu.bh_getfield_gc_r(struct, descr)) elif descr.is_float_field(): return InputArgFloat(self.cpu.bh_getfield_gc_f(struct, descr)) else: return InputArgInt(self.cpu.bh_getfield_gc_i(struct, descr))
def get_runtime_item(self, box, descr, i): array = box.getref_base() if descr.is_array_of_pointers(): return InputArgRef(self.cpu.bh_getarrayitem_gc_r(array, i, descr)) elif descr.is_array_of_floats(): return InputArgFloat(self.cpu.bh_getarrayitem_gc_f(array, i, descr)) else: return InputArgInt(self.cpu.bh_getarrayitem_gc_i(array, i, descr))
def newinputarg(self, elem): if elem.startswith("i"): v = InputArgInt(0) elif elem.startswith("f"): v = InputArgFloat.fromfloat(0.0) else: from rpython.rtyper.lltypesystem import lltype, llmemory assert elem.startswith("p") v = InputArgRef(lltype.nullptr(llmemory.GCREF.TO)) self.vars[elem] = v return v
def compile_tmp_callback(cpu, jitdriver_sd, greenboxes, redargtypes, memory_manager=None): """Make a LoopToken that corresponds to assembler code that just calls back the interpreter. Used temporarily: a fully compiled version of the code may end up replacing it. """ jitcell_token = make_jitcell_token(jitdriver_sd) # # record the target of a temporary callback to the interpreter jl.tmp_callback(jitcell_token) # nb_red_args = jitdriver_sd.num_red_args assert len(redargtypes) == nb_red_args inputargs = [] for kind in redargtypes: if kind == history.INT: box = InputArgInt() elif kind == history.REF: box = InputArgRef() elif kind == history.FLOAT: box = InputArgFloat() else: raise AssertionError inputargs.append(box) k = jitdriver_sd.portal_runner_adr funcbox = history.ConstInt(adr2int(k)) callargs = [funcbox] + greenboxes + inputargs # jd = jitdriver_sd opnum = OpHelpers.call_for_descr(jd.portal_calldescr) call_op = ResOperation(opnum, callargs, descr=jd.portal_calldescr) if call_op.type != 'v' is not None: finishargs = [call_op] else: finishargs = [] # faildescr = jitdriver_sd.propagate_exc_descr operations = [ call_op, ResOperation(rop.GUARD_NO_EXCEPTION, [], descr=faildescr), ResOperation(rop.FINISH, finishargs, descr=jd.portal_finishtoken) ] operations[1].setfailargs([]) operations = get_deep_immutable_oplist(operations) cpu.compile_loop(inputargs, operations, jitcell_token, log=False) if memory_manager is not None: # for tests memory_manager.keep_loop_alive(jitcell_token) return jitcell_token
def test_different_frame_width(self): class XRegisterManager(RegisterManager): pass fm = TFrameManager() b0 = InputArgInt() longevity = {b0: Lifetime(0, 1)} asm = MockAsm() rm = RegisterManager(longevity, frame_manager=fm, assembler=asm) f0 = InputArgFloat() longevity = {f0: Lifetime(0, 1)} xrm = XRegisterManager(longevity, frame_manager=fm, assembler=asm) xrm.loc(f0) rm.loc(b0) assert fm.get_frame_depth() == 3
def newinputarg(self, elem): if elem.startswith('i'): v = InputArgInt(0) elif elem.startswith('f'): v = InputArgFloat.fromfloat(0.0) elif elem.startswith('v'): v = InputArgVector() elem = self.update_vector(v, elem) else: from rpython.rtyper.lltypesystem import lltype, llmemory assert elem.startswith('p') v = InputArgRef(lltype.nullptr(llmemory.GCREF.TO)) # ensure that the variable gets the proper naming self.update_memo(v, elem) self.vars[elem] = v return v
def build_bridge(self): def exc_handling(guard_op): # operations need to start with correct GUARD_EXCEPTION if guard_op._exc_box is None: op = ResOperation(rop.GUARD_NO_EXCEPTION, []) else: op = ResOperation(rop.GUARD_EXCEPTION, [guard_op._exc_box]) op.setdescr(self.builder.getfaildescr()) op.setfailargs([]) return op if self.dont_generate_more: return False r = self.r guard_op = self.guard_op fail_args = guard_op.getfailargs() fail_descr = guard_op.getdescr() op = self.should_fail_by if not op.getfailargs(): return False for _fail_box in fail_args: _fail_box.set_forwarded(None) # generate the branch: a sequence of operations that ends in a FINISH subloop = DummyLoop([]) self.subloops.append(subloop) # keep around for debugging if rop.is_guard_exception(guard_op.getopnum()): subloop.operations.append(exc_handling(guard_op)) bridge_builder = self.builder.fork(self.builder.cpu, subloop, op.getfailargs()[:]) self.generate_ops(bridge_builder, r, subloop, op.getfailargs()[:]) # note that 'self.guard_op' now points to the guard that will fail in # this new bridge, while 'guard_op' still points to the guard that # has just failed. if r.random() < 0.1 and self.guard_op is None: # Occasionally, instead of ending in a FINISH, we end in a jump # to another loop. We don't do it, however, if the new bridge's # execution will hit 'self.guard_op', but only if it executes # to the FINISH normally. (There is no point to the extra # complexity, as we might get the same effect by two calls # to build_bridge().) # First make up the other loop... # # New restriction: must have the same argument count and types # as the original loop subset = [] for box in self.loop.inputargs: srcbox = r.choice(fail_args) if srcbox.type != box.type: if box.type == INT: srcbox = ConstInt(r.random_integer()) elif box.type == FLOAT: srcbox = ConstFloat(r.random_float_storage()) else: raise AssertionError(box.type) subset.append(srcbox) # args = [] for x in subset: if x.type == INT: args.append(InputArgInt(getint(x))) elif x.type == FLOAT: args.append(InputArgFloat(getfloatstorage(x))) else: assert 0, x.type rl = RandomLoop(self.builder.cpu, self.builder.fork, r, args) # done self.should_fail_by = rl.should_fail_by self.expected = rl.expected assert len(rl.loop.inputargs) == len(args) # The new bridge's execution will end normally at its FINISH. # Just replace the FINISH with the JUMP to the new loop. jump_op = ResOperation(rop.JUMP, subset, descr=rl.loop._targettoken) subloop.operations[-1] = jump_op self.guard_op = rl.guard_op self.prebuilt_ptr_consts += rl.prebuilt_ptr_consts self.loop._jitcelltoken.record_jump_to(rl.loop._jitcelltoken) self.dont_generate_more = True if r.random() < .05: return False dump(subloop) self.builder.cpu.compile_bridge(fail_descr, fail_args, subloop.operations, self.loop._jitcelltoken) if self.output: bridge_builder.print_loop(self.output, fail_descr, fail_args) return True
def boxfloat(x): return InputArgFloat(longlong.getfloatstorage(x))