Author: Alex Gaynor <[email protected]>
Branch: jit-resizable-list
Changeset: r44596:9048883517aa
Date: 2011-05-30 10:42 -0700
http://bitbucket.org/pypy/pypy/changeset/9048883517aa/
Log: Special case _resize_ge() on a virtual resizable list.
diff --git a/pypy/jit/codewriter/effectinfo.py
b/pypy/jit/codewriter/effectinfo.py
--- a/pypy/jit/codewriter/effectinfo.py
+++ b/pypy/jit/codewriter/effectinfo.py
@@ -75,6 +75,8 @@
#
OS_MATH_SQRT = 100
+ OS_LIST_RESIZE_GE = 120
+
def __new__(cls, readonly_descrs_fields,
write_descrs_fields, write_descrs_arrays,
extraeffect=EF_CAN_RAISE,
diff --git a/pypy/jit/codewriter/jtransform.py
b/pypy/jit/codewriter/jtransform.py
--- a/pypy/jit/codewriter/jtransform.py
+++ b/pypy/jit/codewriter/jtransform.py
@@ -1233,6 +1233,11 @@
do_resizable_void_list_getitem_foldable = do_resizable_void_list_getitem
do_resizable_void_list_setitem = do_resizable_void_list_getitem
+ def do_resizable_list__resize_ge(self, op, args, arraydescr, lengthdescr,
+ itemsdescr, structdescr):
+ return self._handle_oopspec_call(op, args,
EffectInfo.OS_LIST_RESIZE_GE)
+
+
# ----------
# Strings and Unicodes.
diff --git a/pypy/jit/metainterp/optimizeopt/rewrite.py
b/pypy/jit/metainterp/optimizeopt/rewrite.py
--- a/pypy/jit/metainterp/optimizeopt/rewrite.py
+++ b/pypy/jit/metainterp/optimizeopt/rewrite.py
@@ -3,7 +3,6 @@
from pypy.jit.metainterp.history import ConstInt
from pypy.jit.metainterp.optimizeutil import _findall
from pypy.jit.metainterp.resoperation import rop, ResOperation
-from pypy.jit.codewriter.effectinfo import EffectInfo
from pypy.jit.metainterp.optimizeopt.intutils import IntBound
from pypy.rlib.rarithmetic import highest_bit
@@ -396,38 +395,6 @@
## return
## self.emit_operation(op)
- def optimize_CALL(self, op):
- # dispatch based on 'oopspecindex' to a method that handles
- # specifically the given oopspec call. For non-oopspec calls,
- # oopspecindex is just zero.
- effectinfo = op.getdescr().get_extra_info()
- if effectinfo is not None:
- oopspecindex = effectinfo.oopspecindex
- if oopspecindex == EffectInfo.OS_ARRAYCOPY:
- if self._optimize_CALL_ARRAYCOPY(op):
- return
- self.emit_operation(op)
-
- def _optimize_CALL_ARRAYCOPY(self, op):
- source_value = self.getvalue(op.getarg(1))
- dest_value = self.getvalue(op.getarg(2))
- source_start_box = self.get_constant_box(op.getarg(3))
- dest_start_box = self.get_constant_box(op.getarg(4))
- length = self.get_constant_box(op.getarg(5))
- if (source_value.is_virtual() and source_start_box and dest_start_box
- and length and dest_value.is_virtual()):
- # XXX optimize the case where dest value is not virtual,
- # but we still can avoid a mess
- source_start = source_start_box.getint()
- dest_start = dest_start_box.getint()
- for index in range(length.getint()):
- val = source_value.getitem(index + source_start)
- dest_value.setitem(index + dest_start, val)
- return True
- if length and length.getint() == 0:
- return True # 0-length arraycopy
- return False
-
def optimize_INT_FLOORDIV(self, op):
v1 = self.getvalue(op.getarg(0))
v2 = self.getvalue(op.getarg(1))
diff --git a/pypy/jit/metainterp/optimizeopt/virtualize.py
b/pypy/jit/metainterp/optimizeopt/virtualize.py
--- a/pypy/jit/metainterp/optimizeopt/virtualize.py
+++ b/pypy/jit/metainterp/optimizeopt/virtualize.py
@@ -1,11 +1,11 @@
+from pypy.jit.codewriter.effectinfo import EffectInfo
+from pypy.jit.codewriter.heaptracker import vtable2descr
+from pypy.jit.metainterp.executor import execute
from pypy.jit.metainterp.history import Const, ConstInt, BoxInt
from pypy.jit.metainterp.resoperation import rop, ResOperation
-from pypy.jit.metainterp.optimizeutil import _findall, sort_descrs
-from pypy.jit.metainterp.optimizeutil import descrlist_dict
+from pypy.jit.metainterp.optimizeopt import optimizer
+from pypy.jit.metainterp.optimizeutil import _findall, sort_descrs,
descrlist_dict
from pypy.rlib.objectmodel import we_are_translated
-from pypy.jit.metainterp.optimizeopt import optimizer
-from pypy.jit.metainterp.executor import execute
-from pypy.jit.codewriter.heaptracker import vtable2descr
class AbstractVirtualValue(optimizer.OptValue):
@@ -237,6 +237,17 @@
assert isinstance(itemvalue, optimizer.OptValue)
self._items[index] = itemvalue
+ def resize(self, newsize):
+ assert newsize >= 0
+ # The current items up to newsize (if we're growing that's the full
+ # current list), plus as many new items as need (if we're shrinking
+ # that's [self.constvalue] * negative_value, aka an empty list)
+ self._items = self._items[:newsize] + [self.constvalue] * (newsize -
len(self._items))
+ # Change source_op, if we are forced it is emitted directly.
+ self.source_op = self.source_op.copy_and_change(
+ self.source_op.getopnum(), args=[ConstInt(newsize)]
+ )
+
def _really_force(self):
assert self.source_op is not None
if not we_are_translated():
@@ -312,6 +323,21 @@
self.make_equal_to(box, vvalue)
return vvalue
+ def optimize_CALL(self, op):
+ # dispatch based on 'oopspecindex' to a method that handles
+ # specifically the given oopspec call. For non-oopspec calls,
+ # oopspecindex is just zero.
+ effectinfo = op.getdescr().get_extra_info()
+ if effectinfo is not None:
+ oopspecindex = effectinfo.oopspecindex
+ if oopspecindex == EffectInfo.OS_ARRAYCOPY:
+ if self._optimize_CALL_ARRAYCOPY(op):
+ return
+ elif oopspecindex == EffectInfo.OS_LIST_RESIZE_GE:
+ if self._optimize_CALL_LIST_RESIZE_GE(op):
+ return
+ self.emit_operation(op)
+
def optimize_VIRTUAL_REF(self, op):
indexbox = op.getarg(1)
#
@@ -445,6 +471,44 @@
###self.heap_op_optimizer.optimize_SETARRAYITEM_GC(op, value,
fieldvalue)
self.emit_operation(op)
+ def _optimize_CALL_ARRAYCOPY(self, op):
+ source_value = self.getvalue(op.getarg(1))
+ dest_value = self.getvalue(op.getarg(2))
+ source_start_box = self.get_constant_box(op.getarg(3))
+ dest_start_box = self.get_constant_box(op.getarg(4))
+ length = self.get_constant_box(op.getarg(5))
+ if (source_value.is_virtual() and source_start_box and dest_start_box
+ and length and dest_value.is_virtual()):
+ # XXX optimize the case where dest value is not virtual,
+ # but we still can avoid a mess
+ source_start = source_start_box.getint()
+ dest_start = dest_start_box.getint()
+ for index in range(length.getint()):
+ val = source_value.getitem(index + source_start)
+ dest_value.setitem(index + dest_start, val)
+ return True
+ if length and length.getint() == 0:
+ return True # 0-length arraycopy
+ return False
+
+ def _optimize_CALL_LIST_RESIZE_GE(self, op):
+ list_value = self.getvalue(op.getarg(1))
+ newsize_value = self.getvalue(op.getarg(2))
+ newsize_box = self.get_constant_box(op.getarg(2))
+
+ if list_value.is_virtual() and newsize_box:
+ # XXX: EVIL HACKS BEGIN HERE
+ length_descr, items_descr = list_value._get_field_descr_list()
+ # XXX: EVIL HACKS END HERE
+ arrayitems = list_value.getfield(items_descr, None)
+ if arrayitems and arrayitems.is_virtual():
+ assert isinstance(arrayitems, VArrayValue)
+ newsize = newsize_box.getint()
+ arrayitems.resize(newsize)
+ list_value.setfield(length_descr, newsize_value)
+ return True
+ return False
+
def propagate_forward(self, op):
opnum = op.getopnum()
for value, func in optimize_ops:
diff --git a/pypy/jit/metainterp/test/test_list.py
b/pypy/jit/metainterp/test/test_list.py
--- a/pypy/jit/metainterp/test/test_list.py
+++ b/pypy/jit/metainterp/test/test_list.py
@@ -34,7 +34,7 @@
l = [x + 1]
n -= 1
return l[0]
-
+
res = self.meta_interp(f, [10], listops=True)
assert res == f(10)
self.check_all_virtualized()
@@ -60,7 +60,7 @@
def test_ll_fixed_setitem_fast(self):
jitdriver = JitDriver(greens = [], reds = ['n', 'l'])
-
+
def f(n):
l = [1, 2, 3]
@@ -116,7 +116,7 @@
assert res == f(10)
py.test.skip("'[non-null] * n' gives a residual call so far")
self.check_loops(setarrayitem_gc=0, getarrayitem_gc=0, call=0)
-
+
def test_arraycopy_simpleoptimize(self):
def f():
l = [1, 2, 3, 4]
@@ -208,6 +208,23 @@
assert res == f(15)
self.check_loops(guard_exception=0)
+ def test_virtual_resize(self):
+ jitdriver = JitDriver(greens = [], reds = ['n', 's'])
+ def f(n):
+ s = 0
+ while n > 0:
+ jitdriver.jit_merge_point(n=n, s=s)
+ lst = []
+ lst += [1]
+ n -= len(lst)
+ s += lst[0]
+ return s
+ res = self.meta_interp(f, [15], listops=True)
+ assert res == f(15)
+ self.check_loops({"int_add": 1, "int_sub": 1, "int_gt": 1,
+ "guard_true": 1, "jump": 1})
+
+
class TestOOtype(ListTests, OOJitMixin):
pass
diff --git a/pypy/jit/metainterp/test/test_slist.py
b/pypy/jit/metainterp/test/test_slist.py
--- a/pypy/jit/metainterp/test/test_slist.py
+++ b/pypy/jit/metainterp/test/test_slist.py
@@ -5,7 +5,6 @@
class ListTests(object):
def test_basic_list(self):
- py.test.skip("not yet")
myjitdriver = JitDriver(greens = [], reds = ['n', 'lst'])
def f(n):
lst = []
@@ -93,7 +92,7 @@
return x
res = self.meta_interp(f, [-2], listops=True)
assert res == 41
- self.check_loops(call=1, guard_value=0)
+ self.check_loops(call=0, guard_value=0)
# we don't support resizable lists on ootype
#class TestOOtype(ListTests, OOJitMixin):
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit