[pypy-svn] pypy jit-short-preamble: ARRAYITEM support

hakanardo commits-noreply at bitbucket.org
Sun Jan 9 13:37:44 CET 2011


Author: Hakan Ardo <hakan at debian.org>
Branch: jit-short-preamble
Changeset: r40515:698e87e3fe9f
Date: 2011-01-09 13:26 +0100
http://bitbucket.org/pypy/pypy/changeset/698e87e3fe9f/

Log:	ARRAYITEM support

diff --git a/pypy/jit/metainterp/optimizeopt/unroll.py b/pypy/jit/metainterp/optimizeopt/unroll.py
--- a/pypy/jit/metainterp/optimizeopt/unroll.py
+++ b/pypy/jit/metainterp/optimizeopt/unroll.py
@@ -341,7 +341,9 @@
         self.optimizer = optimizer
         self.heap_dirty = False
         self.unsafe_getitem = {}
-
+        self.unsafe_getarrayitem = {}
+        self.unsafe_getarrayitem_indexes = {}
+        
     # Make sure it is safe to move the instrucions in short_preamble
     # to the top making short_preamble followed by loop equvivalent
     # to preamble
@@ -359,6 +361,23 @@
             if descr in self.unsafe_getitem:
                 return False
             return True
+        elif (opnum == rop.GETARRAYITEM_GC or
+              opnum == rop.GETARRAYITEM_RAW):
+            if self.heap_dirty:
+                return False
+            descr = op.getdescr()
+            if descr in self.unsafe_getarrayitem:
+                return False
+            index = op.getarg(1)
+            if isinstance(index, Const):
+                d = self.unsafe_getarrayitem_indexes.get(descr, None)
+                if d is not None:
+                    if index.getint() in d:
+                        return False
+            else:
+                if descr in self.unsafe_getarrayitem_indexes:
+                    return False
+            return True
         elif opnum == rop.CALL:
             arg = op.getarg(0)
             if isinstance(arg, Const):
@@ -377,19 +396,26 @@
             op.is_guard()): 
             return
         opnum = op.getopnum()
+        descr = op.getdescr()
         if (opnum == rop.DEBUG_MERGE_POINT):
             return
         if (opnum == rop.SETFIELD_GC or
             opnum == rop.SETFIELD_RAW):
-            descr = op.getdescr()
             self.unsafe_getitem[descr] = True
             return
         if (opnum == rop.SETARRAYITEM_GC or
             opnum == rop.SETARRAYITEM_RAW):
-            return # These wont clutter the heap accessable by GETFIELD_*
-                   # FIXME: Implement proper support for ARRAYITEMS
+            index = op.getarg(1)
+            if isinstance(index, Const):                
+                d = self.unsafe_getarrayitem_indexes.get(descr, None)
+                if d is None:
+                    d = self.unsafe_getarrayitem_indexes[descr] = {}
+                d[index.getint()] = True
+            else:
+                self.unsafe_getarrayitem[descr] = True
+            return
         if opnum == rop.CALL:
-            effectinfo = op.getdescr().get_extra_info()
+            effectinfo = descr.get_extra_info()
             if effectinfo is not None:
                 for fielddescr in effectinfo.write_descrs_fields:
                     self.unsafe_getitem[fielddescr] = True

diff --git a/pypy/jit/metainterp/test/test_basic.py b/pypy/jit/metainterp/test/test_basic.py
--- a/pypy/jit/metainterp/test/test_basic.py
+++ b/pypy/jit/metainterp/test/test_basic.py
@@ -1843,6 +1843,47 @@
                           'int_add': 1, 'int_mul': 1, 'int_sub': 2,
                           'int_gt': 2, 'jump': 2})
 
+    def test_multiple_specialied_versions_array(self):
+        myjitdriver = JitDriver(greens = [], reds = ['idx', 'y', 'x', 'res',
+                                                     'array'])
+        class Base:
+            def __init__(self, val):
+                self.val = val
+        class A(Base):
+            def binop(self, other):
+                return A(self.val + other.val)
+        class B(Base):
+            def binop(self, other):
+                return B(self.val * other.val)
+        def f(x, y):
+            res = x
+            array = [1, 2, 3]
+            array[1] = 7
+            idx = 0
+            while y > 0:
+                myjitdriver.can_enter_jit(idx=idx, y=y, x=x, res=res,
+                                          array=array)
+                myjitdriver.jit_merge_point(idx=idx, y=y, x=x, res=res,
+                                            array=array)
+                res = res.binop(x)
+                res.val += array[idx] + array[1]
+                if y < 7:
+                    idx = 2
+                y -= 1
+            return res
+        def g(x, y):
+            a1 = f(A(x), y)
+            a2 = f(A(x), y)
+            b1 = f(B(x), y)
+            b2 = f(B(x), y)
+            assert a1.val == a2.val
+            assert b1.val == b2.val
+            return a1.val + b1.val
+        res = self.meta_interp(g, [6, 14])
+        assert res == g(6, 14)
+        self.check_loop_count(8)
+        self.check_loops(getarrayitem_gc=16, everywhere=True)
+
     def test_multiple_specialied_versions_bridge(self):
         myjitdriver = JitDriver(greens = [], reds = ['y', 'x', 'z', 'res'])
         class Base:

diff --git a/pypy/jit/metainterp/optimizeopt/heap.py b/pypy/jit/metainterp/optimizeopt/heap.py
--- a/pypy/jit/metainterp/optimizeopt/heap.py
+++ b/pypy/jit/metainterp/optimizeopt/heap.py
@@ -51,12 +51,13 @@
                 if cache.var_index_item:
                     newcache.var_index_item = \
                           cache.var_index_item.get_reconstructed(optimizer, valuemap)
-                if newcache.var_index_indexvalue:
+                if cache.var_index_indexvalue:
                     newcache.var_index_indexvalue = \
                           cache.var_index_indexvalue.get_reconstructed(optimizer, valuemap)
                 for index, fieldvalue in cache.fixed_index_items.items():
                     newcache.fixed_index_items[index] = \
                            fieldvalue.get_reconstructed(optimizer, valuemap)
+
         return new
 
     def clean_caches(self):

diff --git a/pypy/jit/metainterp/history.py b/pypy/jit/metainterp/history.py
--- a/pypy/jit/metainterp/history.py
+++ b/pypy/jit/metainterp/history.py
@@ -279,8 +279,9 @@
         cpu.set_future_value_int(j, self.value)
 
     def same_constant(self, other):
-        assert isinstance(other, Const)
-        return self.value == other.getint()
+        if isinstance(other, Const):
+            return self.value == other.getint()
+        return False
 
     def nonnull(self):
         return self.value != 0
@@ -318,8 +319,9 @@
         cpu.set_future_value_float(j, self.getfloat())
 
     def same_constant(self, other):
-        assert isinstance(other, ConstFloat)
-        return self.value == other.value
+        if isinstance(other, ConstFloat):
+            return self.value == other.value
+        return False
 
     def nonnull(self):
         return self.value != 0.0
@@ -366,8 +368,9 @@
         cpu.set_future_value_ref(j, self.value)
 
     def same_constant(self, other):
-        assert isinstance(other, ConstPtr)
-        return self.value == other.value
+        if isinstance(other, ConstPtr):
+            return self.value == other.value
+        return False
 
     def nonnull(self):
         return bool(self.value)
@@ -425,8 +428,9 @@
 ##        return self.value
 
     def same_constant(self, other):
-        assert isinstance(other, ConstObj)
-        return self.value == other.value
+        if isinstance(other, ConstObj):
+            return self.value == other.value
+        return False
 
     def nonnull(self):
         return bool(self.value)


More information about the Pypy-commit mailing list