def test_subclassof(self): A = ootype.Instance("A", ootype.ROOT) B = ootype.Instance("B", A) clsA = ootype.runtimeClass(A) clsB = ootype.runtimeClass(B) myjitdriver = JitDriver(greens=[], reds=['n', 'flag', 'res']) def getcls(flag): if flag: return clsA else: return clsB def f(flag, n): res = True while n > -100: myjitdriver.can_enter_jit(n=n, flag=flag, res=res) myjitdriver.jit_merge_point(n=n, flag=flag, res=res) cls = getcls(flag) n -= 1 res = ootype.subclassof(cls, clsB) return res res = self.meta_interp(f, [1, 100], policy=StopAtXPolicy(getcls), optimizer=OPTIMIZER_SIMPLE) assert not res res = self.meta_interp(f, [0, 100], policy=StopAtXPolicy(getcls), optimizer=OPTIMIZER_SIMPLE) assert res
def test_send_to_single_target_method(self): myjitdriver = JitDriver(greens = [], reds = ['i', 'counter']) class Foo: def meth(self, y): return self.x + y def externfn(i): foo = Foo() foo.x = i * 42 return foo def f(i): counter = 20 res = 0 while counter > 0: myjitdriver.can_enter_jit(counter=counter, i=i) myjitdriver.jit_merge_point(counter=counter, i=i) foo = externfn(i) res = foo.meth(i) counter -= 1 return res res = self.meta_interp(f, [1], policy=StopAtXPolicy(externfn), backendopt=True) assert res == 43 self.check_loops({'call': 1, 'guard_no_exception': 1, 'getfield_gc': 1, 'int_add': 1, 'jump': 1, 'int_gt' : 1, 'guard_true' : 1, 'int_sub' : 1})
def test_three_classes(self): class Base: pass class A(Base): def f(self): return 1 class B(Base): def f(self): return 2 class C(Base): def f(self): return 3 myjitdriver = JitDriver(greens = [], reds = ['n']) def extern(n): if n > 40: return A() elif n > 20: return B() else: return C() def f(n): while n > 0: myjitdriver.can_enter_jit(n=n) myjitdriver.jit_merge_point(n=n) n -= extern(n).f() return n res = self.meta_interp(f, [55], policy=StopAtXPolicy(extern)) assert res == f(55) self.check_tree_loop_count(2)
def test_indirect_call_unknown_object_2(self): myjitdriver = JitDriver(greens = [], reds = ['x', 'y', 'state']) def getvalue2(): return 2 def getvalue25(): return 25 def getvalue1001(): return -1001 class State: count = 0 def externfn(self, n): assert n == 198 - self.count self.count += 1 if n % 5: return getvalue2 elif n % 7: return getvalue25 else: return getvalue1001 def f(y): state = State() x = 0 while y > 0: myjitdriver.can_enter_jit(x=x, y=y, state=state) myjitdriver.jit_merge_point(x=x, y=y, state=state) x += state.externfn(y)() y -= 1 return x res = self.meta_interp(f, [198], policy=StopAtXPolicy(State.externfn.im_func)) assert res == f(198) # we get two TreeLoops: an initial one, and one entering from # the interpreter self.check_tree_loop_count(2)
def test_three_receivers(self): myjitdriver = JitDriver(greens = [], reds = ['y']) class Base: pass class W1(Base): def foo(self): return 1 class W2(Base): def foo(self): return 2 class W3(Base): def foo(self): return 3 def externfn(y): if y % 4 == 0: return W1() elif y % 4 == 3: return W2() else: return W3() def f(y): while y > 0: myjitdriver.can_enter_jit(y=y) myjitdriver.jit_merge_point(y=y) w = externfn(y) w.foo() y -= 1 return 42 policy = StopAtXPolicy(externfn) for j in range(69, 75): res = self.meta_interp(f, [j], policy=policy) assert res == 42 self.check_loop_count(3)
def test_stopatxpolicy(self): myjitdriver = JitDriver(greens=[], reds=['y']) def internfn(y): return y * 3 def externfn(y): return y % 4 def f(y): while y >= 0: myjitdriver.can_enter_jit(y=y) myjitdriver.jit_merge_point(y=y) if y & 7: f = internfn else: f = externfn f(y) y -= 1 return 42 policy = StopAtXPolicy(externfn) res = self.meta_interp(f, [31], policy=policy) assert res == 42 self.check_loops(int_mul=1, int_mod=0)
def test_assembler_call_red_args(self): driver = JitDriver(greens=['codeno'], reds=['i', 'k'], get_printable_location=lambda codeno: str(codeno), can_inline=lambda codeno: False) def residual(k): if k > 40: return 0 return 1 def portal(codeno, k): i = 0 while i < 10: driver.can_enter_jit(codeno=codeno, i=i, k=k) driver.jit_merge_point(codeno=codeno, i=i, k=k) if codeno == 2: k += portal(residual(k), k) if codeno == 0: k += 2 elif codeno == 1: k += 1 i += 1 return k res = self.meta_interp(portal, [2, 0], inline=True, policy=StopAtXPolicy(residual)) assert res == portal(2, 0) self.check_loops(call_assembler=2)
def test_external_write_while_tracing(self): myjitdriver = JitDriver(greens=[], reds=['n', 'm', 'xy'], virtualizables=['xy']) class Outer: pass outer = Outer() def ext(): xy = outer.xy promote_virtualizable(xy, 'inst_x') xy.inst_x += 2 def f(n): xy = self.setup() xy.inst_x = 10 outer.xy = xy m = 0 while n > 0: myjitdriver.can_enter_jit(xy=xy, n=n, m=m) myjitdriver.jit_merge_point(xy=xy, n=n, m=m) promote_virtualizable(xy, 'inst_x') xy.inst_x = n + 9998 # virtualized away ext() # 2x setfield_gc, 2x getfield_gc promote_virtualizable(xy, 'inst_x') m += xy.inst_x # virtualized away n -= 1 return m res = self.meta_interp(f, [20], policy=StopAtXPolicy(ext)) assert res == f(20) self.check_loops(call=1, getfield_gc=2, setfield_gc=2)
def test_residual_oosend_with_void(self): myjitdriver = JitDriver(greens=[], reds=['i', 'obj']) class A: def foo(self, other): return 41 def _freeze_(self): return True def new(n): if n: return A() else: return None pbc = A() def fn(n, i): res = 0 obj = new(n) while i > 0: myjitdriver.can_enter_jit(i=i, obj=obj) myjitdriver.jit_merge_point(i=i, obj=obj) res = obj.foo(pbc) i -= 1 return res policy = StopAtXPolicy(new, A.foo.im_func) res = self.meta_interp(fn, [1, 20], policy=policy) assert res == 41 if self.type_system == 'ootype': self.check_loops(oosend=1) else: self.check_loops(call=1)
def test_adapt_bridge_to_merge_point(self): myjitdriver = JitDriver(greens=[], reds=['x', 'z']) class Z(object): def __init__(self, elem): self.elem = elem def externfn(z): pass def f(x, y): z = Z(y) while x > 0: myjitdriver.can_enter_jit(x=x, z=z) myjitdriver.jit_merge_point(x=x, z=z) if x % 5 != 0: externfn(z) z = Z(z.elem + 1) x -= 1 return z.elem expected = f(100, 5) res = self.meta_interp(f, [100, 5], policy=StopAtXPolicy(externfn)) assert res == expected self.check_loop_count(2) self.check_tree_loop_count(2) # 1 loop, 1 bridge from interp
def test_bug1(self): myjitdriver = JitDriver(greens=[], reds=['node', 'n']) class Base: pass class A(Base): def decr(self, n): return n - 2 class B(Base): def __init__(self, n): self.n = n def decr(self, n): assert n == self.n return self.n - 1 def extern(n): if n <= 21: return B(n) else: return A() def f(n): node = A() while n >= 0: myjitdriver.can_enter_jit(node=node, n=n) myjitdriver.jit_merge_point(node=node, n=n) n = node.decr(n) node = extern(n) return n res = self.meta_interp(f, [60], policy=StopAtXPolicy(extern)) assert res == f(60)
def test_residual_oosend(self): myjitdriver = JitDriver(greens=[], reds=['i', 'obj']) class A: def foo(self): return 41 class B(A): def foo(self): return 42 def new(n): if n: return A() else: return B() def fn(n, i): res = 0 obj = new(n) while i > 0: myjitdriver.can_enter_jit(i=i, obj=obj) myjitdriver.jit_merge_point(i=i, obj=obj) res = obj.foo() i -= 1 return res policy = StopAtXPolicy(new, A.foo.im_func, B.foo.im_func) res = self.meta_interp(fn, [0, 20], policy=policy) assert res == 42 if self.type_system == 'ootype': self.check_loops(oosend=1) else: self.check_loops(call=1)
def test_red_builtin_send(self): myjitdriver = JitDriver(greens=[], reds=['i', 'counter']) lst = [{1: 1, 2: 2, 3: 3}, {4: 4, 5: 5}] def externfn(i): return lst[i] def f(i): counter = 20 res = 0 while counter > 0: myjitdriver.can_enter_jit(counter=counter, i=i) myjitdriver.jit_merge_point(counter=counter, i=i) dct = externfn(i) res = len(dct) counter -= 1 return res res = self.meta_interp(f, [1], policy=StopAtXPolicy(externfn)) assert res == 2 if self.type_system == 'ootype': self.check_loops(call=1, oosend=1) # 'len' remains else: # 'len' becomes a getfield('num_items') for now in lltype, # which is itself encoded as a 'getfield_gc' self.check_loops(call=1, getfield_gc=1)
def test_indirect_call_unknown_object_1(self): myjitdriver = JitDriver(greens=[], reds=['x', 'y']) def getvalue2(): return 2 def getvalue25(): return 25 def getvalue1001(): return -1001 def externfn(n): if n % 5: return getvalue2 elif n % 7: return getvalue25 else: return getvalue1001 def f(y): x = 0 while y > 0: myjitdriver.can_enter_jit(x=x, y=y) myjitdriver.jit_merge_point(x=x, y=y) x += externfn(y)() y -= 1 return x res = self.meta_interp(f, [198], policy=StopAtXPolicy(externfn)) assert res == f(198) self.check_loop_count(4)
def test_raise_through_wrong_exc_2(self): myjitdriver = JitDriver(greens=[], reds=['n']) def check(n): if n < 0: raise ValueError else: raise IndexError def f(n): while True: myjitdriver.can_enter_jit(n=n) myjitdriver.jit_merge_point(n=n) try: check(n) except IndexError: n -= 1 def main(n): try: f(n) except ValueError: return 132 res = self.meta_interp(main, [13], policy=StopAtXPolicy(check)) assert res == 132
def test_loop_with_two_paths(self): from pypy.rpython.lltypesystem import lltype from pypy.rpython.lltypesystem.lloperation import llop myjitdriver = JitDriver(greens=[], reds=['x', 'y', 'res']) def l(y, x, t): llop.debug_print(lltype.Void, y, x, t) def g(y, x, r): if y <= 12: res = x - 2 else: res = x l(y, x, r) return res def f(x, y): res = 0 while y > 0: myjitdriver.can_enter_jit(x=x, y=y, res=res) myjitdriver.jit_merge_point(x=x, y=y, res=res) res += g(y, x, res) y -= 1 return res * 2 res = self.meta_interp(f, [6, 33], policy=StopAtXPolicy(l)) assert res == f(6, 33) self.check_loop_count(2)
def test_constfold_pure_oosend(self): myjitdriver = JitDriver(greens=[], reds=['i', 'obj']) class A: @purefunction def foo(self): return 42 def fn(n, i): res = 0 obj = A() while i > 0: myjitdriver.can_enter_jit(i=i, obj=obj) myjitdriver.jit_merge_point(i=i, obj=obj) obj = hint(obj, promote=True) res = obj.foo() i -= 1 return res policy = StopAtXPolicy(A.foo.im_func) res = self.meta_interp(fn, [1, 20], policy=policy) assert res == 42 if self.type_system == 'ootype': self.check_loops(oosend=0) else: self.check_loops(call=0)
def test_bridge_forces(self): jitdriver = JitDriver(greens=[], reds=['frame'], virtualizables=['frame']) class Frame(object): _virtualizable2_ = ['x', 'y'] class SomewhereElse: pass somewhere_else = SomewhereElse() def g(): n = somewhere_else.top_frame.y + 700 debug_print(lltype.Void, '-+-+-+-+- external write:', n) somewhere_else.top_frame.y = n def f(n): frame = Frame() frame.x = n frame.y = 10 somewhere_else.counter = 0 somewhere_else.top_frame = frame while frame.x > 0: jitdriver.can_enter_jit(frame=frame) jitdriver.jit_merge_point(frame=frame) if frame.y > 17: g() frame.x -= 5 frame.y += 1 return frame.y res = self.meta_interp(f, [123], policy=StopAtXPolicy(g)) assert res == f(123)
def test_external_read(self): jitdriver = JitDriver(greens=[], reds=['frame'], virtualizables=['frame']) class Frame(object): _virtualizable2_ = ['x', 'y'] class SomewhereElse: pass somewhere_else = SomewhereElse() def g(): result = somewhere_else.top_frame.y # external read debug_print(lltype.Void, '-+-+-+-+- external read:', result) return result def f(n): frame = Frame() frame.x = n frame.y = 10 somewhere_else.top_frame = frame while frame.x > 0: jitdriver.can_enter_jit(frame=frame) jitdriver.jit_merge_point(frame=frame) frame.x -= g() frame.y += 1 return frame.x res = self.meta_interp(f, [123], policy=StopAtXPolicy(g)) assert res == f(123)
def test_external_write(self): jitdriver = JitDriver(greens=[], reds=['frame'], virtualizables=['frame']) class Frame(object): _virtualizable2_ = ['x', 'y'] class SomewhereElse: pass somewhere_else = SomewhereElse() def g(): result = somewhere_else.top_frame.y + 1 debug_print(lltype.Void, '-+-+-+-+- external write:', result) somewhere_else.top_frame.y = result # external read/write def f(n): frame = Frame() frame.x = n frame.y = 10 somewhere_else.top_frame = frame while frame.x > 0: jitdriver.can_enter_jit(frame=frame) jitdriver.jit_merge_point(frame=frame) g() frame.x -= frame.y return frame.y res = self.meta_interp(f, [240], policy=StopAtXPolicy(g)) assert res == f(240) self.check_aborted_count(3) self.check_tree_loop_count(0)
def test_external_pass(self): jitdriver = JitDriver(greens=[], reds=['frame', 'n', 'z'], virtualizables=['frame']) class BaseFrame(object): _virtualizable2_ = ['x[*]'] def __init__(self, x): self.x = x class Frame(BaseFrame): pass def g(frame): return frame.x[1] == 1 def f(n): BaseFrame([]) # hack to force 'x' to be in BaseFrame frame = Frame([1, 2, 3]) z = 0 while n > 0: jitdriver.can_enter_jit(frame=frame, n=n, z=z) jitdriver.jit_merge_point(frame=frame, n=n, z=z) z += g(frame) n -= 1 return z res = self.meta_interp(f, [10], policy=StopAtXPolicy(g)) assert res == f(10)
def test_escapes(self): myjitdriver = JitDriver(greens = [], reds = ['n', 'parent']) class Parent(object): def __init__(self, node): self.node = node def g(x): pass def f(n): node = self._new() node.value = 3 parent = Parent(node) while n > 0: myjitdriver.can_enter_jit(n=n, parent=parent) myjitdriver.jit_merge_point(n=n, parent=parent) node = parent.node g(node) newnode = self._new() newnode.value = 3 parent = Parent(newnode) n -= 1 return parent.node.value res = self.meta_interp(f, [10], policy=StopAtXPolicy(g)) assert res == 3 self.check_loops(**{self._new_op: 1})
def test_two_loops_with_escaping_virtual(self): myjitdriver = JitDriver(greens = [], reds = ['n', 'node']) def externfn(node): llop.debug_print(lltype.Void, node) return node.value * 2 def f(n): node = self._new() node.value = 0 node.extra = 0 while n > 0: myjitdriver.can_enter_jit(n=n, node=node) myjitdriver.jit_merge_point(n=n, node=node) next = self._new() next.value = node.value + n next.extra = node.extra + 1 if next.extra == 4: next.value = externfn(next) next.extra = 0 node = next n -= 1 return node.value res = self.meta_interp(f, [10], policy=StopAtXPolicy(externfn)) assert res == f(10) self.check_loop_count(2) self.check_loops(**{self._new_op: 2}) # XXX was 1 self.check_loops(int_mul=0, call=1)
def test_external_read_sometimes_recursive(self): jitdriver = JitDriver(greens=[], reds=['frame', 'rec'], virtualizables=['frame']) class Frame(object): _virtualizable2_ = ['x', 'y'] class SomewhereElse: pass somewhere_else = SomewhereElse() def g(rec): somewhere_else.counter += 1 if somewhere_else.counter == 70: frame = somewhere_else.top_frame result1 = frame.y # external read result2 = frame.back.y # external read debug_print(lltype.Void, '-+-+-+-+- external read:', result1, result2) assert result1 == 13 assert result2 == 1023 result = 2 elif rec: res = f(4, False) assert res == 0 or res == -1 result = 1 else: result = 1 return result def f(n, rec): frame = Frame() frame.x = n frame.y = 10 + 1000 * rec frame.back = somewhere_else.top_frame somewhere_else.top_frame = frame while frame.x > 0: jitdriver.can_enter_jit(frame=frame, rec=rec) jitdriver.jit_merge_point(frame=frame, rec=rec) frame.x -= g(rec) frame.y += 1 somewhere_else.top_frame = frame.back return frame.x def main(n): somewhere_else.counter = 0 somewhere_else.top_frame = None return f(n, True) res = self.meta_interp(main, [123], policy=StopAtXPolicy(g)) assert res == main(123)
def test_directly_call_assembler_virtualizable_force_blackhole(self): class Thing(object): def __init__(self, val): self.val = val class Frame(object): _virtualizable2_ = ['thing'] driver = JitDriver(greens=['codeno'], reds=['frame', 'i'], virtualizables=['frame'], get_printable_location=lambda codeno: str(codeno), can_inline=lambda codeno: False) class SomewhereElse(object): pass somewhere_else = SomewhereElse() def change(newthing, arg): print arg if arg > 30: somewhere_else.frame.thing = newthing arg = 13 return arg def main(codeno): frame = Frame() somewhere_else.frame = frame frame.thing = Thing(0) portal(codeno, frame) return frame.thing.val def portal(codeno, frame): i = 0 while i < 10: driver.can_enter_jit(frame=frame, codeno=codeno, i=i) driver.jit_merge_point(frame=frame, codeno=codeno, i=i) nextval = frame.thing.val if codeno == 0: subframe = Frame() subframe.thing = Thing(nextval) nextval = portal(1, subframe) else: nextval = change(Thing(13), frame.thing.val) frame.thing = Thing(nextval + 1) i += 1 return frame.thing.val res = self.meta_interp(main, [0], inline=True, policy=StopAtXPolicy(change)) assert res == main(0)
def test_bridge_from_guard_exception(self): myjitdriver = JitDriver(greens=[], reds=['n']) def check(n): if n % 2: raise ValueError def f(n): while n > 0: myjitdriver.can_enter_jit(n=n) myjitdriver.jit_merge_point(n=n) try: check(n) n -= 1 except ValueError: n -= 3 return n res = self.meta_interp(f, [20], policy=StopAtXPolicy(check)) assert res == f(20) res = self.meta_interp(f, [21], policy=StopAtXPolicy(check)) assert res == f(21)
def test_external_read_sometimes_changing_virtuals(self): jitdriver = JitDriver(greens=[], reds=['frame'], virtualizables=['frame']) class Frame(object): _virtualizable2_ = ['x', 'y'] class Y: pass class SomewhereElse: pass somewhere_else = SomewhereElse() def g(): somewhere_else.counter += 1 if somewhere_else.counter == 70: y = somewhere_else.top_frame.y # external read debug_print(lltype.Void, '-+-+-+-+- external virtual write') assert y.num == 123 y.num += 2 else: y = None return y def f(n): frame = Frame() frame.x = n somewhere_else.counter = 0 somewhere_else.top_frame = frame while frame.x > 0: jitdriver.can_enter_jit(frame=frame) jitdriver.jit_merge_point(frame=frame) frame.y = y = Y() y.num = 123 result = g() if frame.y is not y: return -660 if result: if result is not y: return -661 if y.num != 125: return -662 frame.y = None frame.x -= 1 return frame.x res = self.meta_interp(f, [123], policy=StopAtXPolicy(g)) assert res == f(123)
def test_external_read_sometimes_with_exception(self): jitdriver = JitDriver(greens=[], reds=['frame'], virtualizables=['frame']) class Frame(object): _virtualizable2_ = ['x', 'y'] class FooBarError(Exception): pass class SomewhereElse: pass somewhere_else = SomewhereElse() def g(): somewhere_else.counter += 1 if somewhere_else.counter == 70: result = somewhere_else.top_frame.y # external read debug_print(lltype.Void, '-+-+-+-+- external read:', result) assert result == 79 raise FooBarError else: result = 1 return result def f(n): frame = Frame() frame.x = n frame.y = 10 somewhere_else.counter = 0 somewhere_else.top_frame = frame try: while frame.x > 0: jitdriver.can_enter_jit(frame=frame) jitdriver.jit_merge_point(frame=frame) frame.x -= g() frame.y += 1 except FooBarError: pass return frame.x res = self.meta_interp(f, [123], policy=StopAtXPolicy(g)) assert res == f(123)
def test_list_escapes(self): py.test.skip("unsupported") jitdriver = JitDriver(greens = [], reds = ['n']) def g(l): pass def f(n): while n > 0: jitdriver.can_enter_jit(n=n) jitdriver.jit_merge_point(n=n) l = [] l.append(3) g(l) n -= 1 return n res = self.meta_interp(f, [30], policy=StopAtXPolicy(g)) assert res == 0 self.check_loops(append=1)
def test_bug_1(self): myjitdriver = JitDriver(greens=[], reds=['n', 'i', 'stack']) def opaque(n, i): if n == 1 and i == 19: for j in range(20): res = f(0) # recurse repeatedly, 20 times assert res == 0 def f(n): stack = [n] i = 0 while i < 20: myjitdriver.can_enter_jit(n=n, i=i, stack=stack) myjitdriver.jit_merge_point(n=n, i=i, stack=stack) opaque(n, i) i += 1 return stack.pop() res = self.meta_interp(f, [1], optimizer=OPTIMIZER_SIMPLE, repeat=2, policy=StopAtXPolicy(opaque)) assert res == 1