Author: Alex Gaynor <[email protected]>
Branch: 
Changeset: r67343:886b28486155
Date: 2013-10-13 16:05 +0200
http://bitbucket.org/pypy/pypy/changeset/886b28486155/

Log:    make the frontend heapcache smarter, take advantage of usually-
        constant indices, and propate known values

diff --git a/rpython/jit/metainterp/heapcache.py 
b/rpython/jit/metainterp/heapcache.py
--- a/rpython/jit/metainterp/heapcache.py
+++ b/rpython/jit/metainterp/heapcache.py
@@ -118,20 +118,42 @@
             # A special case for ll_arraycopy, because it is so common, and its
             # effects are so well defined.
             elif effectinfo.oopspecindex == effectinfo.OS_ARRAYCOPY:
-                # The destination box
                 if (
-                    argboxes[2] in self.new_boxes and
+                    isinstance(argboxes[3], ConstInt) and
+                    isinstance(argboxes[4], ConstInt) and
+                    isinstance(argboxes[5], ConstInt) and
                     len(effectinfo.write_descrs_arrays) == 1
                 ):
-                    # Fish the descr out of the effectinfo
-                    cache = 
self.heap_array_cache.get(effectinfo.write_descrs_arrays[0], None)
-                    if cache is not None:
-                        # XXX: in theory the indices of the copy could be
-                        # looked at
-                        for idx, cache in cache.iteritems():
-                            for frombox in cache.keys():
-                                if not self.is_unescaped(frombox):
-                                    del cache[frombox]
+                    descr = effectinfo.write_descrs_arrays[0]
+                    cache = self.heap_array_cache.get(descr, None)
+                    srcstart = argboxes[3].getint()
+                    dststart = argboxes[4].getint()
+                    length = argboxes[5].getint()
+                    for i in xrange(length):
+                        value = self.getarrayitem(
+                            argboxes[1],
+                            ConstInt(srcstart + i),
+                            descr,
+                        )
+                        if value is not None:
+                            self.setarrayitem(
+                                argboxes[2],
+                                ConstInt(dststart + i),
+                                value,
+                                descr,
+                            )
+                        elif cache is not None:
+                            if argboxes[2] in self.new_boxes:
+                                try:
+                                    idx_cache = cache[dststart + i]
+                                except KeyError:
+                                    pass
+                                else:
+                                    for frombox in idx_cache.keys():
+                                        if not self.is_unescaped(frombox):
+                                            del idx_cache[frombox]
+                            else:
+                                cache[dststart + i].clear()
                     return
             else:
                 # Only invalidate things that are either escaped or arguments
@@ -210,9 +232,9 @@
         return new_d
 
     def getarrayitem(self, box, indexbox, descr):
-        box = self._input_indirection(box)
         if not isinstance(indexbox, ConstInt):
             return
+        box = self._input_indirection(box)
         index = indexbox.getint()
         cache = self.heap_array_cache.get(descr, None)
         if cache:
@@ -221,10 +243,10 @@
                 return self._output_indirection(indexcache.get(box, None))
 
     def getarrayitem_now_known(self, box, indexbox, valuebox, descr):
+        if not isinstance(indexbox, ConstInt):
+            return
         box = self._input_indirection(box)
         valuebox = self._input_indirection(valuebox)
-        if not isinstance(indexbox, ConstInt):
-            return
         index = indexbox.getint()
         cache = self.heap_array_cache.setdefault(descr, {})
         indexcache = cache.get(index, None)
diff --git a/rpython/jit/metainterp/test/test_heapcache.py 
b/rpython/jit/metainterp/test/test_heapcache.py
--- a/rpython/jit/metainterp/test/test_heapcache.py
+++ b/rpython/jit/metainterp/test/test_heapcache.py
@@ -372,22 +372,22 @@
         h.invalidate_caches(
             rop.CALL,
             FakeCallDescr(FakeEffectinfo.EF_CANNOT_RAISE, 
FakeEffectinfo.OS_ARRAYCOPY, write_descrs_arrays=[descr1]),
-            [None, None, box2, None, None]
+            [None, box5, box2, index1, index1, index1]
         )
         assert h.getarrayitem(box1, index1, descr1) is box2
         h.invalidate_caches(
             rop.CALL,
             FakeCallDescr(FakeEffectinfo.EF_CANNOT_RAISE, 
FakeEffectinfo.OS_ARRAYCOPY, write_descrs_arrays=[descr1]),
-            [None, None, box3, None, None]
+            [None, box5, box3, index1, index1, index1]
         )
-        assert h.getarrayitem(box1, index1, descr1) is None
+        assert h.getarrayitem(box1, index1, descr1) is box2
 
         h.setarrayitem(box4, index1, box2, descr1)
         assert h.getarrayitem(box4, index1, descr1) is box2
         h.invalidate_caches(
             rop.CALL,
             FakeCallDescr(FakeEffectinfo.EF_CANNOT_RAISE, 
FakeEffectinfo.OS_ARRAYCOPY, write_descrs_arrays=[descr1]),
-            [None, None, box2, None, None]
+            [None, box3, box5, index1, index1, index2]
         )
         assert h.getarrayitem(box4, index1, descr1) is None
 
@@ -399,10 +399,29 @@
         h.invalidate_caches(
             rop.CALL,
             FakeCallDescr(FakeEffectinfo.EF_CANNOT_RAISE, 
FakeEffectinfo.OS_ARRAYCOPY, write_descrs_arrays=[descr2]),
-            [None, None, box2, None, None]
+            [None, box3, box2, index1, index1, index2]
         )
         assert h.getarrayitem(box1, index1, descr1) is box2
 
+    def test_ll_arraycopy_result_propogated(self):
+        h = HeapCache()
+        h.setarrayitem(box1, index1, box2, descr1)
+        h.invalidate_caches(
+            rop.CALL,
+            FakeCallDescr(FakeEffectinfo.EF_CANNOT_RAISE, 
FakeEffectinfo.OS_ARRAYCOPY, write_descrs_arrays=[descr1]),
+            [None, box1, box3, index1, index1, index2]
+        )
+        assert h.getarrayitem(box3, index1, descr1) is box2
+
+    def test_ll_arraycopy_dest_new(self):
+        h = HeapCache()
+        h.new_array(box1, lengthbox1)
+        h.setarrayitem(box3, index1, box4, descr1)
+        h.invalidate_caches(
+            rop.CALL,
+            FakeCallDescr(FakeEffectinfo.EF_CANNOT_RAISE, 
FakeEffectinfo.OS_ARRAYCOPY, write_descrs_arrays=[descr1]),
+            [None, box2, box1, index1, index1, index2]
+        )
 
     def test_unescaped(self):
         h = HeapCache()
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to