[pypy-svn] r78924 - in pypy/branch/rlist-jit/pypy: jit/codewriter jit/codewriter/test jit/metainterp/test rpython rpython/test
arigo at codespeak.net
arigo at codespeak.net
Tue Nov 9 15:51:43 CET 2010
Author: arigo
Date: Tue Nov 9 15:51:41 2010
New Revision: 78924
Modified:
pypy/branch/rlist-jit/pypy/jit/codewriter/jtransform.py
pypy/branch/rlist-jit/pypy/jit/codewriter/test/test_list.py
pypy/branch/rlist-jit/pypy/jit/codewriter/test/test_void_list.py
pypy/branch/rlist-jit/pypy/jit/metainterp/test/test_list.py
pypy/branch/rlist-jit/pypy/rpython/rlist.py
pypy/branch/rlist-jit/pypy/rpython/test/test_rlist.py
Log:
Not really a complete clean-up, but good enough to make
one new test in jit/metainterp/test/test_list.py pass.
Modified: pypy/branch/rlist-jit/pypy/jit/codewriter/jtransform.py
==============================================================================
--- pypy/branch/rlist-jit/pypy/jit/codewriter/jtransform.py (original)
+++ pypy/branch/rlist-jit/pypy/jit/codewriter/jtransform.py Tue Nov 9 15:51:41 2010
@@ -924,21 +924,19 @@
# base hints on the name of the ll function, which is a bit xxx-ish
# but which is safe for now
assert func.func_name.startswith('ll_')
+ # check that we have carefully placed the oopspec in
+ # pypy/rpython/rlist.py. There should not be an oopspec on
+ # a ll_getitem or ll_setitem that expects a 'func' argument.
+ # The idea is that a ll_getitem/ll_setitem with dum_checkidx
+ # should get inlined by the JIT, so that we see the potential
+ # 'raise IndexError'.
+ assert 'func' not in func.func_code.co_varnames
non_negative = '_nonneg' in func.func_name
fast = '_fast' in func.func_name
- if fast:
- can_raise = False
- non_negative = True
- else:
- tag = op.args[1].value
- assert tag in (rlist.dum_nocheck, rlist.dum_checkidx)
- can_raise = tag != rlist.dum_nocheck
- return non_negative, can_raise
+ return non_negative or fast
def _prepare_list_getset(self, op, descr, args, checkname):
- non_negative, can_raise = self._get_list_nonneg_canraise_flags(op)
- if can_raise:
- raise NotSupported("list operation can raise")
+ non_negative = self._get_list_nonneg_canraise_flags(op)
if non_negative:
return args[1], []
else:
@@ -950,9 +948,8 @@
return v_posindex, [op0, op1]
def _prepare_void_list_getset(self, op):
- non_negative, can_raise = self._get_list_nonneg_canraise_flags(op)
- if can_raise:
- raise NotSupported("list operation can raise")
+ # sanity check:
+ self._get_list_nonneg_canraise_flags(op)
def _get_initial_newlist_length(self, op, args):
# normalize number of arguments to the 'newlist' function
Modified: pypy/branch/rlist-jit/pypy/jit/codewriter/test/test_list.py
==============================================================================
--- pypy/branch/rlist-jit/pypy/jit/codewriter/test/test_list.py (original)
+++ pypy/branch/rlist-jit/pypy/jit/codewriter/test/test_list.py Tue Nov 9 15:51:41 2010
@@ -56,9 +56,8 @@
if '/' in oopspec_name:
oopspec_name, property = oopspec_name.split('/')
def force_flags(op):
- if property == 'NONNEG': return True, False
- if property == 'NEG': return False, False
- if property == 'CANRAISE': return False, True
+ if property == 'NONNEG': return True
+ if property == 'NEG': return False
raise ValueError(property)
tr._get_list_nonneg_canraise_flags = force_flags
op = SpaceOperation('direct_call',
@@ -122,9 +121,6 @@
check_neg_index %r0, <ArrayDescr>, %i0 -> %i1
getarrayitem_gc_i %r0, <ArrayDescr>, %i1 -> %i2
""")
- builtin_test('list.getitem/CANRAISE',
- [varoftype(FIXEDLIST), varoftype(lltype.Signed)],
- lltype.Signed, NotSupported)
def test_fixed_getitem_foldable():
builtin_test('list.getitem_foldable/NONNEG',
@@ -139,9 +135,6 @@
check_neg_index %r0, <ArrayDescr>, %i0 -> %i1
getarrayitem_gc_pure_i %r0, <ArrayDescr>, %i1 -> %i2
""")
- builtin_test('list.getitem_foldable/CANRAISE',
- [varoftype(FIXEDLIST), varoftype(lltype.Signed)],
- lltype.Signed, NotSupported)
def test_fixed_setitem():
builtin_test('list.setitem/NONNEG', [varoftype(FIXEDLIST),
@@ -158,10 +151,6 @@
check_neg_index %r0, <ArrayDescr>, %i0 -> %i1
setarrayitem_gc_i %r0, <ArrayDescr>, %i1, %i2
""")
- builtin_test('list.setitem/CANRAISE', [varoftype(FIXEDLIST),
- varoftype(lltype.Signed),
- varoftype(lltype.Signed)],
- lltype.Void, NotSupported)
def test_fixed_len():
builtin_test('list.len', [varoftype(FIXEDLIST)], lltype.Signed,
@@ -206,9 +195,6 @@
check_resizable_neg_index %r0, <FieldDescr length>, %i0 -> %i1
getlistitem_gc_i %r0, <FieldDescr items>, <ArrayDescr>, %i1 -> %i2
""")
- builtin_test('list.getitem/CANRAISE',
- [varoftype(VARLIST), varoftype(lltype.Signed)],
- lltype.Signed, NotSupported)
def test_resizable_setitem():
builtin_test('list.setitem/NONNEG', [varoftype(VARLIST),
@@ -225,10 +211,6 @@
check_resizable_neg_index %r0, <FieldDescr length>, %i0 -> %i1
setlistitem_gc_i %r0, <FieldDescr items>, <ArrayDescr>, %i1, %i2
""")
- builtin_test('list.setitem/CANRAISE', [varoftype(VARLIST),
- varoftype(lltype.Signed),
- varoftype(lltype.Signed)],
- lltype.Void, NotSupported)
def test_resizable_len():
builtin_test('list.len', [varoftype(VARLIST)], lltype.Signed,
Modified: pypy/branch/rlist-jit/pypy/jit/codewriter/test/test_void_list.py
==============================================================================
--- pypy/branch/rlist-jit/pypy/jit/codewriter/test/test_void_list.py (original)
+++ pypy/branch/rlist-jit/pypy/jit/codewriter/test/test_void_list.py Tue Nov 9 15:51:41 2010
@@ -51,9 +51,6 @@
builtin_test('list.getitem/NEG',
[varoftype(FIXEDLIST), varoftype(lltype.Signed)],
lltype.Void, "")
- builtin_test('list.getitem/CANRAISE',
- [varoftype(FIXEDLIST), varoftype(lltype.Signed)],
- lltype.Void, NotSupported)
def test_fixed_getitem_foldable():
builtin_test('list.getitem_foldable/NONNEG',
@@ -62,9 +59,6 @@
builtin_test('list.getitem_foldable/NEG',
[varoftype(FIXEDLIST), varoftype(lltype.Signed)],
lltype.Void, "")
- builtin_test('list.getitem_foldable/CANRAISE',
- [varoftype(FIXEDLIST), varoftype(lltype.Signed)],
- lltype.Void, NotSupported)
def test_fixed_setitem():
builtin_test('list.setitem/NONNEG', [varoftype(FIXEDLIST),
@@ -75,10 +69,6 @@
varoftype(lltype.Signed),
varoftype(lltype.Void)],
lltype.Void, "")
- builtin_test('list.setitem/CANRAISE', [varoftype(FIXEDLIST),
- varoftype(lltype.Signed),
- varoftype(lltype.Void)],
- lltype.Void, NotSupported)
def test_fixed_len():
builtin_test('list.len', [varoftype(FIXEDLIST)], lltype.Signed,
@@ -115,9 +105,6 @@
builtin_test('list.getitem/NEG',
[varoftype(VARLIST), varoftype(lltype.Signed)],
lltype.Void, "")
- builtin_test('list.getitem/CANRAISE',
- [varoftype(VARLIST), varoftype(lltype.Signed)],
- lltype.Void, NotSupported)
def test_resizable_setitem():
builtin_test('list.setitem/NONNEG', [varoftype(VARLIST),
@@ -128,10 +115,6 @@
varoftype(lltype.Signed),
varoftype(lltype.Void)],
lltype.Void, "")
- builtin_test('list.setitem/CANRAISE', [varoftype(VARLIST),
- varoftype(lltype.Signed),
- varoftype(lltype.Void)],
- lltype.Void, NotSupported)
def test_resizable_len():
builtin_test('list.len', [varoftype(VARLIST)], lltype.Signed,
Modified: pypy/branch/rlist-jit/pypy/jit/metainterp/test/test_list.py
==============================================================================
--- pypy/branch/rlist-jit/pypy/jit/metainterp/test/test_list.py (original)
+++ pypy/branch/rlist-jit/pypy/jit/metainterp/test/test_list.py Tue Nov 9 15:51:41 2010
@@ -188,6 +188,26 @@
assert res == f(4)
self.check_loops(call=0, getfield_gc=0)
+ def test_fold_indexerror(self):
+ jitdriver = JitDriver(greens = [], reds = ['total', 'n', 'lst'])
+ def f(n):
+ lst = []
+ total = 0
+ while n > 0:
+ jitdriver.can_enter_jit(lst=lst, n=n, total=total)
+ jitdriver.jit_merge_point(lst=lst, n=n, total=total)
+ lst.append(n)
+ try:
+ total += lst[n]
+ except IndexError:
+ total += 1000
+ n -= 1
+ return total
+
+ res = self.meta_interp(f, [15], listops=True)
+ assert res == f(15)
+ self.check_loops(guard_exception=0)
+
class TestOOtype(ListTests, OOJitMixin):
pass
Modified: pypy/branch/rlist-jit/pypy/rpython/rlist.py
==============================================================================
--- pypy/branch/rlist-jit/pypy/rpython/rlist.py (original)
+++ pypy/branch/rlist-jit/pypy/rpython/rlist.py Tue Nov 9 15:51:41 2010
@@ -9,7 +9,7 @@
from pypy.rpython import robject
from pypy.rlib.objectmodel import malloc_zero_filled
from pypy.rlib.debug import ll_assert
-from pypy.rlib.rarithmetic import ovfcheck, widen
+from pypy.rlib.rarithmetic import ovfcheck, widen, r_uint
from pypy.rpython.annlowlevel import ADTInterface
from pypy.rlib import rgc
@@ -241,17 +241,22 @@
class __extend__(pairtype(AbstractBaseListRepr, IntegerRepr)):
def rtype_getitem((r_lst, r_int), hop, checkidx=False):
+ v_lst, v_index = hop.inputargs(r_lst, Signed)
if checkidx:
- spec = dum_checkidx
+ hop.exception_is_here()
else:
- spec = dum_nocheck
- v_func = hop.inputconst(Void, spec)
- v_lst, v_index = hop.inputargs(r_lst, Signed)
+ hop.exception_cannot_occur()
if hop.args_s[0].listdef.listitem.mutated or checkidx:
if hop.args_s[1].nonneg:
llfn = ll_getitem_nonneg
else:
llfn = ll_getitem
+ if checkidx:
+ spec = dum_checkidx
+ else:
+ spec = dum_nocheck
+ c_func_marker = hop.inputconst(Void, spec)
+ v_res = hop.gendirectcall(llfn, c_func_marker, v_lst, v_index)
else:
# this is the 'foldable' version, which is not used when
# we check for IndexError
@@ -259,11 +264,7 @@
llfn = ll_getitem_foldable_nonneg
else:
llfn = ll_getitem_foldable
- if checkidx:
- hop.exception_is_here()
- else:
- hop.exception_cannot_occur()
- v_res = hop.gendirectcall(llfn, v_func, v_lst, v_index)
+ v_res = hop.gendirectcall(llfn, v_lst, v_index)
return r_lst.recast(hop.llops, v_res)
rtype_getitem_key = rtype_getitem
@@ -538,12 +539,14 @@
dest.ll_setitem_fast(dest_start + i, item)
i += 1
ll_arraycopy._annenforceargs_ = [None, None, int, int, int]
+# no oopspec -- the function is inlined by the JIT
def ll_copy(RESLIST, l):
length = l.ll_length()
new_lst = RESLIST.ll_newlist(length)
ll_arraycopy(l, new_lst, 0, 0, length)
return new_lst
+# no oopspec -- the function is inlined by the JIT
def ll_len(l):
return l.ll_length()
@@ -551,6 +554,7 @@
def ll_list_is_true(l):
# check if a list is True, allowing for None
return bool(l) and l.ll_length() != 0
+# no oopspec -- the function is inlined by the JIT
def ll_len_foldable(l):
return l.ll_length()
@@ -558,6 +562,7 @@
def ll_list_is_true_foldable(l):
return bool(l) and ll_len_foldable(l) != 0
+# no oopspec -- the function is inlined by the JIT
def ll_append(l, newitem):
length = l.ll_length()
@@ -588,6 +593,7 @@
ll_arraycopy(l1, l, 0, 0, len1)
ll_arraycopy(l2, l, 0, len1, len2)
return l
+# no oopspec -- the function is inlined by the JIT
def ll_insert_nonneg(l, index, newitem):
length = l.ll_length()
@@ -674,60 +680,69 @@
l.ll_setitem_fast(length_1_i, tmp)
i += 1
length_1_i -= 1
+ll_reverse.oopspec = 'list.reverse(l)'
def ll_getitem_nonneg(func, l, index):
ll_assert(index >= 0, "unexpectedly negative list getitem index")
if func is dum_checkidx:
if index >= l.ll_length():
raise IndexError
- else:
- ll_assert(index < l.ll_length(), "list getitem index out of bound")
return l.ll_getitem_fast(index)
-ll_getitem_nonneg.oopspec = 'list.getitem(l, index)'
+# no oopspec -- the function is inlined by the JIT
def ll_getitem(func, l, index):
- length = l.ll_length()
- if index < 0:
- index += length
if func is dum_checkidx:
- if index < 0 or index >= length:
- raise IndexError
+ length = l.ll_length() # common case: 0 <= index < length
+ if r_uint(index) >= r_uint(length):
+ # Failed, so either (-length <= index < 0), or we have to raise
+ # IndexError. Using r_uint, the condition can be rewritten as
+ # (-length-1 < index), which is (~length < index).
+ if r_uint(~length) < r_uint(index):
+ index += length
+ else:
+ raise IndexError
else:
- ll_assert(index >= 0, "negative list getitem index out of bound")
- ll_assert(index < length, "list getitem index out of bound")
+ # We don't want checking, but still want to support index < 0.
+ # Only call ll_length() if needed.
+ if index < 0:
+ index += l.ll_length()
+ ll_assert(index >= 0, "negative list getitem index out of bound")
return l.ll_getitem_fast(index)
-ll_getitem.oopspec = 'list.getitem(l, index)'
+# no oopspec -- the function is inlined by the JIT
-def ll_getitem_foldable_nonneg(func, l, index):
- return ll_getitem_nonneg(func, l, index)
+def ll_getitem_foldable_nonneg(l, index):
+ ll_assert(index >= 0, "unexpectedly negative list getitem index")
+ return l.ll_getitem_fast(index)
ll_getitem_foldable_nonneg.oopspec = 'list.getitem_foldable(l, index)'
-def ll_getitem_foldable(func, l, index):
- return ll_getitem(func, l, index)
-ll_getitem_foldable.oopspec = 'list.getitem_foldable(l, index)'
+def ll_getitem_foldable(l, index):
+ if index < 0:
+ index += l.ll_length()
+ return ll_getitem_foldable_nonneg(l, index)
+# no oopspec -- the function is inlined by the JIT
def ll_setitem_nonneg(func, l, index, newitem):
ll_assert(index >= 0, "unexpectedly negative list setitem index")
if func is dum_checkidx:
if index >= l.ll_length():
raise IndexError
- else:
- ll_assert(index < l.ll_length(), "list setitem index out of bound")
l.ll_setitem_fast(index, newitem)
-ll_setitem_nonneg.oopspec = 'list.setitem(l, index, newitem)'
+# no oopspec -- the function is inlined by the JIT
def ll_setitem(func, l, index, newitem):
- length = l.ll_length()
- if index < 0:
- index += length
if func is dum_checkidx:
- if index < 0 or index >= length:
- raise IndexError
+ length = l.ll_length()
+ if r_uint(index) >= r_uint(length): # see comments in ll_getitem().
+ if r_uint(~length) < r_uint(index):
+ index += length
+ else:
+ raise IndexError
else:
- ll_assert(index >= 0, "negative list setitem index out of bound")
- ll_assert(index < length, "list setitem index out of bound")
+ if index < 0:
+ index += l.ll_length()
+ ll_assert(index >= 0, "negative list getitem index out of bound")
l.ll_setitem_fast(index, newitem)
-ll_setitem.oopspec = 'list.setitem(l, index, newitem)'
+# no oopspec -- the function is inlined by the JIT
def ll_delitem_nonneg(func, l, index):
ll_assert(index >= 0, "unexpectedly negative list delitem index")
@@ -756,7 +771,7 @@
if i < 0:
i += length
if func is dum_checkidx:
- if i < 0 or i >= length:
+ if r_uint(i) >= r_uint(length):
raise IndexError
else:
ll_assert(i >= 0, "negative list delitem index out of bound")
@@ -799,6 +814,7 @@
lst.ll_setitem_fast(j, c)
i += 1
j += 1
+# not inlined by the JIT -- contains a loop
def ll_extend_with_str_slice_startstop(lst, s, getstrlen, getstritem,
start, stop):
@@ -824,6 +840,7 @@
lst.ll_setitem_fast(j, c)
i += 1
j += 1
+# not inlined by the JIT -- contains a loop
def ll_extend_with_str_slice_minusone(lst, s, getstrlen, getstritem):
len1 = lst.ll_length()
@@ -843,6 +860,7 @@
lst.ll_setitem_fast(j, c)
i += 1
j += 1
+# not inlined by the JIT -- contains a loop
def ll_extend_with_char_count(lst, char, count):
if count <= 0:
@@ -859,6 +877,7 @@
while j < newlength:
lst.ll_setitem_fast(j, char)
j += 1
+# not inlined by the JIT -- contains a loop
def ll_listslice_startonly(RESLIST, l1, start):
len1 = l1.ll_length()
@@ -869,6 +888,7 @@
ll_arraycopy(l1, l, start, 0, newlength)
return l
ll_listslice_startonly._annenforceargs_ = (None, None, int)
+# no oopspec -- the function is inlined by the JIT
def ll_listslice_startstop(RESLIST, l1, start, stop):
length = l1.ll_length()
@@ -881,6 +901,7 @@
l = RESLIST.ll_newlist(newlength)
ll_arraycopy(l1, l, start, 0, newlength)
return l
+# no oopspec -- the function is inlined by the JIT
def ll_listslice_minusone(RESLIST, l1):
newlength = l1.ll_length() - 1
@@ -888,6 +909,7 @@
l = RESLIST.ll_newlist(newlength)
ll_arraycopy(l1, l, 0, 0, newlength)
return l
+# no oopspec -- the function is inlined by the JIT
def ll_listdelslice_startonly(l, start):
ll_assert(start >= 0, "del l[start:] with unexpectedly negative start")
@@ -958,6 +980,7 @@
return False
j += 1
return True
+# not inlined by the JIT -- contains a loop
def ll_listcontains(lst, obj, eqfn):
lng = lst.ll_length()
@@ -971,6 +994,7 @@
return True
j += 1
return False
+# not inlined by the JIT -- contains a loop
def ll_listindex(lst, obj, eqfn):
lng = lst.ll_length()
@@ -984,6 +1008,7 @@
return j
j += 1
raise ValueError # can't say 'list.index(x): x not in list'
+# not inlined by the JIT -- contains a loop
def ll_listremove(lst, obj, eqfn):
index = ll_listindex(lst, obj, eqfn) # raises ValueError if obj not in lst
@@ -1030,3 +1055,4 @@
i += 1
j += length
return res
+# not inlined by the JIT -- contains a loop
Modified: pypy/branch/rlist-jit/pypy/rpython/test/test_rlist.py
==============================================================================
--- pypy/branch/rlist-jit/pypy/rpython/test/test_rlist.py (original)
+++ pypy/branch/rlist-jit/pypy/rpython/test/test_rlist.py Tue Nov 9 15:51:41 2010
@@ -1420,14 +1420,15 @@
lst2 = [i]
lst2.append(42) # mutated list
return lst1[i] + lst2[i]
- _, _, graph = self.gengraph(f, [int])
+ from pypy.annotation import model as annmodel
+ _, _, graph = self.gengraph(f, [annmodel.SomeInteger(nonneg=True)])
block = graph.startblock
lst1_getitem_op = block.operations[-3] # XXX graph fishing
lst2_getitem_op = block.operations[-2]
func1 = lst1_getitem_op.args[0].value._obj._callable
func2 = lst2_getitem_op.args[0].value._obj._callable
assert func1.oopspec == 'list.getitem_foldable(l, index)'
- assert func2.oopspec == 'list.getitem(l, index)'
+ assert not hasattr(func2, 'oopspec')
class TestOOtype(BaseTestRlist, OORtypeMixin):
rlist = oo_rlist
More information about the Pypy-commit
mailing list