/pypy/jit/metainterp/test/test_ajit.py
Python | 3934 lines | 3867 code | 50 blank | 17 comment | 73 complexity | b97d371c2bed7e19b9425017a976db19 MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- import math
- import sys
- import py
- from pypy import conftest
- from pypy.jit.codewriter import longlong
- from pypy.jit.codewriter.policy import JitPolicy, StopAtXPolicy
- from pypy.jit.metainterp import pyjitpl, history
- from pypy.jit.metainterp.optimizeopt import ALL_OPTS_DICT
- from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin, noConst
- from pypy.jit.metainterp.typesystem import LLTypeHelper, OOTypeHelper
- from pypy.jit.metainterp.warmspot import get_stats
- from pypy.rlib import rerased
- from pypy.rlib.jit import (JitDriver, we_are_jitted, hint, dont_look_inside,
- loop_invariant, elidable, promote, jit_debug, assert_green,
- AssertGreenFailed, unroll_safe, current_trace_length, look_inside_iff,
- isconstant, isvirtual, promote_string, set_param, record_known_class)
- from pypy.rlib.longlong2float import float2longlong, longlong2float
- from pypy.rlib.rarithmetic import ovfcheck, is_valid_int
- from pypy.rpython.lltypesystem import lltype, llmemory, rffi
- from pypy.rpython.ootypesystem import ootype
- class BasicTests:
- def test_basic(self):
- def f(x, y):
- return x + y
- res = self.interp_operations(f, [40, 2])
- assert res == 42
- def test_basic_inst(self):
- class A:
- pass
- def f(n):
- a = A()
- a.x = n
- return a.x
- res = self.interp_operations(f, [42])
- assert res == 42
- def test_uint_floordiv(self):
- from pypy.rlib.rarithmetic import r_uint
- def f(a, b):
- a = r_uint(a)
- b = r_uint(b)
- return a/b
- res = self.interp_operations(f, [-4, 3])
- assert res == long(r_uint(-4)) // 3
- def test_direct_call(self):
- def g(n):
- return n + 2
- def f(a, b):
- return g(a) + g(b)
- res = self.interp_operations(f, [8, 98])
- assert res == 110
- def test_direct_call_with_guard(self):
- def g(n):
- if n < 0:
- return 0
- return n + 2
- def f(a, b):
- return g(a) + g(b)
- res = self.interp_operations(f, [8, 98])
- assert res == 110
- def test_loop_1(self):
- myjitdriver = JitDriver(greens = [], reds = ['x', 'y', '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 += x
- y -= 1
- return res
- res = self.meta_interp(f, [6, 7])
- assert res == 42
- self.check_trace_count(1)
- self.check_resops({'jump': 1, 'int_gt': 2, 'int_add': 2,
- 'guard_true': 2, 'int_sub': 2})
- if self.basic:
- found = 0
- for op in get_stats().get_all_loops()[0]._all_operations():
- if op.getopname() == 'guard_true':
- liveboxes = op.getfailargs()
- assert len(liveboxes) == 3
- for box in liveboxes:
- assert isinstance(box, history.BoxInt)
- found += 1
- assert found == 2
- def test_loop_variant_mul1(self):
- myjitdriver = JitDriver(greens = [], reds = ['y', 'res', 'x'])
- 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 += x * x
- x += 1
- res += x * x
- y -= 1
- return res
- res = self.meta_interp(f, [6, 7])
- assert res == 1323
- self.check_trace_count(1)
- self.check_simple_loop(int_mul=1)
- def test_loop_variant_mul_ovf(self):
- myjitdriver = JitDriver(greens = [], reds = ['y', 'res', 'x'])
- 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 += ovfcheck(x * x)
- x += 1
- res += ovfcheck(x * x)
- y -= 1
- return res
- res = self.meta_interp(f, [6, 7])
- assert res == 1323
- self.check_trace_count(1)
- self.check_simple_loop(int_mul_ovf=1)
- def test_loop_invariant_mul1(self):
- myjitdriver = JitDriver(greens = [], reds = ['y', 'res', 'x'])
- 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 += x * x
- y -= 1
- return res
- res = self.meta_interp(f, [6, 7])
- assert res == 252
- self.check_trace_count(1)
- self.check_simple_loop(int_mul=0)
- self.check_resops({'jump': 1, 'int_gt': 2, 'int_add': 2,
- 'int_mul': 1, 'guard_true': 2, 'int_sub': 2})
- def test_loop_invariant_mul_ovf1(self):
- myjitdriver = JitDriver(greens = [], reds = ['y', 'res', 'x'])
- 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)
- b = y * 2
- res += ovfcheck(x * x) + b
- y -= 1
- return res
- res = self.meta_interp(f, [6, 7])
- assert res == 308
- self.check_trace_count(1)
- self.check_simple_loop(int_mul_ovf=0)
- self.check_resops({'jump': 1, 'int_lshift': 2, 'int_gt': 2,
- 'int_mul_ovf': 1, 'int_add': 4,
- 'guard_true': 2, 'guard_no_overflow': 1,
- 'int_sub': 2})
- def test_loop_invariant_mul_bridge1(self):
- myjitdriver = JitDriver(greens = [], reds = ['y', 'res', 'x', 'n'])
- def f(x, y, n):
- res = 0
- while y > 0:
- myjitdriver.can_enter_jit(x=x, y=y, n=n, res=res)
- myjitdriver.jit_merge_point(x=x, y=y, n=n, res=res)
- res += x * x
- if y<n:
- x += 1
- y -= 1
- return res
- res = self.meta_interp(f, [6, 32, 16])
- assert res == 3427
- self.check_trace_count(3)
- def test_loop_invariant_mul_bridge_maintaining1(self):
- myjitdriver = JitDriver(greens = [], reds = ['y', 'res', 'x', 'n'])
- def f(x, y, n):
- res = 0
- while y > 0:
- myjitdriver.can_enter_jit(x=x, y=y, res=res, n=n)
- myjitdriver.jit_merge_point(x=x, y=y, res=res, n=n)
- res += x * x
- if y<n:
- res += 1
- y -= 1
- return res
- res = self.meta_interp(f, [6, 32, 16])
- assert res == 1167
- self.check_trace_count(3)
- self.check_resops(int_mul=3)
- def test_loop_invariant_mul_bridge_maintaining2(self):
- myjitdriver = JitDriver(greens = [], reds = ['y', 'res', 'x', 'n'])
- def f(x, y, n):
- res = 0
- while y > 0:
- myjitdriver.can_enter_jit(x=x, y=y, res=res, n=n)
- myjitdriver.jit_merge_point(x=x, y=y, res=res, n=n)
- z = x * x
- res += z
- if y<n:
- res += z
- y -= 1
- return res
- res = self.meta_interp(f, [6, 32, 16])
- assert res == 1692
- self.check_trace_count(3)
- self.check_resops(int_mul=3)
- def test_loop_invariant_mul_bridge_maintaining3(self):
- myjitdriver = JitDriver(greens = [], reds = ['y', 'res', 'x', 'm'])
- def f(x, y, m):
- res = 0
- while y > 0:
- myjitdriver.can_enter_jit(x=x, y=y, res=res, m=m)
- myjitdriver.jit_merge_point(x=x, y=y, res=res, m=m)
- z = x * x
- res += z
- if y<m:
- res += z
- y -= 1
- return res
- res = self.meta_interp(f, [6, 32, 16])
- assert res == 1692
- self.check_trace_count(3)
- self.check_resops({'int_lt': 2, 'int_gt': 4, 'guard_false': 2,
- 'guard_true': 4, 'int_sub': 4, 'jump': 3,
- 'int_mul': 3, 'int_add': 4})
- def test_loop_invariant_mul_ovf2(self):
- myjitdriver = JitDriver(greens = [], reds = ['y', 'res', 'x'])
- 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)
- b = y * 2
- try:
- res += ovfcheck(x * x) + b
- except OverflowError:
- res += 1
- y -= 1
- return res
- res = self.meta_interp(f, [sys.maxint, 7])
- assert res == f(sys.maxint, 7)
- self.check_trace_count(1)
- res = self.meta_interp(f, [6, 7])
- assert res == 308
- def test_loop_invariant_mul_bridge_ovf1(self):
- myjitdriver = JitDriver(greens = [], reds = ['y', 'res', 'x1', 'x2'])
- def f(x1, x2, y):
- res = 0
- while y > 0:
- myjitdriver.can_enter_jit(x1=x1, x2=x2, y=y, res=res)
- myjitdriver.jit_merge_point(x1=x1, x2=x2, y=y, res=res)
- try:
- res += ovfcheck(x1 * x1)
- except OverflowError:
- res += 1
- if y<32 and (y>>2)&1==0:
- x1, x2 = x2, x1
- y -= 1
- return res
- res = self.meta_interp(f, [6, sys.maxint, 48])
- assert res == f(6, sys.maxint, 48)
- def test_loop_invariant_mul_bridge_ovf2(self):
- myjitdriver = JitDriver(greens = [], reds = ['y', 'res', 'x1', 'x2', 'n'])
- def f(x1, x2, n, y):
- res = 0
- while y > 0:
- myjitdriver.can_enter_jit(x1=x1, x2=x2, y=y, res=res, n=n)
- myjitdriver.jit_merge_point(x1=x1, x2=x2, y=y, res=res, n=n)
- try:
- res += ovfcheck(x1 * x1)
- except OverflowError:
- res += 1
- y -= 1
- if y&4 == 0:
- x1, x2 = x2, x1
- return res
- res = self.meta_interp(f, [6, sys.maxint, 32, 48])
- assert res == f(6, sys.maxint, 32, 48)
- res = self.meta_interp(f, [sys.maxint, 6, 32, 48])
- assert res == f(sys.maxint, 6, 32, 48)
- def test_loop_invariant_intbox(self):
- myjitdriver = JitDriver(greens = [], reds = ['y', 'res', 'x'])
- class I:
- __slots__ = 'intval'
- _immutable_ = True
- def __init__(self, intval):
- self.intval = intval
- def f(i, y):
- res = 0
- x = I(i)
- while y > 0:
- myjitdriver.can_enter_jit(x=x, y=y, res=res)
- myjitdriver.jit_merge_point(x=x, y=y, res=res)
- res += x.intval * x.intval
- y -= 1
- return res
- res = self.meta_interp(f, [6, 7])
- assert res == 252
- self.check_trace_count(1)
- self.check_resops({'jump': 1, 'int_gt': 2, 'int_add': 2,
- 'getfield_gc_pure': 1, 'int_mul': 1,
- 'guard_true': 2, 'int_sub': 2})
- def test_loops_are_transient(self):
- import gc, weakref
- myjitdriver = JitDriver(greens = [], reds = ['x', 'y', '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 += x
- if y%2:
- res *= 2
- y -= 1
- return res
- wr_loops = []
- old_init = history.TreeLoop.__init__.im_func
- try:
- def track_init(self, name):
- old_init(self, name)
- wr_loops.append(weakref.ref(self))
- history.TreeLoop.__init__ = track_init
- res = self.meta_interp(f, [6, 15], no_stats=True)
- finally:
- history.TreeLoop.__init__ = old_init
- assert res == f(6, 15)
- gc.collect()
- assert not [wr for wr in wr_loops if wr()]
- def test_string(self):
- def f(n):
- bytecode = 'adlfkj' + chr(n)
- if n < len(bytecode):
- return bytecode[n]
- else:
- return "?"
- res = self.interp_operations(f, [1])
- assert res == ord("d") # XXX should be "d"
- res = self.interp_operations(f, [6])
- assert res == 6
- res = self.interp_operations(f, [42])
- assert res == ord("?")
- def test_chr2str(self):
- def f(n):
- s = chr(n)
- return s[0]
- res = self.interp_operations(f, [3])
- assert res == 3
- def test_unicode(self):
- def f(n):
- bytecode = u'adlfkj' + unichr(n)
- if n < len(bytecode):
- return bytecode[n]
- else:
- return u"?"
- res = self.interp_operations(f, [1])
- assert res == ord(u"d") # XXX should be "d"
- res = self.interp_operations(f, [6])
- assert res == 6
- res = self.interp_operations(f, [42])
- assert res == ord(u"?")
- def test_char_in_constant_string(self):
- def g(string):
- return '\x00' in string
- def f():
- if g('abcdef'): return -60
- if not g('abc\x00ef'): return -61
- return 42
- res = self.interp_operations(f, [])
- assert res == 42
- self.check_operations_history({'finish': 1}) # nothing else
- def test_residual_call(self):
- @dont_look_inside
- def externfn(x, y):
- return x * y
- def f(n):
- return externfn(n, n+1)
- res = self.interp_operations(f, [6])
- assert res == 42
- self.check_operations_history(int_add=1, int_mul=0, call=1, guard_no_exception=0)
- def test_residual_call_elidable(self):
- def externfn(x, y):
- return x * y
- externfn._elidable_function_ = True
- def f(n):
- promote(n)
- return externfn(n, n+1)
- res = self.interp_operations(f, [6])
- assert res == 42
- # CALL_PURE is not recorded in the history if all-constant args
- self.check_operations_history(int_add=0, int_mul=0,
- call=0, call_pure=0)
- def test_residual_call_elidable_1(self):
- @elidable
- def externfn(x, y):
- return x * y
- def f(n):
- return externfn(n, n+1)
- res = self.interp_operations(f, [6])
- assert res == 42
- # CALL_PURE is recorded in the history if not-all-constant args
- self.check_operations_history(int_add=1, int_mul=0,
- call=0, call_pure=1)
- def test_residual_call_elidable_2(self):
- myjitdriver = JitDriver(greens = [], reds = ['n'])
- @elidable
- def externfn(x):
- return x - 1
- def f(n):
- while n > 0:
- myjitdriver.can_enter_jit(n=n)
- myjitdriver.jit_merge_point(n=n)
- n = externfn(n)
- return n
- res = self.meta_interp(f, [7])
- assert res == 0
- # CALL_PURE is recorded in the history, but turned into a CALL
- # by optimizeopt.py
- self.check_resops(call_pure=0, call=2, int_sub=0)
- def test_constfold_call_elidable(self):
- myjitdriver = JitDriver(greens = ['m'], reds = ['n'])
- @elidable
- def externfn(x):
- return x - 3
- def f(n, m):
- while n > 0:
- myjitdriver.can_enter_jit(n=n, m=m)
- myjitdriver.jit_merge_point(n=n, m=m)
- n -= externfn(m)
- return n
- res = self.meta_interp(f, [21, 5])
- assert res == -1
- # the CALL_PURE is constant-folded away by optimizeopt.py
- self.check_resops(call_pure=0, call=0, int_sub=2)
- def test_constfold_call_elidable_2(self):
- myjitdriver = JitDriver(greens = ['m'], reds = ['n'])
- @elidable
- def externfn(x):
- return x - 3
- class V:
- def __init__(self, value):
- self.value = value
- def f(n, m):
- while n > 0:
- myjitdriver.can_enter_jit(n=n, m=m)
- myjitdriver.jit_merge_point(n=n, m=m)
- v = V(m)
- n -= externfn(v.value)
- return n
- res = self.meta_interp(f, [21, 5])
- assert res == -1
- # the CALL_PURE is constant-folded away by optimizeopt.py
- self.check_resops(call_pure=0, call=0, int_sub=2)
- def test_elidable_function_returning_object(self):
- myjitdriver = JitDriver(greens = ['m'], reds = ['n'])
- class V:
- def __init__(self, x):
- self.x = x
- v1 = V(1)
- v2 = V(2)
- @elidable
- def externfn(x):
- if x:
- return v1
- else:
- return v2
- def f(n, m):
- while n > 0:
- myjitdriver.can_enter_jit(n=n, m=m)
- myjitdriver.jit_merge_point(n=n, m=m)
- m = V(m).x
- n -= externfn(m).x + externfn(m + m - m).x
- return n
- res = self.meta_interp(f, [21, 5])
- assert res == -1
- # the CALL_PURE is constant-folded away by optimizeopt.py
- self.check_resops(call_pure=0, call=0, getfield_gc=1, int_sub=2)
- def test_elidable_raising(self):
- myjitdriver = JitDriver(greens = ['m'], reds = ['n'])
- @elidable
- def externfn(x):
- if x <= 0:
- raise ValueError
- return x - 1
- def f(n, m):
- while n > 0:
- myjitdriver.can_enter_jit(n=n, m=m)
- myjitdriver.jit_merge_point(n=n, m=m)
- try:
- n -= externfn(m)
- except ValueError:
- n -= 1
- return n
- res = self.meta_interp(f, [22, 6])
- assert res == -3
- # the CALL_PURE is constant-folded away during tracing
- self.check_resops(call_pure=0, call=0, int_sub=2)
- #
- res = self.meta_interp(f, [22, -5])
- assert res == 0
- # raises: becomes CALL and is not constant-folded away
- self.check_resops(call_pure=0, call=2, int_sub=2)
- def test_elidable_raising_2(self):
- myjitdriver = JitDriver(greens = ['m'], reds = ['n'])
- @elidable
- def externfn(x):
- if x <= 0:
- raise ValueError
- return x - 1
- def f(n, m):
- while n > 0:
- myjitdriver.can_enter_jit(n=n, m=m)
- myjitdriver.jit_merge_point(n=n, m=m)
- try:
- n -= externfn(noConst(m))
- except ValueError:
- n -= 1
- return n
- res = self.meta_interp(f, [22, 6])
- assert res == -3
- # the CALL_PURE is constant-folded away by optimizeopt.py
- self.check_resops(call_pure=0, call=0, int_sub=2)
- #
- res = self.meta_interp(f, [22, -5])
- assert res == 0
- # raises: becomes CALL and is not constant-folded away
- self.check_resops(call_pure=0, call=2, int_sub=2)
- def test_constant_across_mp(self):
- myjitdriver = JitDriver(greens = [], reds = ['n'])
- class X(object):
- pass
- def f(n):
- while n > -100:
- myjitdriver.can_enter_jit(n=n)
- myjitdriver.jit_merge_point(n=n)
- x = X()
- x.arg = 5
- if n <= 0: break
- n -= x.arg
- x.arg = 6 # prevents 'x.arg' from being annotated as constant
- return n
- res = self.meta_interp(f, [31])
- assert res == -4
- 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_resops(int_mul=2, int_mod=0)
- def test_we_are_jitted(self):
- myjitdriver = JitDriver(greens = [], reds = ['y'])
- def f(y):
- while y >= 0:
- myjitdriver.can_enter_jit(y=y)
- myjitdriver.jit_merge_point(y=y)
- if we_are_jitted():
- x = 1
- else:
- x = 10
- y -= x
- return y
- assert f(55) == -5
- res = self.meta_interp(f, [55])
- assert res == -1
- def test_confirm_enter_jit(self):
- def confirm_enter_jit(x, y):
- return x <= 5
- myjitdriver = JitDriver(greens = ['x'], reds = ['y'],
- confirm_enter_jit = confirm_enter_jit)
- def f(x, y):
- while y >= 0:
- myjitdriver.can_enter_jit(x=x, y=y)
- myjitdriver.jit_merge_point(x=x, y=y)
- y -= x
- return y
- #
- res = self.meta_interp(f, [10, 84])
- assert res == -6
- self.check_trace_count(0)
- #
- res = self.meta_interp(f, [3, 19])
- assert res == -2
- self.check_trace_count(1)
- def test_can_never_inline(self):
- def can_never_inline(x):
- return x > 50
- myjitdriver = JitDriver(greens = ['x'], reds = ['y'],
- can_never_inline = can_never_inline)
- @dont_look_inside
- def marker():
- pass
- def f(x, y):
- while y >= 0:
- myjitdriver.can_enter_jit(x=x, y=y)
- myjitdriver.jit_merge_point(x=x, y=y)
- x += 1
- if x == 4 or x == 61:
- marker()
- y -= x
- return y
- #
- res = self.meta_interp(f, [3, 6], repeat=7, function_threshold=0)
- assert res == 6 - 4 - 5
- self.check_history(call=0) # because the trace starts in the middle
- #
- res = self.meta_interp(f, [60, 84], repeat=7)
- assert res == 84 - 61 - 62
- self.check_history(call=1) # because the trace starts immediately
- def test_unroll_one_loop_iteration(self):
- def unroll(code):
- return code == 0
- myjitdriver = JitDriver(greens = ['code'],
- reds = ['loops', 'inner_loops', 's'],
- should_unroll_one_iteration=unroll)
- def f(code, loops, inner_loops):
- s = 0
- while loops > 0:
- myjitdriver.jit_merge_point(code=code, loops=loops,
- inner_loops=inner_loops, s=s)
- if code == 1:
- s += f(0, inner_loops, 0)
- loops -= 1
- s += 1
- return s
- res = self.meta_interp(f, [1, 4, 1], enable_opts="", inline=True)
- assert res == f(1, 4, 1)
- self.check_history(call_assembler=0)
- res = self.meta_interp(f, [1, 4, 2], enable_opts="", inline=True)
- assert res == f(1, 4, 2)
- self.check_history(call_assembler=1)
- def test_format(self):
- def f(n):
- return len("<%d>" % n)
- res = self.interp_operations(f, [421])
- assert res == 5
- def test_switch(self):
- def f(n):
- if n == -5: return 12
- elif n == 2: return 51
- elif n == 7: return 1212
- else: return 42
- res = self.interp_operations(f, [7])
- assert res == 1212
- res = self.interp_operations(f, [12311])
- assert res == 42
- def test_r_uint(self):
- from pypy.rlib.rarithmetic import r_uint
- myjitdriver = JitDriver(greens = [], reds = ['y'])
- def f(y):
- y = r_uint(y)
- while y > 0:
- myjitdriver.can_enter_jit(y=y)
- myjitdriver.jit_merge_point(y=y)
- y -= 1
- return y
- res = self.meta_interp(f, [10])
- assert res == 0
- def test_uint_operations(self):
- from pypy.rlib.rarithmetic import r_uint
- def f(n):
- return ((r_uint(n) - 123) >> 1) <= r_uint(456)
- res = self.interp_operations(f, [50])
- assert res == False
- self.check_operations_history(int_rshift=0, uint_rshift=1,
- int_le=0, uint_le=1,
- int_sub=1)
- def test_uint_condition(self):
- from pypy.rlib.rarithmetic import r_uint
- def f(n):
- if ((r_uint(n) - 123) >> 1) <= r_uint(456):
- return 24
- else:
- return 12
- res = self.interp_operations(f, [50])
- assert res == 12
- self.check_operations_history(int_rshift=0, uint_rshift=1,
- int_le=0, uint_le=1,
- int_sub=1)
- def test_int_between(self):
- #
- def check(arg1, arg2, arg3, expect_result, **expect_operations):
- from pypy.rpython.lltypesystem import lltype
- from pypy.rpython.lltypesystem.lloperation import llop
- loc = locals().copy()
- exec py.code.Source("""
- def f(n, m, p):
- arg1 = %(arg1)s
- arg2 = %(arg2)s
- arg3 = %(arg3)s
- return llop.int_between(lltype.Bool, arg1, arg2, arg3)
- """ % locals()).compile() in loc
- res = self.interp_operations(loc['f'], [5, 6, 7])
- assert res == expect_result
- self.check_operations_history(expect_operations)
- #
- check('n', 'm', 'p', True, int_sub=2, uint_lt=1)
- check('n', 'p', 'm', False, int_sub=2, uint_lt=1)
- #
- check('n', 'm', 6, False, int_sub=2, uint_lt=1)
- #
- check('n', 4, 'p', False, int_sub=2, uint_lt=1)
- check('n', 5, 'p', True, int_sub=2, uint_lt=1)
- check('n', 8, 'p', False, int_sub=2, uint_lt=1)
- #
- check('n', 6, 7, True, int_sub=2, uint_lt=1)
- #
- check(-2, 'n', 'p', True, int_sub=2, uint_lt=1)
- check(-2, 'm', 'p', True, int_sub=2, uint_lt=1)
- check(-2, 'p', 'm', False, int_sub=2, uint_lt=1)
- #check(0, 'n', 'p', True, uint_lt=1) xxx implement me
- #check(0, 'm', 'p', True, uint_lt=1)
- #check(0, 'p', 'm', False, uint_lt=1)
- #
- check(2, 'n', 6, True, int_sub=1, uint_lt=1)
- check(2, 'm', 6, False, int_sub=1, uint_lt=1)
- check(2, 'p', 6, False, int_sub=1, uint_lt=1)
- check(5, 'n', 6, True, int_eq=1) # 6 == 5+1
- check(5, 'm', 6, False, int_eq=1) # 6 == 5+1
- #
- check(2, 6, 'm', False, int_sub=1, uint_lt=1)
- check(2, 6, 'p', True, int_sub=1, uint_lt=1)
- #
- check(2, 40, 6, False)
- check(2, 40, 60, True)
- def test_getfield(self):
- class A:
- pass
- a1 = A()
- a1.foo = 5
- a2 = A()
- a2.foo = 8
- def f(x):
- if x > 5:
- a = a1
- else:
- a = a2
- return a.foo * x
- res = self.interp_operations(f, [42])
- assert res == 210
- self.check_operations_history(getfield_gc=1)
- def test_getfield_immutable(self):
- class A:
- _immutable_ = True
- a1 = A()
- a1.foo = 5
- a2 = A()
- a2.foo = 8
- def f(x):
- if x > 5:
- a = a1
- else:
- a = a2
- return a.foo * x
- res = self.interp_operations(f, [42])
- assert res == 210
- self.check_operations_history(getfield_gc=0)
- def test_setfield_bool(self):
- class A:
- def __init__(self):
- self.flag = True
- myjitdriver = JitDriver(greens = [], reds = ['n', 'obj'])
- def f(n):
- obj = A()
- res = False
- while n > 0:
- myjitdriver.can_enter_jit(n=n, obj=obj)
- myjitdriver.jit_merge_point(n=n, obj=obj)
- obj.flag = False
- n -= 1
- return res
- res = self.meta_interp(f, [7])
- assert type(res) == bool
- assert not res
- def test_switch_dict(self):
- def f(x):
- if x == 1: return 61
- elif x == 2: return 511
- elif x == 3: return -22
- elif x == 4: return 81
- elif x == 5: return 17
- elif x == 6: return 54
- elif x == 7: return 987
- elif x == 8: return -12
- elif x == 9: return 321
- return -1
- res = self.interp_operations(f, [5])
- assert res == 17
- res = self.interp_operations(f, [15])
- assert res == -1
- def test_int_add_ovf(self):
- def f(x, y):
- try:
- return ovfcheck(x + y)
- except OverflowError:
- return -42
- res = self.interp_operations(f, [-100, 2])
- assert res == -98
- res = self.interp_operations(f, [1, sys.maxint])
- assert res == -42
- def test_int_sub_ovf(self):
- def f(x, y):
- try:
- return ovfcheck(x - y)
- except OverflowError:
- return -42
- res = self.interp_operations(f, [-100, 2])
- assert res == -102
- res = self.interp_operations(f, [1, -sys.maxint])
- assert res == -42
- def test_int_mul_ovf(self):
- def f(x, y):
- try:
- return ovfcheck(x * y)
- except OverflowError:
- return -42
- res = self.interp_operations(f, [-100, 2])
- assert res == -200
- res = self.interp_operations(f, [-3, sys.maxint//2])
- assert res == -42
- def test_mod_ovf(self):
- myjitdriver = JitDriver(greens = [], reds = ['n', 'x', 'y'])
- def f(n, x, y):
- while n > 0:
- myjitdriver.can_enter_jit(x=x, y=y, n=n)
- myjitdriver.jit_merge_point(x=x, y=y, n=n)
- n -= ovfcheck(x % y)
- return n
- res = self.meta_interp(f, [20, 1, 2])
- assert res == 0
- self.check_resops(call=0)
- def test_abs(self):
- myjitdriver = JitDriver(greens = [], reds = ['i', 't'])
- def f(i):
- t = 0
- while i < 10:
- myjitdriver.can_enter_jit(i=i, t=t)
- myjitdriver.jit_merge_point(i=i, t=t)
- t += abs(i)
- i += 1
- return t
- res = self.meta_interp(f, [-5])
- assert res == 5+4+3+2+1+0+1+2+3+4+5+6+7+8+9
- def test_float(self):
- myjitdriver = JitDriver(greens = [], reds = ['x', 'y', 'res'])
- def f(x, y):
- x = float(x)
- y = float(y)
- res = 0.0
- while y > 0.0:
- myjitdriver.can_enter_jit(x=x, y=y, res=res)
- myjitdriver.jit_merge_point(x=x, y=y, res=res)
- res += x
- y -= 1.0
- return res
- res = self.meta_interp(f, [6, 7])
- assert res == 42.0
- self.check_trace_count(1)
- self.check_resops({'jump': 1, 'float_gt': 2, 'float_add': 2,
- 'float_sub': 2, 'guard_true': 2})
- def test_print(self):
- myjitdriver = JitDriver(greens = [], reds = ['n'])
- def f(n):
- while n > 0:
- myjitdriver.can_enter_jit(n=n)
- myjitdriver.jit_merge_point(n=n)
- print n
- n -= 1
- return n
- res = self.meta_interp(f, [7])
- assert res == 0
- def test_bridge_from_interpreter_1(self):
- mydriver = JitDriver(reds = ['n'], greens = [])
- def f(n):
- while n > 0:
- mydriver.can_enter_jit(n=n)
- mydriver.jit_merge_point(n=n)
- n -= 1
- self.meta_interp(f, [20], repeat=7)
- # the loop and the entry path as a single trace
- self.check_jitcell_token_count(1)
- # we get:
- # ENTER - compile the new loop and the entry bridge
- # ENTER - compile the leaving path
- self.check_enter_count(2)
- def test_bridge_from_interpreter_2(self):
- # one case for backend - computing of framesize on guard failure
- mydriver = JitDriver(reds = ['n'], greens = [])
- glob = [1]
- def f(n):
- while n > 0:
- mydriver.can_enter_jit(n=n)
- mydriver.jit_merge_point(n=n)
- if n == 17 and glob[0]:
- glob[0] = 0
- x = n + 1
- y = n + 2
- z = n + 3
- k = n + 4
- n -= 1
- n += x + y + z + k
- n -= x + y + z + k
- n -= 1
- self.meta_interp(f, [20], repeat=7)
- def test_bridge_from_interpreter_3(self):
- # one case for backend - computing of framesize on guard failure
- mydriver = JitDriver(reds = ['n', 'x', 'y', 'z', 'k'], greens = [])
- class Global:
- pass
- glob = Global()
- def f(n):
- glob.x = 1
- x = 0
- y = 0
- z = 0
- k = 0
- while n > 0:
- mydriver.can_enter_jit(n=n, x=x, y=y, z=z, k=k)
- mydriver.jit_merge_point(n=n, x=x, y=y, z=z, k=k)
- x += 10
- y += 3
- z -= 15
- k += 4
- if n == 17 and glob.x:
- glob.x = 0
- x += n + 1
- y += n + 2
- z += n + 3
- k += n + 4
- n -= 1
- n -= 1
- return x + 2*y + 3*z + 5*k + 13*n
- res = self.meta_interp(f, [20], repeat=7)
- assert res == f(20)
- def test_bridge_from_interpreter_4(self):
- jitdriver = JitDriver(reds = ['n', 'k'], greens = [])
- def f(n, k):
- while n > 0:
- jitdriver.can_enter_jit(n=n, k=k)
- jitdriver.jit_merge_point(n=n, k=k)
- if k:
- n -= 2
- else:
- n -= 1
- return n + k
- from pypy.rpython.test.test_llinterp import get_interpreter, clear_tcache
- from pypy.jit.metainterp.warmspot import WarmRunnerDesc
- interp, graph = get_interpreter(f, [0, 0], backendopt=False,
- inline_threshold=0, type_system=self.type_system)
- clear_tcache()
- translator = interp.typer.annotator.translator
- translator.config.translation.gc = "boehm"
- warmrunnerdesc = WarmRunnerDesc(translator,
- CPUClass=self.CPUClass)
- state = warmrunnerdesc.jitdrivers_sd[0].warmstate
- state.set_param_threshold(3) # for tests
- state.set_param_trace_eagerness(0) # for tests
- warmrunnerdesc.finish()
- for n, k in [(20, 0), (20, 1)]:
- interp.eval_graph(graph, [n, k])
- def test_bridge_leaving_interpreter_5(self):
- mydriver = JitDriver(reds = ['n', 'x'], greens = [])
- class Global:
- pass
- glob = Global()
- def f(n):
- x = 0
- glob.x = 1
- while n > 0:
- mydriver.can_enter_jit(n=n, x=x)
- mydriver.jit_merge_point(n=n, x=x)
- glob.x += 1
- x += 3
- n -= 1
- glob.x += 100
- return glob.x + x
- res = self.meta_interp(f, [20], repeat=7)
- assert res == f(20)
- def test_instantiate_classes(self):
- class Base: pass
- class A(Base): foo = 72
- class B(Base): foo = 8
- def f(n):
- if n > 5:
- cls = A
- else:
- cls = B
- return cls().foo
- res = self.interp_operations(f, [3])
- assert res == 8
- res = self.interp_operations(f, [13])
- assert res == 72
- def test_instantiate_does_not_call(self):
- mydriver = JitDriver(reds = ['n', 'x'], greens = [])
- class Base: pass
- class A(Base): foo = 72
- class B(Base): foo = 8
- def f(n):
- x = 0
- while n > 0:
- mydriver.can_enter_jit(n=n, x=x)
- mydriver.jit_merge_point(n=n, x=x)
- if n % 2 == 0:
- cls = A
- else:
- cls = B
- inst = cls()
- x += inst.foo
- n -= 1
- return x
- res = self.meta_interp(f, [20], enable_opts='')
- assert res == f(20)
- self.check_resops(call=0)
- def test_zerodivisionerror(self):
- # test the case of exception-raising operation that is not delegated
- # to the backend at all: ZeroDivisionError
- #
- def f(n):
- assert n >= 0
- try:
- return ovfcheck(5 % n)
- except ZeroDivisionError:
- return -666
- except OverflowError:
- return -777
- res = self.interp_operations(f, [0])
- assert res == -666
- #
- def f(n):
- assert n >= 0
- try:
- return ovfcheck(6 // n)
- except ZeroDivisionError:
- return -667
- except OverflowError:
- return -778
- res = self.interp_operations(f, [0])
- assert res == -667
- def test_div_overflow(self):
- import sys
- from pypy.rpython.lltypesystem.lloperation import llop
- myjitdriver = JitDriver(greens = [], reds = ['x', 'y', '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)
- try:
- res += llop.int_floordiv_ovf(lltype.Signed,
- -sys.maxint-1, x)
- x += 5
- except OverflowError:
- res += 100
- y -= 1
- return res
- res = self.meta_interp(f, [-41, 16])
- assert res == ((-sys.maxint-1) // (-41) +
- (-sys.maxint-1) // (-36) +
- (-sys.maxint-1) // (-31) +
- (-sys.maxint-1) // (-26) +
- (-sys.maxint-1) // (-21) +
- (-sys.maxint-1) // (-16) +
- (-sys.maxint-1) // (-11) +
- (-sys.maxint-1) // (-6) +
- 100 * 8)
- def test_isinstance(self):
- class A:
- pass
- class B(A):
- pass
- @dont_look_inside
- def extern(n):
- if n:
- return A()
- else:
- return B()
- def fn(n):
- obj = extern(n)
- return isinstance(obj, B)
- res = self.interp_operations(fn, [0])
- assert res
- self.check_operations_history(guard_class=1)
- res = self.interp_operations(fn, [1])
- assert not res
- def test_isinstance_2(self):
- driver = JitDriver(greens = [], reds = ['n', 'sum', 'x'])
- class A:
- pass
- class B(A):
- pass
- class C(B):
- pass
- def main():
- return f(5, B()) * 10 + f(5, C()) + f(5, A()) * 100
- def f(n, x):
- sum = 0
- while n > 0:
- driver.can_enter_jit(x=x, n=n, sum=sum)
- driver.jit_merge_point(x=x, n=n, sum=sum)
- if isinstance(x, B):
- sum += 1
- n -= 1
- return sum
- res = self.meta_interp(main, [])
- assert res == 55
- def test_assert_isinstance(self):
- class A:
- pass
- class B(A):
- pass
- def fn(n):
- # this should only be called with n != 0
- if n:
- obj = B()
- obj.a = n
- else:
- obj = A()
- obj.a = 17
- assert isinstance(obj, B)
- return obj.a
- res = self.interp_operations(fn, [1])
- assert res == 1
- self.check_operations_history(guard_class=0)
- if self.type_system == 'ootype':
- self.check_operations_history(instanceof=0)
- def test_r_dict(self):
- from pypy.rlib.objectmodel import r_dict
- class FooError(Exception):
- pass
- def myeq(n, m):
- return n == m
- def myhash(n):
- if n < 0:
- raise FooError
- return -n
- def f(n):
- d = r_dict(myeq, myhash)
- for i in range(10):
- d[i] = i*i
- try:
- return d[n]
- except FooError:
- return 99
- res = self.interp_operations(f, [5])
- assert res == f(5)
- def test_free_object(self):
- import weakref
- from pypy.rlib import rgc
- from pypy.rpython.lltypesystem.lloperation import llop
- myjitdriver = JitDriver(greens = [], reds = ['n', 'x'])
- class X(object):
- pass
- def main(n, x):
- while n > 0:
- myjitdriver.can_enter_jit(n=n, x=x)
- myjitdriver.jit_merge_point(n=n, x=x)
- n -= x.foo
- def g(n):
- x = X()
- x.foo = 2
- main(n, x)
- x.foo = 5
- return weakref.ref(x)
- def f(n):
- r = g(n)
- rgc.collect(); rgc.collect(); rgc.collect()
- return r() is None
- #
- assert f(30) == 1
- res = self.meta_interp(f, [30], no_stats=True)
- assert res == 1
- def test_pass_around(self):
- myjitdriver = JitDriver(greens = [], reds = ['n', 'x'])
- def call():
- pass
- def f(n, x):
- while n > 0:
- myjitdriver.can_enter_jit(n=n, x=x)
- myjitdriver.jit_merge_point(n=n, x=x)
- if n % 2:
- call()
- if n == 8:
- return x
- x = 3
- else:
- x = 5
- n -= 1
- return 0
- self.meta_interp(f, [40, 0])
- def test_const_inputargs(self):
- myjitdriver = JitDriver(greens = ['m'], reds = ['n', 'x'])
- def f(n, x):
- m = 0x7FFFFFFF
- while n > 0:
- myjitdriver.can_enter_jit(m=m, n=n, x=x)
- myjitdriver.jit_merge_point(m=m, n=n, x=x)
- x = 42
- n -= 1
- m = m >> 1
- return x
- res = self.meta_interp(f, [50, 1], enable_opts='')
- assert res == 42
- def test_set_param(self):
- myjitdriver = JitDriver(greens = [], reds = ['n', 'x'])
- def g(n):
- x = 0
- while n > 0:
- myjitdriver.can_enter_jit(n=n, x=x)
- myjitdriver.jit_merge_point(n=n, x=x)
- n -= 1
- x += n
- return x
- def f(n, threshold, arg):
- if arg:
- set_param(myjitdriver, 'threshold', threshold)
- else:
- set_param(None, 'threshold', threshold)
- return g(n)
- res = self.meta_interp(f, [10, 3, 1])
- assert res == 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + 0
- self.check_jitcell_token_count(1)
- res = self.meta_interp(f, [10, 13, 0])
- assert res == 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + 0
- self.check_jitcell_token_count(0)
- def test_dont_look_inside(self):
- @dont_look_inside
- def g(a, b):
- return a + b
- def f(a, b):
- return g(a, b)
- res = self.interp_operations(f, [3, 5])
- assert res == 8
- self.check_operations_history(int_add=0, call=1)
- def test_listcomp(self):
- myjitdriver = JitDriver(greens = [], reds = ['x', 'y', 'lst'])
- def f(x, y):
- lst = [0, 0, 0]
- while y > 0:
- myjitdriver.can_enter_jit(x=x, y=y, lst=lst)
- myjitdriver.jit_merge_point(x=x, y=y, lst=lst)
- lst = [i+x for i in lst if i >=0]
- y -= 1
- return lst[0]
- res = self.meta_interp(f, [6, 7], listcomp=True, backendopt=True, listops=True)
- # XXX: the loop looks inefficient
- assert res == 42
- def test_tuple_immutable(self):
- def new(a, b):
- return a, b
- def f(a, b):
- tup = new(a, b)
- return tup[1]
- res = self.interp_operations(f, [3, 5])
- assert res == 5
- self.check_operations_history(setfield_gc=2, getfield_gc_pure=0)
- def test_oosend_look_inside_only_one(self):
- class A:
- pass
- class B(A):
- def g(self):
- return 123
- class C(A):
- @dont_look_inside
- def g(self):
- return 456
- def f(n):
- if n > 3:
- x = B()
- else:
- x = C()
- return x.g() + x.g()
- res = self.interp_operations(f, [10])
- assert res == 123 * 2
- res = self.interp_operations(f, [-10])
- assert res == 456 * 2
- def test_residual_external_call(self):
- import math
- myjitdriver = JitDriver(greens = [], reds = ['y', 'x', 'res'])
- # When this test was written ll_math couldn't be inlined, now it can,
- # instead of rewriting this test, just ensure that an external call is
- # still generated by wrapping the function.
- @dont_look_inside
- def modf(x):
- return math.modf(x)
- def f(x, y):
- x = float(x)
- res = 0.0
- while y > 0:
- myjitdriver.can_enter_jit(x=x, y=y, res=res)
- myjitdriver.jit_merge_point(x=x, y=y, res=res)
- # this is an external call that the default policy ignores
- rpart, ipart = modf(x)
- res += ipart
- y -= 1
- return res
- res = self.meta_interp(f, [6, 7])
- assert res == 42
- self.check_trace_count(1)
- self.check_resops(call=2)
- def test_merge_guardclass_guardvalue(self):
- from pypy.rlib.objectmodel import instantiate
- myjitdriver = JitDriver(greens = [], reds = ['x', 'l'])
- class A(object):
- def g(self, x):
- return x - 5
- class B(A):
- def g(self, y):
- return y - 3
- a1 = A()
- a2 = A()
- b = B()
- def f(x):
- l = [a1] * 100 + [a2] * 100 + [b] * 100
- while x > 0:
- myjitdriver.can_enter_jit(x=x, l=l)
- myjitdriver.jit_merge_point(x=x, l=l)
- a = l[x]
- x = a.g(x)
- promote(a)
- return x
- res = self.meta_interp(f, [299], listops=True)
- assert res == f(299)
- self.check_resops(guard_class=0, guard_value=6)
- def test_merge_guardnonnull_guardclass(self):
- from pypy.rlib.objectmodel import instantiate
- myjitdriver = JitDriver(greens = [], reds = ['x', 'l'])
- class A(object):
- def g(self, x):
- return x - 3
- class B(A):
- def g(self, y):
- return y - 5
- a1 = A()
- b1 = B()
- def f(x):
- l = [None] * 100 + [b1] * 100 + [a1] * 100
- while x > 0:
- myjitdriver.can_enter_jit(x=x, l=l)
- myjitdriver.jit_merge_point(x=x, l=l)
- a = l[x]
- if a:
- x = a.g(x)
- else:
- x -= 7
- return x
- res = self.meta_interp(f, [299], listops=True)
- assert res == f(299)
- self.check_resops(guard_class=0, guard_nonnull=4,
- guard_nonnull_class=4, guard_isnull=2)
- def test_merge_guardnonnull_guardvalue(self):
- from pypy.rlib.objectmodel import instantiate
- myjitdriver = JitDriver(greens = [], reds = ['x', 'l'])
- class A(object):
- pass
- class B(A):
- pass
- a1 = A()
- b1 = B()
- def f(x):
- l = [b1] * 100 + [None] * 100 + [a1] * 100
- while x > 0:
- myjitdriver.can_enter_jit(x=x, l=l)
- myjitdriver.jit_merge_point(x=x, l=l)
- a = l[x]
- if a:
- x -= 5
- else:
- x -= 7
- promote(a)
- return x
- res = self.meta_interp(f, [299], listops=True)
- assert res == f(299)
- self.check_resops(guard_value=4, guard_class=0, guard_nonnull=4,
- guard_nonnull_class=0, guard_isnull=2)
- def test_merge_guardnonnull_guardvalue_2(self):
- from pypy.rlib.objectmodel import instantiate
- myjitdriver = JitDriver(greens = [], reds = ['x',…
Large files files are truncated, but you can click here to view the full file