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) nb_red_args = jitdriver_sd.num_red_args assert len(redargtypes) == nb_red_args inputargs = [] for kind in redargtypes: if kind == history.INT: box = BoxInt() elif kind == history.REF: box = BoxPtr() elif kind == history.FLOAT: box = BoxFloat() else: raise AssertionError inputargs.append(box) k = jitdriver_sd.portal_runner_adr funcbox = history.ConstInt(heaptracker.adr2int(k)) callargs = [funcbox] + greenboxes + inputargs # result_type = jitdriver_sd.result_type if result_type == history.INT: result = BoxInt() elif result_type == history.REF: result = BoxPtr() elif result_type == history.FLOAT: result = BoxFloat() elif result_type == history.VOID: result = None else: assert 0, "bad result_type" if result is not None: finishargs = [result] else: finishargs = [] # jd = jitdriver_sd faildescr = jitdriver_sd.propagate_exc_descr operations = [ ResOperation(rop.CALL, callargs, result, descr=jd.portal_calldescr), ResOperation(rop.GUARD_NO_EXCEPTION, [], None, descr=faildescr), ResOperation(rop.FINISH, finishargs, None, 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_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(BoxInt()) assert fm.get_frame_depth() == 3 # f0 = BoxFloat() locf0 = fm.loc(f0) # can't be odd assert fm.get_loc_index(locf0) == 4 assert fm.get_frame_depth() == 6 # f1 = BoxFloat() 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 = BoxInt() 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 = BoxPtr() ploc = fm.loc(p0) assert fm.get_loc_index(ploc) == 0 assert fm.get_frame_depth() == 8 assert ploc != loc1 p1 = BoxPtr() p1loc = fm.loc(p1) assert fm.get_loc_index(p1loc) == 3 assert fm.get_frame_depth() == 8 fm.mark_as_free(p0) p2 = BoxPtr() p2loc = fm.loc(p2) assert p2loc == ploc assert len(fm.freelist) == 0 fm.mark_as_free(b2) f3 = BoxFloat() 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 new_box_item(self, arraydescr): if arraydescr.is_array_of_pointers(): return self.new_ptr_box() elif arraydescr.is_array_of_floats(): return BoxFloat() else: return BoxInt()
def new_box(self, fieldofs): if fieldofs.is_pointer_field(): return self.new_ptr_box() elif fieldofs.is_float_field(): return BoxFloat() else: return BoxInt()
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 BoxFloat while others # have a lot of them k = r.random() # but make sure there is at least one BoxInt 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(BoxFloat(r.random_float_storage())) else: startvars.append(BoxInt(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 do_getarrayitem_raw(cpu, _, arraybox, indexbox, arraydescr): array = arraybox.getint() index = indexbox.getint() assert not arraydescr.is_array_of_pointers() if arraydescr.is_array_of_floats(): return BoxFloat(cpu.bh_getarrayitem_raw_f(array, index, arraydescr)) else: return BoxInt(cpu.bh_getarrayitem_raw_i(array, index, arraydescr))
def do_getfield_gc(cpu, _, structbox, fielddescr): struct = structbox.getref_base() if fielddescr.is_pointer_field(): return BoxPtr(cpu.bh_getfield_gc_r(struct, fielddescr)) elif fielddescr.is_float_field(): return BoxFloat(cpu.bh_getfield_gc_f(struct, fielddescr)) else: return BoxInt(cpu.bh_getfield_gc_i(struct, fielddescr))
def do_getarrayitem_gc(cpu, _, arraybox, indexbox, arraydescr): array = arraybox.getref_base() index = indexbox.getint() if arraydescr.is_array_of_pointers(): return BoxPtr(cpu.bh_getarrayitem_gc_r(array, index, arraydescr)) elif arraydescr.is_array_of_floats(): return BoxFloat(cpu.bh_getarrayitem_gc_f(array, index, arraydescr)) else: return BoxInt(cpu.bh_getarrayitem_gc_i(array, index, arraydescr))
def do_raw_load(cpu, _, addrbox, offsetbox, arraydescr): addr = addrbox.getint() offset = offsetbox.getint() if arraydescr.is_array_of_pointers(): raise AssertionError("cannot store GC pointers in raw store") elif arraydescr.is_array_of_floats(): return BoxFloat(cpu.bh_raw_load_f(addr, offset, arraydescr)) else: return BoxInt(cpu.bh_raw_load_i(addr, offset, arraydescr))
def do_getfield_raw(cpu, _, structbox, fielddescr): check_descr(fielddescr) struct = structbox.getint() if fielddescr.is_pointer_field(): return BoxPtr(cpu.bh_getfield_raw_r(struct, fielddescr)) elif fielddescr.is_float_field(): return BoxFloat(cpu.bh_getfield_raw_f(struct, fielddescr)) else: return BoxInt(cpu.bh_getfield_raw_i(struct, fielddescr))
def do_getinteriorfield_gc(cpu, _, arraybox, indexbox, descr): array = arraybox.getref_base() index = indexbox.getint() if descr.is_pointer_field(): return BoxPtr(cpu.bh_getinteriorfield_gc_r(array, index, descr)) elif descr.is_float_field(): return BoxFloat(cpu.bh_getinteriorfield_gc_f(array, index, descr)) else: return BoxInt(cpu.bh_getinteriorfield_gc_i(array, index, descr))
def _optimize_CALL_ARRAYCOPY(self, op): length = self.get_constant_box(op.getarg(5)) if length and length.getint() == 0: return True # 0-length arraycopy source_value = self.getvalue(op.getarg(1)) dest_value = self.getvalue(op.getarg(2)) source_start_box = self.get_constant_box(op.getarg(3)) dest_start_box = self.get_constant_box(op.getarg(4)) extrainfo = op.getdescr().get_extra_info() if (source_start_box and dest_start_box and length and (dest_value.is_virtual() or length.getint() <= 8) and (source_value.is_virtual() or length.getint() <= 8) and len(extrainfo.write_descrs_arrays) == 1): # <-sanity check from rpython.jit.metainterp.optimizeopt.virtualize import VArrayValue source_start = source_start_box.getint() dest_start = dest_start_box.getint() # XXX fish fish fish arraydescr = extrainfo.write_descrs_arrays[0] if arraydescr.is_array_of_structs(): return False # not supported right now for index in range(length.getint()): if source_value.is_virtual(): assert isinstance(source_value, VArrayValue) val = source_value.getitem(index + source_start) else: if arraydescr.is_array_of_pointers(): resbox = BoxPtr() elif arraydescr.is_array_of_floats(): resbox = BoxFloat() else: resbox = BoxInt() newop = ResOperation( rop.GETARRAYITEM_GC, [op.getarg(1), ConstInt(index + source_start)], resbox, descr=arraydescr) self.optimizer.send_extra_operation(newop) val = self.getvalue(resbox) if val is None: continue if dest_value.is_virtual(): dest_value.setitem(index + dest_start, val) else: newop = ResOperation(rop.SETARRAYITEM_GC, [ op.getarg(2), ConstInt(index + dest_start), val.get_key_box() ], None, descr=arraydescr) self.emit_operation(newop) return True return False
def test_wrap(): def _is(box1, box2): return (box1.__class__ == box2.__class__ and box1.value == box2.value) p = lltype.malloc(lltype.GcStruct('S')) po = lltype.cast_opaque_ptr(llmemory.GCREF, p) assert _is(wrap(None, 42), BoxInt(42)) assert _is(wrap(None, 42.5), boxfloat(42.5)) assert _is(wrap(None, p), BoxPtr(po)) assert _is(wrap(None, 42, in_const_box=True), ConstInt(42)) assert _is(wrap(None, 42.5, in_const_box=True), constfloat(42.5)) assert _is(wrap(None, p, in_const_box=True), ConstPtr(po)) if longlong.supports_longlong: import sys from rpython.rlib.rarithmetic import r_longlong, r_ulonglong value = r_longlong(-sys.maxint*17) assert _is(wrap(None, value), BoxFloat(value)) assert _is(wrap(None, value, in_const_box=True), ConstFloat(value)) value_unsigned = r_ulonglong(-sys.maxint*17) assert _is(wrap(None, value_unsigned), BoxFloat(value)) sfval = r_singlefloat(42.5) ival = longlong.singlefloat2int(sfval) assert _is(wrap(None, sfval), BoxInt(ival)) assert _is(wrap(None, sfval, in_const_box=True), ConstInt(ival))
def test_different_frame_width(self): class XRegisterManager(RegisterManager): pass fm = TFrameManager() b0 = BoxInt() longevity = {b0: (0, 1)} asm = MockAsm() rm = RegisterManager(longevity, frame_manager=fm, assembler=asm) f0 = BoxFloat() longevity = {f0: (0, 1)} xrm = XRegisterManager(longevity, frame_manager=fm, assembler=asm) xrm.loc(f0) rm.loc(b0) assert fm.get_frame_depth() == 3
def test_count_reg_args(): assert count_reg_args([BoxPtr()]) == 1 assert count_reg_args([BoxPtr()] * 2) == 2 assert count_reg_args([BoxPtr()] * 3) == 3 assert count_reg_args([BoxPtr()] * 4) == 4 assert count_reg_args([BoxPtr()] * 5) == 4 assert count_reg_args([BoxFloat()] * 1) == 1 assert count_reg_args([BoxFloat()] * 2) == 2 assert count_reg_args([BoxFloat()] * 3) == 2 assert count_reg_args([BoxInt(), BoxInt(), BoxFloat()]) == 3 assert count_reg_args([BoxInt(), BoxFloat(), BoxInt()]) == 2 assert count_reg_args([BoxInt(), BoxFloat(), BoxInt()]) == 2 assert count_reg_args([BoxInt(), BoxInt(), BoxInt(), BoxFloat()]) == 3
def do(cpu, _, *argboxes): newargs = () for argtype in argtypes: if argtype == 'cpu': value = cpu elif argtype == 'd': value = argboxes[-1] assert isinstance(value, AbstractDescr) argboxes = argboxes[:-1] else: argbox = argboxes[0] argboxes = argboxes[1:] if argtype == 'i': value = argbox.getint() elif argtype == 'r': value = argbox.getref_base() elif argtype == 'f': value = argbox.getfloatstorage() newargs = newargs + (value, ) assert not argboxes # result = func(*newargs) # if resulttype == 'i': return BoxInt(result) if resulttype == 'r': return BoxPtr(result) if resulttype == 'f': return BoxFloat(result) return None
def boxfloat(x): return BoxFloat(longlong.getfloatstorage(x))
result = 0 return BoxInt(result) if rettype == REF: try: result = cpu.bh_call_r(func, args_i, args_r, args_f, descr) except Exception, e: metainterp.execute_raised(e) result = NULL return BoxPtr(result) if rettype == FLOAT or rettype == 'L': # *L*ong long try: result = cpu.bh_call_f(func, args_i, args_r, args_f, descr) except Exception, e: metainterp.execute_raised(e) result = longlong.ZEROF return BoxFloat(result) if rettype == VOID: try: cpu.bh_call_v(func, args_i, args_r, args_f, descr) except Exception, e: metainterp.execute_raised(e) return None raise AssertionError("bad rettype") do_call_loopinvariant = do_call do_call_may_force = do_call def do_cond_call(cpu, metainterp, argboxes, descr): condbox = argboxes[0]