def test_simple_lambda(): f = lambda x: x * 2 t = TranslationContext() t.buildannotator().build_types(f, [int]) t.buildrtyper().specialize() t.config.translation.countmallocs = True builder = genc.CExtModuleBuilder(t, f, config=t.config) builder.generate_source() builder.compile() f1 = builder.get_entry_point() assert f1(5) == 10
def getgraph(f, argtypes): from pypy.translator.translator import TranslationContext, graphof from pypy.translator.backendopt.all import backend_optimizations t = TranslationContext() a = t.buildannotator() typer = t.buildrtyper() a.build_types(f, argtypes) typer.specialize() backend_optimizations(t) graph = graphof(t, f) if option.view: graph.show() return graph
def get_graph(fn, signature, all_opts=True): t = TranslationContext() t.buildannotator().build_types(fn, signature) t.buildrtyper().specialize() if all_opts: backend_optimizations(t, inline_threshold=INLINE_THRESHOLD_FOR_TEST, constfold=False, raisingop2direct_call=False) graph = graphof(t, fn) if conftest.option.view: t.view() return graph, t
def getcompiled(self, func): def main(argv): try: res = func() except MemoryError: print 'Result: MemoryError' else: if isinstance(res, int): print 'Result:', res else: print 'Result: "%s"' % (res,) return 0 from pypy.config.pypyoption import get_pypy_config config = get_pypy_config(translating=True) config.translation.gc = self.gcpolicy config.translation.gcrootfinder = "asmgcc" t = TranslationContext(config=config) self.t = t a = t.buildannotator() a.build_types(main, [s_list_of_strings]) t.buildrtyper().specialize() t.checkgraphs() cbuilder = CStandaloneBuilder(t, main, config=config) c_source_filename = cbuilder.generate_source( defines = cbuilder.DEBUG_DEFINES) self.patch_makefile(cbuilder.targetdir) if conftest.option.view: t.view() exe_name = cbuilder.compile() def run(): lines = [] print >> sys.stderr, 'RUN: starting', exe_name g = os.popen("'%s'" % (exe_name,), 'r') for line in g: print >> sys.stderr, 'RUN:', line.rstrip() lines.append(line) g.close() if not lines: py.test.fail("no output from subprocess") if not lines[-1].startswith('Result:'): py.test.fail("unexpected output from subprocess") result = lines[-1][len('Result:'):].strip() if result == 'MemoryError': raise MemoryError("subprocess got an RPython MemoryError") if result.startswith('"') and result.endswith('"'): return result[1:-1] else: return int(result) return run
def test_identity_hash_is_fast(self): class A(object): pass def f(): return {A(): 1} t = TranslationContext() s = t.buildannotator().build_types(f, []) rtyper = t.buildrtyper() rtyper.specialize() r_dict = rtyper.getrepr(s) assert not hasattr(r_dict.lowleveltype.TO.entries.TO.OF, "f_hash")
def test_simple(): t = TranslationContext() a = t.buildannotator() a.build_types(g, [int]) a.simplify() t.buildrtyper().specialize() backend_optimizations(t) t.checkgraphs() n = insert_ll_stackcheck(t) t.checkgraphs() assert n == 1 if conftest.option.view: t.view() check(graphof(t, f), 'f')
def test_annotate_array_access_variable(self): def access_with_variable(): my_array = numpy.array(range(10)) my_array[2] = 2 sum = 0 for idx in range(10): sum += my_array[idx] return sum t = TranslationContext() a = t.buildannotator() s = a.build_types(access_with_variable, []) assert s.knowntype == rffi.r_int
def specialize(self, func, argtypes): from pypy.rpython.llinterp import LLInterpreter t = TranslationContext(list_comprehension_operations=True) t.buildannotator().build_types(func, argtypes) if conftest.option.view: t.view() t.buildrtyper(self.typesystem).specialize() if self.typesystem == 'lltype': backend_optimizations(t) if conftest.option.view: t.view() graph = graphof(t, func) interp = LLInterpreter(t.rtyper) return interp, graph
def test_find_loop_blocks(): def f(k): result = 0 for i in range(k): result += 1 for j in range(k): result += 1 return result t = TranslationContext() t.buildannotator().build_types(f, [int]) t.buildrtyper().specialize() graph = graphof(t, f) loop_blocks = find_loop_blocks(graph) assert len(loop_blocks) == 4
def test_dont_write_source_files(): def f(x): return x * 2 t = TranslationContext() t.buildannotator().build_types(f, [int]) t.buildrtyper().specialize() t.config.translation.countmallocs = True t.config.translation.dont_write_c_files = True builder = genc.CExtModuleBuilder(t, f, config=t.config) builder.generate_source() assert isinstance(builder.targetdir, NullPyPathLocal) assert builder.targetdir.listdir() == []
def test_del_inheritance(self): class State: pass s = State() s.a_dels = 0 s.b_dels = 0 class A(object): def __del__(self): s.a_dels += 1 class B(A): def __del__(self): s.b_dels += 1 class C(A): pass def f(): A() B() C() A() B() C() return s.a_dels * 10 + s.b_dels res = f() assert res == 42 t = TranslationContext() t.buildannotator().build_types(f, []) t.buildrtyper().specialize() graph = graphof(t, f) TYPEA = graph.startblock.operations[0].args[0].value RTTIA = getRuntimeTypeInfo(TYPEA) TYPEB = graph.startblock.operations[3].args[0].value RTTIB = getRuntimeTypeInfo(TYPEB) TYPEC = graph.startblock.operations[6].args[0].value RTTIC = getRuntimeTypeInfo(TYPEC) queryptra = RTTIA._obj.query_funcptr # should not raise queryptrb = RTTIB._obj.query_funcptr # should not raise queryptrc = RTTIC._obj.query_funcptr # should not raise destrptra = RTTIA._obj.destructor_funcptr destrptrb = RTTIB._obj.destructor_funcptr destrptrc = RTTIC._obj.destructor_funcptr assert destrptra == destrptrc assert typeOf(destrptra).TO.ARGS[0] != typeOf(destrptrb).TO.ARGS[0] assert destrptra is not None assert destrptrb is not None
def compile(self, entry_point, debug=True): t = TranslationContext(self.config) t.buildannotator().build_types(entry_point, [s_list_of_strings]) t.buildrtyper().specialize() cbuilder = CStandaloneBuilder(t, entry_point, t.config) if debug: cbuilder.generate_source(defines=cbuilder.DEBUG_DEFINES) else: cbuilder.generate_source() cbuilder.compile() if option.view: t.view() return t, cbuilder
def test_is_exception_instance(): def f(): return NameError() t = TranslationContext() t.buildannotator().build_types(f, []) if conftest.option.view: t.view() rtyper = t.buildrtyper(type_system="ootype") rtyper.specialize() graph = graphof(t, f) INST = graph.getreturnvar().concretetype assert rtyper.exceptiondata.is_exception_instance(INST)
def test_stackless(): t = TranslationContext() a = t.buildannotator() a.build_types(g, [int]) a.simplify() t.buildrtyper().specialize() backend_optimizations(t) t.checkgraphs() n = insert_ll_stackcheck(t) t.checkgraphs() assert n == 1 t.config.translation.stackless = True stacklesstransf = StacklessTransformer(t, g) f_graph = graphof(t, f) stacklesstransf.transform_graph(f_graph) if conftest.option.view: f_graph.show() exctransf = t.getexceptiontransformer() exctransf.create_exception_handling(f_graph) if conftest.option.view: f_graph.show() check(f_graph, 'f', 'fetch_retval_void') class GCTransform(framework.FrameworkGCTransformer): from pypy.rpython.memory.gc.generation import GenerationGC as \ GCClass GC_PARAMS = {} gctransf = GCTransform(t) gctransf.transform_graph(f_graph) if conftest.option.view: f_graph.show() relevant = check(f_graph, 'f', 'fetch_retval_void') for p in relevant: in_between = False reload = 0 for spaceop in p: if spaceop.opname == 'direct_call': target = direct_target(spaceop) if target == 'f': in_between = False elif target == 'stack_check___': in_between = True if in_between and spaceop.opname == 'gc_reload_possibly_moved': reload += 1 assert reload == 1
def analyze(self, func, sig, func_to_analyze=None, backendopt=False): if func_to_analyze is None: func_to_analyze = func t = TranslationContext() t.buildannotator().build_types(func, sig) t.buildrtyper(type_system=self.type_system).specialize() if backendopt: backend_optimizations(t) if option.view: t.view() a = FinalizerAnalyzer(t) fgraph = graphof(t, func_to_analyze) result = a.analyze_light_finalizer(fgraph) return result
def test_caching_dynamic_deallocator(): S = lltype.GcStruct("S", ('x', lltype.Signed)) S1 = lltype.GcStruct("S1", ('s', S), ('y', lltype.Signed)) T = lltype.GcStruct("T", ('x', lltype.Signed)) def f_S(s): s.x = 1 def f_S1(s1): s1.s.x = 1 s1.y = 2 def f_T(s): s.x = 1 def type_info_S(p): return lltype.getRuntimeTypeInfo(S) def type_info_T(p): return lltype.getRuntimeTypeInfo(T) qp = lltype.functionptr(lltype.FuncType([lltype.Ptr(S)], lltype.Ptr(lltype.RuntimeTypeInfo)), "type_info_S", _callable=type_info_S) dp = lltype.functionptr(lltype.FuncType([lltype.Ptr(S)], lltype.Void), "destructor_funcptr", _callable=f_S) pinf = lltype.attachRuntimeTypeInfo(S, qp, destrptr=dp) dp = lltype.functionptr(lltype.FuncType([lltype.Ptr(S)], lltype.Void), "destructor_funcptr", _callable=f_S1) pinf = lltype.attachRuntimeTypeInfo(S1, qp, destrptr=dp) qp = lltype.functionptr(lltype.FuncType([lltype.Ptr(T)], lltype.Ptr(lltype.RuntimeTypeInfo)), "type_info_S", _callable=type_info_T) dp = lltype.functionptr(lltype.FuncType([lltype.Ptr(T)], lltype.Void), "destructor_funcptr", _callable=f_T) pinf = lltype.attachRuntimeTypeInfo(T, qp, destrptr=dp) def f(): pass t = TranslationContext() t.buildannotator().build_types(f, []) t.buildrtyper().specialize() transformer = RefcountingGCTransformer(t) p_S = transformer.dynamic_deallocation_funcptr_for_type(S) p_S1 = transformer.dynamic_deallocation_funcptr_for_type(S1) p_T = transformer.dynamic_deallocation_funcptr_for_type(T) assert p_S is not p_T assert p_S is p_S1
def test_half_exceptiontransformed_graphs(): from pypy.translator import exceptiontransform def f1(x): if x < 0: raise ValueError return 754 def g1(x): try: return f1(x) except ValueError: return 5 def f2(x): if x < 0: raise ValueError return 21 def g2(x): try: return f2(x) except ValueError: return 6 f3 = lltype.functionptr(lltype.FuncType([lltype.Signed], lltype.Signed), 'f3', _callable = f1) def g3(x): try: return f3(x) except ValueError: return 7 def f(flag, x): if flag == 1: return g1(x) elif flag == 2: return g2(x) else: return g3(x) t = TranslationContext() t.buildannotator().build_types(f, [int, int]) t.buildrtyper().specialize() etrafo = exceptiontransform.ExceptionTransformer(t) etrafo.create_exception_handling(graphof(t, f1)) etrafo.create_exception_handling(graphof(t, g2)) etrafo.create_exception_handling(graphof(t, g3)) graph = graphof(t, f) interp = LLInterpreter(t.rtyper) res = interp.eval_graph(graph, [1, -64]) assert res == 5 res = interp.eval_graph(graph, [2, -897]) assert res == 6 res = interp.eval_graph(graph, [3, -9831]) assert res == 7
def test_desugar_isinstance(): class X(object): pass def f(): x = X() return isinstance(x, X()) graph = TranslationContext().buildflowgraph(f) desugar_isinstance(graph) assert len(graph.startblock.operations) == 3 block = graph.startblock assert block.operations[2].opname == "simple_call" assert isinstance(block.operations[2].args[0], Constant) assert block.operations[2].args[0].value is isinstance
def test_inserting_zeroing_op(self): from pypy.rpython.lltypesystem import lltype S = lltype.GcStruct("S", ('x', lltype.Signed)) def f(x): s = lltype.malloc(S) s.x = 0 return s.x t = TranslationContext() t.buildannotator().build_types(f, [int]) t.buildrtyper(type_system=self.type_system).specialize() g = graphof(t, f) etrafo = exceptiontransform.ExceptionTransformer(t) etrafo.create_exception_handling(g) ops = dict.fromkeys([o.opname for b, o in g.iterblockops()]) assert 'zero_gc_pointers_inside' in ops
def write_barrier_check(spaceop, needs_write_barrier=True): t = TranslationContext() t.buildannotator().build_types(lambda x: x, [SomeInteger()]) t.buildrtyper().specialize() transformer = WriteBarrierTransformer(t) llops = LowLevelOpList() hop = GcHighLevelOp(transformer, spaceop, 0, llops) hop.dispatch() found = False print spaceop, '======>' for op in llops: print '\t', op if op.opname == 'direct_call': found = True assert found == needs_write_barrier
def test_two_constants(): def fn(): r = range(10, 37, 4) r.reverse() return r[0] t = TranslationContext() a = t.buildannotator() a.build_types(fn, []) rtyper = t.buildrtyper() rtyper.specialize() backend_optimizations(t, merge_if_blocks=True) graph = tgraphof(t, fn) blocknum = len(list(graph.iterblocks())) merge_if_blocks(graph) assert blocknum == len(list(graph.iterblocks()))
def test_build(): def entry_point(argv): res = interp_pyexpat.XML_ErrorString(3) os.write(1, rffi.charp2str(res)) return 0 t = TranslationContext() t.buildannotator().build_types(entry_point, [s_list_of_strings]) t.buildrtyper().specialize() builder = CStandaloneBuilder(t, entry_point, t.config) builder.generate_source() builder.compile() data = builder.cmdexec() assert data == pyexpat.ErrorString(3)
def transform_func(self, fn, inputtypes, backendopt=False): t = TranslationContext() t.buildannotator().build_types(fn, inputtypes) t.buildrtyper(type_system=self.type_system).specialize() if conftest.option.view: t.view() if backendopt: backend_optimizations(t) g = graphof(t, fn) etrafo = exceptiontransform.ExceptionTransformer(t) etrafo.create_exception_handling(g) join_blocks(g) if conftest.option.view: t.view() return t, g
def test_tupletype_explosion(self): def f(x): t1 = ([x], [x, x]) t2 = ([x, x], [x]) return t1, t2 t = TranslationContext() a = t.buildannotator() s = a.build_types(f, [int]) typer = t.buildrtyper(type_system="ootype") typer.specialize() s_t1, s_t2 = s.items r_t1 = typer.getrepr(s_t1) r_t2 = typer.getrepr(s_t2) assert r_t1.lowleveltype == r_t2.lowleveltype
def test_listtype_explosion(self): def f(x): l1 = [x] l2 = [x] return l1, l2 t = TranslationContext() a = t.buildannotator() s = a.build_types(f, [int]) typer = t.buildrtyper(type_system="ootype") typer.specialize() s_l1, s_l2 = s.items r_l1 = typer.getrepr(s_l1) r_l2 = typer.getrepr(s_l2) assert r_l1.lowleveltype == r_l2.lowleveltype
def test_annotate_indexing(self): def f(): a = numpy.empty((3, 4, 5)) b = a[0] a[0, 1, 2] = 1. b[0, 1] = 2. b[:] = a[1] b[:, :] = a[1] b[0, :] = a[1, 2] return b t = TranslationContext() a = t.buildannotator() s = a.build_types(f, []) assert s.ndim == 2
def test_recursive_gcd(): def gcd(a, b): if a == 1 or a == 0: return b if a > b: return gcd(b, a) return gcd(b % a, a) t = TranslationContext() t.buildannotator().build_types(gcd, [int, int]) t.buildrtyper().specialize() gcd_graph = graphof(t, gcd) remove_tail_calls_to_self(t, gcd_graph ) lli = LLInterpreter(t.rtyper) res = lli.eval_graph(gcd_graph, (15, 25)) assert res == 5
def test_gc_x_operations(): t = TranslationContext() from pypy.rlib.rgc import gc_clone, gc_swap_pool S = lltype.GcStruct("S", ('x', lltype.Signed)) def f(): s = lltype.malloc(S) gc_swap_pool(None) try: t = gc_clone(s, None) except RuntimeError: return 1 else: return 0 fn = compile_func(f, [], t=t) res = fn() assert res == 1
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(type_system='lltype').specialize() exctransformer = t.getexceptiontransformer() exctransformer.create_exception_handling(graphof(t, common)) from pypy.annotation import model as annmodel from pypy.rpython.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 conftest.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 pypy.rpython.llinterp import LLInterpreter llinterp = LLInterpreter(t.rtyper) res = llinterp.eval_graph(later_graph, [10]) assert res == 1
def __init__(self, translator=None, policy=None, bookkeeper=None): import pypy.rpython.ootypesystem.ooregistry # has side effects import pypy.rpython.ootypesystem.bltregistry # has side effects import pypy.rpython.extfuncregistry # has side effects import pypy.rlib.nonconst # has side effects if translator is None: # interface for tests from pypy.translator.translator import TranslationContext translator = TranslationContext() translator.annotator = self self.translator = translator self.pendingblocks = {} # map {block: graph-containing-it} self.bindings = {} # map Variables to SomeValues self.annotated = {} # set of blocks already seen self.added_blocks = None # see processblock() below self.links_followed = {} # set of links that have ever been followed self.notify = {} # {block: {positions-to-reflow-from-when-done}} self.fixed_graphs = {} # set of graphs not to annotate again self.blocked_blocks = {} # set of {blocked_block: graph} # --- the following information is recorded for debugging only --- # --- and only if annotation.model.DEBUG is kept to True self.why_not_annotated = { } # {block: (exc_type, exc_value, traceback)} # records the location of BlockedInference # exceptions that blocked some blocks. self.blocked_graphs = {} # set of graphs that have blocked blocks self.bindingshistory = {} # map Variables to lists of SomeValues self.binding_caused_by = {} # map Variables to position_keys # records the caller position that caused bindings of inputargs # to be updated self.binding_cause_history = {} # map Variables to lists of positions # history of binding_caused_by, kept in sync with # bindingshistory self.reflowcounter = {} self.return_bindings = {} # map return Variables to their graphs # --- end of debugging information --- self.frozen = False if policy is None: from pypy.annotation.policy import AnnotatorPolicy self.policy = AnnotatorPolicy() else: self.policy = policy if bookkeeper is None: bookkeeper = Bookkeeper(self) self.bookkeeper = bookkeeper