def test_indirect_call_target(self): def g(m): return 123 def h(m): return 456 def f(n): if n > 3: call = g else: call = h return call(n + 1) + call(n + 2) graphs = self.make_graphs(f, [5]) cw = CodeWriter(self.rtyper) cw.candidate_graphs = graphs cw._start(self.metainterp_sd, None) jitcode = cw.make_one_bytecode((graphs[0], None), False) assert len(self.metainterp_sd.indirectcalls) == 2 names = [ jitcode.name for (fnaddress, jitcode) in self.metainterp_sd.indirectcalls ] assert dict.fromkeys(names) == {'g': None, 'h': None}
def test_oois_constant_null(self): from pypy.rpython.lltypesystem import lltype S = lltype.GcStruct('S') s = lltype.malloc(S) NULL = lltype.nullptr(S) def f(p, i): if i % 2: return p == NULL elif i % 3: return NULL == p elif i % 4: return p != NULL else: return NULL != p graphs = self.make_graphs(f, [s, 5]) cw = CodeWriter(self.rtyper) cw.candidate_graphs = graphs cw._start(self.metainterp_sd, None) jitcode = cw.make_one_bytecode((graphs[0], None), False) assert 'ptr_eq' not in jitcode._source assert 'ptr_ne' not in jitcode._source assert jitcode._source.count('oononnull') == 2 assert jitcode._source.count('ooisnull') == 2
def test_indirect_look_inside_only_one(self): def g(m): return 123 @jit.dont_look_inside def h(m): return 456 def f(n): if n > 3: call = g else: call = h return call(n + 1) + call(n + 2) graphs = self.make_graphs(f, [5]) graphs = [g for g in graphs if getattr(g.func, "_jit_look_inside_", True)] cw = CodeWriter(self.rtyper) cw.candidate_graphs = graphs cw._start(self.metainterp_sd, None) jitcode = cw.make_one_bytecode((graphs[0], None), False) assert len(self.metainterp_sd.indirectcalls) == 1 names = [jitcode1.name for (fnaddress, jitcode1) in self.metainterp_sd.indirectcalls] assert dict.fromkeys(names) == {"g": None} calldescrs = [ calldescr for calldescr in jitcode.constants if isinstance(calldescr, tuple) and calldescr[0] == "calldescr" ] assert len(calldescrs) == 1 assert calldescrs[0][4] is not None assert not calldescrs[0][4].write_descrs_fields assert not calldescrs[0][4].write_descrs_arrays assert not calldescrs[0][4].forces_virtual_or_virtualizable
def test_oosend_look_inside_only_one(self): class A: pass class B(A): def g(self): return 123 class C(A): @jit.dont_look_inside def g(self): return 456 def f(n): if n > 3: x = B() else: x = C() return x.g() + x.g() graphs = self.make_graphs(f, [5], type_system='ootype') graphs = [g for g in graphs if getattr(g.func, '_jit_look_inside_', True)] cw = CodeWriter(self.rtyper) cw.candidate_graphs = graphs cw._start(self.metainterp_sd, None) jitcode = cw.make_one_bytecode((graphs[0], None), False) assert len(self.methdescrs) == 1 assert self.methdescrs[0].CLASS._name.endswith('.A') assert self.methdescrs[0].methname == 'og' assert len(self.methdescrs[0].jitcodes.keys()) == 2 values = self.methdescrs[0].jitcodes.values() values.sort() assert values[0] is None assert values[1].name == 'B.g' for graph, _ in cw.all_graphs.keys(): assert graph.name in ['f', 'B.g']
def test_oois_constant_null(self): from pypy.rpython.lltypesystem import lltype S = lltype.GcStruct("S") s = lltype.malloc(S) NULL = lltype.nullptr(S) def f(p, i): if i % 2: return p == NULL elif i % 3: return NULL == p elif i % 4: return p != NULL else: return NULL != p graphs = self.make_graphs(f, [s, 5]) cw = CodeWriter(self.rtyper) cw.candidate_graphs = graphs cw._start(self.metainterp_sd, None) jitcode = cw.make_one_bytecode((graphs[0], None), False) assert "ptr_eq" not in jitcode._source assert "ptr_ne" not in jitcode._source assert jitcode._source.count("oononnull") == 2 assert jitcode._source.count("ooisnull") == 2
def test_indirect_look_inside_only_one(self): def g(m): return 123 @jit.dont_look_inside def h(m): return 456 def f(n): if n > 3: call = g else: call = h return call(n + 1) + call(n + 2) graphs = self.make_graphs(f, [5]) graphs = [ g for g in graphs if getattr(g.func, '_jit_look_inside_', True) ] cw = CodeWriter(self.rtyper) cw.candidate_graphs = graphs cw._start(self.metainterp_sd, None) jitcode = cw.make_one_bytecode((graphs[0], None), False) assert len(self.metainterp_sd.indirectcalls) == 1 names = [ jitcode.name for (fnaddress, jitcode) in self.metainterp_sd.indirectcalls ] assert dict.fromkeys(names) == {'g': None}
def test_instantiate(self): class A1: id = 651 class A2(A1): id = 652 class B1: id = 661 class B2(B1): id = 662 def f(n): if n > 5: x, y = A1, B1 else: x, y = A2, B2 n += 1 return x().id + y().id + n graphs = self.make_graphs(f, [5]) cw = CodeWriter(self.rtyper) cw.candidate_graphs = graphs cw._start(self.metainterp_sd, None) cw.make_one_bytecode((graphs[0], None), False) graph2 = self.graphof(ll_instantiate) jitcode = cw.make_one_bytecode((graph2, None), False) assert 'residual_call' not in jitcode._source names = [jitcode.name for (fnaddress, jitcode) in self.metainterp_sd.indirectcalls] names = dict.fromkeys(names) assert len(names) >= 4 for expected in ['A1', 'A2', 'B1', 'B2']: for name in names: if name.startswith('instantiate_') and name.endswith(expected): break else: assert 0, "missing instantiate_*_%s in:\n%r" % (expected, names)
def test_guess_call_kind_and_calls_from_graphs(self): from pypy.objspace.flow.model import SpaceOperation, Constant, Variable portal_runner_ptr = object() g = object() g1 = object() cw = CodeWriter(None) cw.candidate_graphs = [g, g1] cw.portal_runner_ptr = portal_runner_ptr op = SpaceOperation('direct_call', [Constant(portal_runner_ptr)], Variable()) assert cw.guess_call_kind(op) == 'recursive' op = SpaceOperation('direct_call', [Constant(object())], Variable()) assert cw.guess_call_kind(op) == 'residual' class funcptr: class graph: class func: oopspec = "spec" op = SpaceOperation('direct_call', [Constant(funcptr)], Variable()) assert cw.guess_call_kind(op) == 'builtin' class funcptr: graph = g op = SpaceOperation('direct_call', [Constant(funcptr)], Variable()) res = cw.graphs_from(op) assert res == [g] assert cw.guess_call_kind(op) == 'regular' class funcptr: graph = object() op = SpaceOperation('direct_call', [Constant(funcptr)], Variable()) res = cw.graphs_from(op) assert res is None assert cw.guess_call_kind(op) == 'residual' h = object() op = SpaceOperation('indirect_call', [Variable(), Constant([g, g1, h])], Variable()) res = cw.graphs_from(op) assert res == [g, g1] assert cw.guess_call_kind(op) == 'regular' op = SpaceOperation('indirect_call', [Variable(), Constant([h])], Variable()) res = cw.graphs_from(op) assert res is None assert cw.guess_call_kind(op) == 'residual'
def test_basic(self): def f(n): return n + 10 graphs = self.make_graphs(f, [5]) cw = CodeWriter(self.rtyper) cw.candidate_graphs = graphs cw._start(self.metainterp_sd, None) jitcode = cw.make_one_bytecode((graphs[0], None), False) assert jitcode._source == [SomeLabel(), "int_add", 0, 1, "# => r1", "make_new_vars_1", 2, "return"]
def test_direct_call(self): def g(m): return 123 def f(n): return g(n+1) graphs = self.make_graphs(f, [5]) cw = CodeWriter(self.rtyper) cw.candidate_graphs = graphs cw._start(self.metainterp_sd, None) jitcode = cw.make_one_bytecode((graphs[0], None), False) assert len(cw.all_graphs) == 2
def test_guess_call_kind_and_calls_from_graphs(self): from pypy.objspace.flow.model import SpaceOperation, Constant, Variable portal_runner_ptr = object() g = object() g1 = object() cw = CodeWriter(None) cw.candidate_graphs = [g, g1] cw.portal_runner_ptr = portal_runner_ptr op = SpaceOperation('direct_call', [Constant(portal_runner_ptr)], Variable()) assert cw.guess_call_kind(op) == 'recursive' op = SpaceOperation('direct_call', [Constant(object())], Variable()) assert cw.guess_call_kind(op) == 'residual' class funcptr: class graph: class func: oopspec = "spec" op = SpaceOperation('direct_call', [Constant(funcptr)], Variable()) assert cw.guess_call_kind(op) == 'builtin' class funcptr: graph = g op = SpaceOperation('direct_call', [Constant(funcptr)], Variable()) res = cw.graphs_from(op) assert res == [g] assert cw.guess_call_kind(op) == 'regular' class funcptr: graph = object() op = SpaceOperation('direct_call', [Constant(funcptr)], Variable()) res = cw.graphs_from(op) assert res is None assert cw.guess_call_kind(op) == 'residual' h = object() op = SpaceOperation('indirect_call', [Variable(), Constant([g, g1, h])], Variable()) res = cw.graphs_from(op) assert res == [g, g1] assert cw.guess_call_kind(op) == 'regular' op = SpaceOperation('indirect_call', [Variable(), Constant([h])], Variable()) res = cw.graphs_from(op) assert res is None assert cw.guess_call_kind(op) == 'residual'
def test_direct_call(self): def g(m): return 123 def f(n): return g(n + 1) graphs = self.make_graphs(f, [5]) cw = CodeWriter(self.rtyper) cw.candidate_graphs = graphs cw._start(self.metainterp_sd, None) jitcode = cw.make_one_bytecode((graphs[0], None), False) assert len(cw.all_graphs) == 2
def test_basic(self): def f(n): return n + 10 graphs = self.make_graphs(f, [5]) cw = CodeWriter(self.rtyper) cw.candidate_graphs = graphs cw._start(self.metainterp_sd, None) jitcode = cw.make_one_bytecode((graphs[0], None), False) assert jitcode._source == [ SomeLabel(), 'int_add', 0, 1, '# => r1', 'make_new_vars_1', 2, 'return' ]
def test_we_are_jitted(self): def f(): if jit.we_are_jitted(): return 55 else: return 66 graphs = self.make_graphs(f, []) cw = CodeWriter(self.rtyper) cw.candidate_graphs = [graphs[0]] cw._start(self.metainterp_sd, None) jitcode = cw.make_one_bytecode((graphs[0], None), False) assert 'goto_if_not' not in jitcode._source assert ConstInt(55) in jitcode.constants assert ConstInt(66) not in jitcode.constants
def test_we_are_jitted(self): def f(): if jit.we_are_jitted(): return 55 else: return 66 graphs = self.make_graphs(f, []) cw = CodeWriter(self.rtyper) cw.candidate_graphs = [graphs[0]] cw._start(self.metainterp_sd, None) jitcode = cw.make_one_bytecode((graphs[0], None), False) assert "goto_if_not" not in jitcode._source assert ConstInt(55) in jitcode.constants assert ConstInt(66) not in jitcode.constants
def test_vref_simple(self): class X: pass def f(): return jit.virtual_ref(X()) graphs = self.make_graphs(f, []) assert graphs[0].func is f assert graphs[1].func is jit.virtual_ref self.make_vrefinfo() cw = CodeWriter(self.rtyper) cw.candidate_graphs = [graphs[0]] cw._start(self.metainterp_sd, None) jitcode = cw.make_one_bytecode((graphs[0], None), False) assert 'virtual_ref' in jitcode._source
def test_vref_simple(self): class X: pass def f(): return jit.virtual_ref(X()) graphs = self.make_graphs(f, []) assert graphs[0].func is f assert graphs[1].func is jit.virtual_ref self.make_vrefinfo() cw = CodeWriter(self.rtyper) cw.candidate_graphs = [graphs[0]] cw._start(self.metainterp_sd, None) jitcode = cw.make_one_bytecode((graphs[0], None), False) assert "virtual_ref" in jitcode._source
def test_list_of_addr2name(self): class A1: def g(self): self.x = 123 return 5 def f(): a = A1() a.y = a.g() return a graphs = self.make_graphs(f, []) cw = CodeWriter(self.rtyper) cw.candidate_graphs = [graphs[0]] cw._start(self.metainterp_sd, None) jitcode = cw.make_one_bytecode((graphs[0], None), False) assert len(cw.list_of_addr2name) == 2 assert cw.list_of_addr2name[0][1].endswith('.A1') assert cw.list_of_addr2name[1][1] == 'A1.g'
def test_list_of_addr2name(self): class A1: def g(self): self.x = 123 return 5 def f(): a = A1() a.y = a.g() return a graphs = self.make_graphs(f, []) cw = CodeWriter(self.rtyper) cw.candidate_graphs = [graphs[0]] cw._start(self.metainterp_sd, None) jitcode = cw.make_one_bytecode((graphs[0], None), False) assert len(cw.list_of_addr2name) == 2 assert cw.list_of_addr2name[0][1].endswith(".A1") assert cw.list_of_addr2name[1][1] == "A1.g"
def test_instantiate(self): class A1: id = 651 class A2(A1): id = 652 class B1: id = 661 class B2(B1): id = 662 def f(n): if n > 5: x, y = A1, B1 else: x, y = A2, B2 n += 1 return x().id + y().id + n graphs = self.make_graphs(f, [5]) cw = CodeWriter(self.rtyper) cw.candidate_graphs = graphs cw._start(self.metainterp_sd, None) cw.make_one_bytecode((graphs[0], None), False) graph2 = self.graphof(ll_instantiate) jitcode = cw.make_one_bytecode((graph2, None), False) assert 'residual_call' not in jitcode._source names = [ jitcode.name for (fnaddress, jitcode) in self.metainterp_sd.indirectcalls ] names = dict.fromkeys(names) assert len(names) >= 4 for expected in ['A1', 'A2', 'B1', 'B2']: for name in names: if name.startswith('instantiate_') and name.endswith(expected): break else: assert 0, "missing instantiate_*_%s in:\n%r" % (expected, names)
def test_indirect_call_target(self): def g(m): return 123 def h(m): return 456 def f(n): if n > 3: call = g else: call = h return call(n+1) + call(n+2) graphs = self.make_graphs(f, [5]) cw = CodeWriter(self.rtyper) cw.candidate_graphs = graphs cw._start(self.metainterp_sd, None) jitcode = cw.make_one_bytecode((graphs[0], None), False) assert len(self.metainterp_sd.indirectcalls) == 2 names = [jitcode.name for (fnaddress, jitcode) in self.metainterp_sd.indirectcalls] assert dict.fromkeys(names) == {'g': None, 'h': None}
def test_vref_forced(self): class X: pass def f(): vref = jit.virtual_ref(X()) return vref() graphs = self.make_graphs(f, []) assert graphs[0].func is f assert graphs[1].func is jit.virtual_ref self.make_vrefinfo() cw = CodeWriter(self.rtyper) cw.candidate_graphs = [graphs[0]] cw._start(self.metainterp_sd, None) jitcode = cw.make_one_bytecode((graphs[0], None), False) assert 'virtual_ref' in jitcode._source # the call vref() becomes a residual call to a helper that contains # itself a copy of the call. assert 'residual_call' in jitcode._source
def test_vref_forced(self): class X: pass def f(): vref = jit.virtual_ref(X()) return vref() graphs = self.make_graphs(f, []) assert graphs[0].func is f assert graphs[1].func is jit.virtual_ref self.make_vrefinfo() cw = CodeWriter(self.rtyper) cw.candidate_graphs = [graphs[0]] cw._start(self.metainterp_sd, None) jitcode = cw.make_one_bytecode((graphs[0], None), False) assert "virtual_ref" in jitcode._source # the call vref() becomes a residual call to a helper that contains # itself a copy of the call. assert "residual_call" in jitcode._source
def test_jit_force_virtualizable_effectinfo(self): class Frame(object): _virtualizable2_ = ['x'] def __init__(self, x, y): self.x = x self.y = y def g1(f): f.x += 1 def g2(f): return f.x def h(f): f.y -= 1 def f(n): f_inst = Frame(n + 1, n + 2) g1(f_inst) r = g2(f_inst) h(f_inst) return r graphs = self.make_graphs(f, [5]) cw = CodeWriter(self.rtyper) cw.candidate_graphs = [graphs[0]] cw._start(self.metainterp_sd, None) jitcode = cw.make_one_bytecode((graphs[0], None), False) calldescrs = [ calldescr for calldescr in jitcode.constants if isinstance(calldescr, tuple) and calldescr[0] == 'calldescr' ] assert len(calldescrs) == 4 # for __init__, g1, g2, h. effectinfo_g1 = calldescrs[1][4] effectinfo_g2 = calldescrs[2][4] effectinfo_h = calldescrs[3][4] assert effectinfo_g1.forces_virtual_or_virtualizable assert effectinfo_g2.forces_virtual_or_virtualizable assert not effectinfo_h.forces_virtual_or_virtualizable
def test_jit_force_virtualizable_effectinfo(self): class Frame(object): _virtualizable2_ = ["x"] def __init__(self, x, y): self.x = x self.y = y def g1(f): f.x += 1 def g2(f): return f.x def h(f): f.y -= 1 def f(n): f_inst = Frame(n + 1, n + 2) g1(f_inst) r = g2(f_inst) h(f_inst) return r graphs = self.make_graphs(f, [5]) cw = CodeWriter(self.rtyper) cw.candidate_graphs = [graphs[0]] cw._start(self.metainterp_sd, None) jitcode = cw.make_one_bytecode((graphs[0], None), False) calldescrs = [ calldescr for calldescr in jitcode.constants if isinstance(calldescr, tuple) and calldescr[0] == "calldescr" ] assert len(calldescrs) == 4 # for __init__, g1, g2, h. effectinfo_g1 = calldescrs[1][4] effectinfo_g2 = calldescrs[2][4] effectinfo_h = calldescrs[3][4] assert effectinfo_g1.forces_virtual_or_virtualizable assert effectinfo_g2.forces_virtual_or_virtualizable assert not effectinfo_h.forces_virtual_or_virtualizable
def test_oosend_look_inside_only_one(self): class A: pass class B(A): def g(self): return 123 class C(A): @jit.dont_look_inside def g(self): return 456 def f(n): if n > 3: x = B() else: x = C() return x.g() + x.g() graphs = self.make_graphs(f, [5], type_system='ootype') graphs = [ g for g in graphs if getattr(g.func, '_jit_look_inside_', True) ] cw = CodeWriter(self.rtyper) cw.candidate_graphs = graphs cw._start(self.metainterp_sd, None) jitcode = cw.make_one_bytecode((graphs[0], None), False) assert len(self.methdescrs) == 1 assert self.methdescrs[0].CLASS._name.endswith('.A') assert self.methdescrs[0].methname == 'og' assert len(self.methdescrs[0].jitcodes.keys()) == 2 values = self.methdescrs[0].jitcodes.values() values.sort() assert values[0] is None assert values[1].name == 'B.g' for graph, _ in cw.all_graphs.keys(): assert graph.name in ['f', 'B.g']
def test_indirect_look_inside_only_one(self): def g(m): return 123 @jit.dont_look_inside def h(m): return 456 def f(n): if n > 3: call = g else: call = h return call(n + 1) + call(n + 2) graphs = self.make_graphs(f, [5]) graphs = [ g for g in graphs if getattr(g.func, '_jit_look_inside_', True) ] cw = CodeWriter(self.rtyper) cw.candidate_graphs = graphs cw._start(self.metainterp_sd, None) jitcode = cw.make_one_bytecode((graphs[0], None), False) assert len(self.metainterp_sd.indirectcalls) == 1 names = [ jitcode1.name for (fnaddress, jitcode1) in self.metainterp_sd.indirectcalls ] assert dict.fromkeys(names) == {'g': None} calldescrs = [ calldescr for calldescr in jitcode.constants if isinstance(calldescr, tuple) and calldescr[0] == 'calldescr' ] assert len(calldescrs) == 1 assert calldescrs[0][4] is not None assert not calldescrs[0][4].write_descrs_fields assert not calldescrs[0][4].write_descrs_arrays assert not calldescrs[0][4].forces_virtual_or_virtualizable
def test_indirect_look_inside_only_one(self): def g(m): return 123 @jit.dont_look_inside def h(m): return 456 def f(n): if n > 3: call = g else: call = h return call(n+1) + call(n+2) graphs = self.make_graphs(f, [5]) graphs = [g for g in graphs if getattr(g.func, '_jit_look_inside_', True)] cw = CodeWriter(self.rtyper) cw.candidate_graphs = graphs cw._start(self.metainterp_sd, None) jitcode = cw.make_one_bytecode((graphs[0], None), False) assert len(self.metainterp_sd.indirectcalls) == 1 names = [jitcode.name for (fnaddress, jitcode) in self.metainterp_sd.indirectcalls] assert dict.fromkeys(names) == {'g': None}