def test_pseudohighlevelcallable(): t = TranslationContext() t.buildannotator() rtyper = t.buildrtyper() rtyper.specialize() a = MixLevelHelperAnnotator(rtyper) class A: value = 5 def double(self): return self.value * 2 def fn1(a): a2 = A() a2.value = a.double() return a2 s_A, r_A = a.s_r_instanceof(A) fn1ptr = a.delayedfunction(fn1, [s_A], s_A) pseudo = PseudoHighLevelCallable(fn1ptr, [s_A], s_A) def fn2(n): a = A() a.value = n a2 = pseudo(a) return a2.value graph = a.getgraph(fn2, [annmodel.SomeInteger()], annmodel.SomeInteger()) a.finish() llinterp = LLInterpreter(rtyper) res = llinterp.eval_graph(graph, [21]) assert res == 42
def annotate_walker_functions(self, getfn): self.incr_stack_ptr = getfn(self.root_walker.incr_stack, [annmodel.SomeInteger()], SomeAddress(), inline=True) self.decr_stack_ptr = getfn(self.root_walker.decr_stack, [annmodel.SomeInteger()], SomeAddress(), inline=True)
class CTestFuncEntry(ExtFuncEntry): _about_ = c name = 'ccc' signature_args = [annmodel.SomeInteger()] * 2 signature_result = annmodel.SomeInteger() def lltypeimpl(y, x): return y + x lltypeimpl = staticmethod(lltypeimpl)
def test_cast_primitive(self): def llf(u): return cast_primitive(Signed, u) s = self.annotate(llf, [annmodel.SomeInteger(unsigned=True)]) assert s.knowntype == int def llf(s): return cast_primitive(Unsigned, s) s = self.annotate(llf, [annmodel.SomeInteger()]) assert s.unsigned == True
def test_return_any(): @signature(types.int(), returns=types.any()) def f(x): return x sig = getsig(f) assert sig == [model.SomeInteger(), model.SomeInteger()] @signature(types.str(), returns=types.any()) def cannot_add_string(x): return f(3) + x exc = py.test.raises(model.AnnotatorError, annotate_at, cannot_add_string).value assert 'Blocked block' in str(exc) assert 'cannot_add_string' in str(exc)
def make_driverhook_graphs(self): # annhelper = MixLevelHelperAnnotator(self.translator.rtyper) for jd in self.jitdrivers_sd: jd._get_printable_location_ptr = self._make_hook_graph( jd, annhelper, jd.jitdriver.get_printable_location, annmodel.SomeString()) jd._get_unique_id_ptr = self._make_hook_graph( jd, annhelper, jd.jitdriver.get_unique_id, annmodel.SomeInteger()) jd._confirm_enter_jit_ptr = self._make_hook_graph( jd, annhelper, jd.jitdriver.confirm_enter_jit, annmodel.s_Bool, onlygreens=False) jd._can_never_inline_ptr = self._make_hook_graph( jd, annhelper, jd.jitdriver.can_never_inline, annmodel.s_Bool) jd._should_unroll_one_iteration_ptr = self._make_hook_graph( jd, annhelper, jd.jitdriver.should_unroll_one_iteration, annmodel.s_Bool) # items = [] types = () pos = () if jd.jitdriver.get_location: assert hasattr(jd.jitdriver.get_location, '_loc_types'), """ You must decorate your get_location function: from rpython.rlib.rjitlog import rjitlog as jl @jl.returns(jl.MP_FILENAME, jl.MP_XXX, ...) def get_loc(your, green, keys): name = "x.txt" # extract it from your green keys return (name, ...) """ types = jd.jitdriver.get_location._loc_types del jd.jitdriver.get_location._loc_types # for _, type in types: if type == 's': items.append(annmodel.SomeString()) elif type == 'i': items.append(annmodel.SomeInteger()) else: raise NotImplementedError s_Tuple = annmodel.SomeTuple(items) jd._get_location_ptr = self._make_hook_graph( jd, annhelper, jd.jitdriver.get_location, s_Tuple) jd._get_loc_types = types annhelper.finish()
def test_stress(self): from rpython.annotator.dictdef import DictKey, DictValue from rpython.annotator import model as annmodel from rpython.rtyper import rint from rpython.rtyper.test.test_rdict import not_really_random rodct = rordereddict dictrepr = rodct.OrderedDictRepr( None, rint.signed_repr, rint.signed_repr, DictKey(None, annmodel.SomeInteger()), DictValue(None, annmodel.SomeInteger())) dictrepr.setup() l_dict = rodct.ll_newdict(dictrepr.DICT) referencetable = [None] * 400 referencelength = 0 value = 0 def complete_check(): for n, refvalue in zip(range(len(referencetable)), referencetable): try: gotvalue = rodct.ll_dict_getitem(l_dict, n) except KeyError: assert refvalue is None else: assert gotvalue == refvalue for x in not_really_random(): n = int(x * 100.0) # 0 <= x < 400 op = repr(x)[-1] if op <= '2' and referencetable[n] is not None: rodct.ll_dict_delitem(l_dict, n) referencetable[n] = None referencelength -= 1 elif op <= '6': rodct.ll_dict_setitem(l_dict, n, value) if referencetable[n] is None: referencelength += 1 referencetable[n] = value value += 1 else: try: gotvalue = rodct.ll_dict_getitem(l_dict, n) except KeyError: assert referencetable[n] is None else: assert gotvalue == referencetable[n] if 1.38 <= x <= 1.39: complete_check() print 'current dict length:', referencelength assert l_dict.num_live_items == referencelength complete_check()
def test_funny_links(): from rpython.flowspace.model import Block, FunctionGraph, \ Variable, Constant, Link from rpython.flowspace.operation import op for i in range(2): v_i = Variable("i") block = Block([v_i]) g = FunctionGraph("is_one", block) op1 = op.eq(v_i, Constant(1)) block.operations.append(op1) block.exitswitch = op1.result tlink = Link([Constant(1)], g.returnblock, True) flink = Link([Constant(0)], g.returnblock, False) links = [tlink, flink] if i: links.reverse() block.closeblock(*links) t = TranslationContext() a = t.buildannotator() a.build_graph_types(g, [annmodel.SomeInteger()]) rtyper = t.buildrtyper() rtyper.specialize() interp = LLInterpreter(rtyper) assert interp.eval_graph(g, [1]) == 1 assert interp.eval_graph(g, [0]) == 0
def test_any_as_argument(): @signature(types.any(), types.int(), returns=types.float()) def f(x, y): return x + y @signature(types.int(), returns=types.float()) def g(x): return f(x, x) sig = getsig(g) assert sig == [model.SomeInteger(), model.SomeFloat()] @signature(types.float(), returns=types.float()) def g(x): return f(x, 4) sig = getsig(g) assert sig == [model.SomeFloat(), model.SomeFloat()] @signature(types.str(), returns=types.int()) def cannot_add_string(x): return f(x, 2) exc = py.test.raises(model.AnnotatorError, annotate_at, cannot_add_string).value assert 'Blocked block' in str(exc)
class Entry(ExtRegistryEntry): _about_ = dummy_func s_result_annotation = annmodel.SomeInteger() def specialize_call(self, hop): hop.exception_cannot_occur() return hop.inputconst(lltype.Signed, 42)
def arguments_ALLOCATING(self): from rpython.annotator import model as annmodel from rpython.rtyper import llannotation return [ annmodel.SomeInteger(knowntype=r_longlong), llannotation.lltype_to_annotation(llmemory.GCREF) ]
def __init__(self, rtyper): super(RuleRepr, self).__init__() self.ll_rule_cache = {} self.match_init_repr = rtyper.getrepr( rtyper.annotator.bookkeeper.immutablevalue(Match.__init__) ) self.match_context_init_repr = rtyper.getrepr( rtyper.annotator.bookkeeper.immutablevalue( rsre_core.StrMatchContext.__init__ ) ) self.match_context_repr = rtyper.getrepr( rtyper.annotator.bookkeeper.immutablevalue( rsre_core.match_context ) ) list_repr = FixedSizeListRepr( rtyper, rtyper.getrepr(model.SomeInteger(nonneg=True)) ) list_repr._setup_repr() self.lowleveltype = lltype.Ptr(lltype.GcStruct( "RULE", ("name", lltype.Ptr(STR)), ("code", list_repr.lowleveltype), ("flags", lltype.Signed), ))
def test_secondary_backendopt(self): # checks an issue with a newly added graph that calls an # already-exception-transformed graph. This can occur e.g. # from a late-seen destructor added by the GC transformer # which ends up calling existing code. def common(n): if n > 5: raise ValueError def main(n): common(n) def later(n): try: common(n) return 0 except ValueError: return 1 t = TranslationContext() t.buildannotator().build_types(main, [int]) t.buildrtyper().specialize() exctransformer = t.getexceptiontransformer() exctransformer.create_exception_handling(graphof(t, common)) from rpython.annotator import model as annmodel from rpython.rtyper.annlowlevel import MixLevelHelperAnnotator annhelper = MixLevelHelperAnnotator(t.rtyper) later_graph = annhelper.getgraph(later, [annmodel.SomeInteger()], annmodel.SomeInteger()) annhelper.finish() annhelper.backend_optimize() # ^^^ as the inliner can't handle exception-transformed graphs, # this should *not* inline common() into later(). if option.view: later_graph.show() common_graph = graphof(t, common) found = False for block in later_graph.iterblocks(): for op in block.operations: if (op.opname == 'direct_call' and op.args[0].value._obj.graph is common_graph): found = True assert found, "cannot find the call (buggily inlined?)" from rpython.rtyper.llinterp import LLInterpreter llinterp = LLInterpreter(t.rtyper) res = llinterp.eval_graph(later_graph, [10]) assert res == 1
def compute_result_annotation(self, s_l): from rpython.annotator import model as annmodel if annmodel.s_None.contains(s_l): pass # first argument is only None so far, but we # expect a generalization later elif not isinstance(s_l, annmodel.SomeList): raise annmodel.AnnotatorError("First argument must be a list") return annmodel.SomeInteger(nonneg=True)
def test_dict(): @signature(returns=types.dict(types.str(), types.int())) def f(): return {'a': 1, 'b': 2} rettype = getsig(f)[0] assert isinstance(rettype, model.SomeDict) assert rettype.dictdef.dictkey.s_value == model.SomeString() assert rettype.dictdef.dictvalue.s_value == model.SomeInteger()
def method_matches(self, s_s, s_pos): assert model.SomeString().contains(s_s) assert model.SomeInteger(nonneg=True).contains(s_pos) bk = getbookkeeper() init_pbc = bk.immutablevalue(Match.__init__) bk.emulate_pbc_call((self, "match_init"), init_pbc, [ model.SomeInstance(bk.getuniqueclassdef(Match)), model.SomeInteger(nonneg=True), model.SomeInteger(nonneg=True) ]) init_pbc = bk.immutablevalue(rsre_core.StrMatchContext.__init__) bk.emulate_pbc_call((self, "str_match_context_init"), init_pbc, [ model.SomeInstance( bk.getuniqueclassdef(rsre_core.StrMatchContext)), bk.newlist(model.SomeInteger(nonneg=True)), model.SomeString(), model.SomeInteger(nonneg=True), model.SomeInteger(nonneg=True), model.SomeInteger(nonneg=True), ]) match_context_pbc = bk.immutablevalue(rsre_core.match_context) bk.emulate_pbc_call((self, "match_context"), match_context_pbc, [ model.SomeInstance( bk.getuniqueclassdef(rsre_core.StrMatchContext)), ]) return model.SomeInstance(getbookkeeper().getuniqueclassdef(Match), can_be_None=True)
def build_increase_root_stack_depth_ptr(self, getfn): shadow_stack_pool = self.shadow_stack_pool def gc_increase_root_stack_depth(new_size): shadow_stack_pool.increase_root_stack_depth(new_size) self.gc_increase_root_stack_depth_ptr = getfn( gc_increase_root_stack_depth, [annmodel.SomeInteger()], annmodel.s_None)
def test_longlong(): # get_loader for (r_longolong, nonneg=True) used to return # load_int_nonneg on 32-bit, instead of load_longlong. for nonneg in [True, False]: s_longlong = annmodel.SomeInteger(knowntype=r_longlong, nonneg=nonneg) load = get_loader(s_longlong) loader = Loader("I\x01\x23\x45\x67\x89\xab\xcd\x0e") res = load(loader) assert res == 0x0ecdab8967452301
def compute_result_annotation(self, s_driver, s_name, s_value): from rpython.annotator import model as annmodel assert s_name.is_constant() if s_name.const == 'enable_opts': assert annmodel.SomeString(can_be_None=True).contains(s_value) else: assert (s_value == annmodel.s_None or annmodel.SomeInteger().contains(s_value)) return annmodel.s_None
def test_basic(): @signature(types.int(), types.str(), returns=types.char()) def f(a, b): return b[a] assert getsig(f) == [ model.SomeInteger(), model.SomeString(), model.SomeChar() ]
def test_array(): @signature(returns=types.array(types.int())) def f(): return [1] rettype = getsig(f)[0] assert isinstance(rettype, model.SomeList) item = rettype.listdef.listitem assert item.s_value == model.SomeInteger() assert item.resized == False def try_append(): l = f() l.append(2) check_annotator_fails(try_append)
def getentrypointptr(self): # XXX check that the entrypoint has the correct # signature: list-of-strings -> int if not self.make_entrypoint_wrapper: bk = self.translator.annotator.bookkeeper return getfunctionptr(bk.getdesc(self.entrypoint).getuniquegraph()) if self._entrypoint_wrapper is not None: return self._entrypoint_wrapper # from rpython.annotator import model as annmodel from rpython.rtyper.lltypesystem import rffi from rpython.rtyper.annlowlevel import MixLevelHelperAnnotator from rpython.rtyper.llannotation import lltype_to_annotation entrypoint = self.entrypoint # def entrypoint_wrapper(argc, argv): """This is a wrapper that takes "Signed argc" and "char **argv" like the C main function, and puts them inside an RPython list of strings before invoking the real entrypoint() function. """ list = [""] * argc i = 0 while i < argc: list[i] = rffi.charp2str(argv[i]) i += 1 return entrypoint(list) # mix = MixLevelHelperAnnotator(self.translator.rtyper) args_s = [annmodel.SomeInteger(), lltype_to_annotation(rffi.CCHARPP)] s_result = annmodel.SomeInteger() graph = mix.getgraph(entrypoint_wrapper, args_s, s_result) mix.finish() res = getfunctionptr(graph) self._entrypoint_wrapper = res return res
def test_oopspec(self): lst1 = [123, 456] # non-mutated list def f(i): lst2 = [i] lst2.append(42) # mutated list return lst1[i] + lst2[i] from rpython.annotator import model as annmodel _, _, graph = self.gengraph(f, [annmodel.SomeInteger(nonneg=True)]) block = graph.startblock lst1_getitem_op = block.operations[-3] # XXX graph fishing lst2_getitem_op = block.operations[-2] func1 = lst1_getitem_op.args[2].value func2 = lst2_getitem_op.args[2].value assert func1.oopspec == 'list.getitem_foldable(l, index)' assert not hasattr(func2, 'oopspec')
def test_list(): @signature(types.list(types.int()), returns=types.int()) def f(a): return len(a) argtype = getsig(f)[0] assert isinstance(argtype, model.SomeList) item = argtype.listdef.listitem assert item.s_value == model.SomeInteger() assert item.resized == True @check_annotator_fails def ok_for_body(): f(['a']) @check_annotator_fails def bad_for_body(): f('a') @signature(returns=types.list(types.char())) def ff(): return ['a'] @check_annotator_fails def mutate_broader(): ff()[0] = 'abc' @check_annotator_fails def mutate_unrelated(): ff()[0] = 1 @check_annotator_fails @signature(types.list(types.char()), returns=types.int()) def mutate_in_body(l): l[0] = 'abc' return len(l) def can_append(): l = ff() l.append('b') getsig(can_append)
def make_driverhook_graphs(self): s_Str = annmodel.SomeString() # annhelper = MixLevelHelperAnnotator(self.translator.rtyper) for jd in self.jitdrivers_sd: jd._get_printable_location_ptr = self._make_hook_graph( jd, annhelper, jd.jitdriver.get_printable_location, s_Str) jd._get_unique_id_ptr = self._make_hook_graph( jd, annhelper, jd.jitdriver.get_unique_id, annmodel.SomeInteger()) jd._confirm_enter_jit_ptr = self._make_hook_graph( jd, annhelper, jd.jitdriver.confirm_enter_jit, annmodel.s_Bool, onlygreens=False) jd._can_never_inline_ptr = self._make_hook_graph( jd, annhelper, jd.jitdriver.can_never_inline, annmodel.s_Bool) jd._should_unroll_one_iteration_ptr = self._make_hook_graph( jd, annhelper, jd.jitdriver.should_unroll_one_iteration, annmodel.s_Bool) annhelper.finish()
def test_mix_after_recursion(self): def prefn(n): if n: return 2 * prefn(n - 1) else: return 1 t = TranslationContext() a = t.buildannotator() a.build_types(prefn, [int]) typer = t.buildrtyper() typer.specialize() #t.view() def f(): return 1 from rpython.rtyper import annlowlevel annhelper = annlowlevel.MixLevelHelperAnnotator(typer) graph = annhelper.getgraph(f, [], annmodel.SomeInteger()) annhelper.finish()
def compute_result_annotation(self): from rpython.annotator import model as annmodel return annmodel.SomeInteger()
def annotation(self): from rpython.annotator import model return model.SomeInteger()
return lltype.nullptr(llmemory.GCREF.TO) @register_helper(SomePtr(llmemory.GCREF)) def resop_new(no, llargs, llres): from rpython.jit.metainterp.history import ResOperation args = [_cast_to_box(llargs[i]) for i in range(len(llargs))] if llres: res = _cast_to_box(llres) else: res = None return _cast_to_gcref(ResOperation(no, args, res)) @register_helper(annmodel.SomeInteger()) def resop_getopnum(llop): return _cast_to_resop(llop).getopnum() @register_helper(annmodel.SomeString(can_be_None=True)) def resop_getopname(llop): return llstr(_cast_to_resop(llop).getopname()) @register_helper(SomePtr(llmemory.GCREF)) def resop_getarg(llop, no): return _cast_to_gcref(_cast_to_resop(llop).getarg(no)) @register_helper(annmodel.s_None)
def meta_interp(self, function, args, repeat=1, inline=False, trace_limit=sys.maxint, backendopt=None, listcomp=False, **kwds): # XXX ignored from rpython.jit.metainterp.warmspot import WarmRunnerDesc from rpython.annotator.listdef import s_list_of_strings from rpython.annotator import model as annmodel for arg in args: assert is_valid_int(arg) self.pre_translation_hook() t = self._get_TranslationContext() if listcomp: t.config.translation.list_comprehension_operations = True arglist = ", ".join( ['int(argv[%d])' % (i + 1) for i in range(len(args))]) if len(args) == 1: arglist += ',' arglist = '(%s)' % arglist if repeat != 1: src = py.code.Source(""" def entry_point(argv): args = %s res = function(*args) for k in range(%d - 1): res = function(*args) print res return 0 """ % (arglist, repeat)) else: src = py.code.Source(""" def entry_point(argv): args = %s res = function(*args) print res return 0 """ % (arglist, )) exec src.compile() in locals() t.buildannotator().build_types(function, [int] * len(args), main_entry_point=True) t.buildrtyper().specialize() warmrunnerdesc = WarmRunnerDesc(t, translate_support_code=True, CPUClass=self.CPUClass, **kwds) for jd in warmrunnerdesc.jitdrivers_sd: jd.warmstate.set_param_threshold(3) # for tests jd.warmstate.set_param_trace_eagerness(2) # for tests jd.warmstate.set_param_trace_limit(trace_limit) jd.warmstate.set_param_inlining(inline) jd.warmstate.set_param_enable_opts(ALL_OPTS_NAMES) mixlevelann = warmrunnerdesc.annhelper entry_point_graph = mixlevelann.getgraph(entry_point, [s_list_of_strings], annmodel.SomeInteger()) warmrunnerdesc.finish() self.post_translation_hook() return self._compile_and_run(t, entry_point, entry_point_graph, args)