[pypy-commit] pypy improve-heap-caching-tracing: add the knowledge that two boxes with that were the result of a "new" operation

cfbolz noreply at buildbot.pypy.org
Fri Sep 2 15:13:33 CEST 2011


Author: Carl Friedrich Bolz <cfbolz at gmx.de>
Branch: improve-heap-caching-tracing
Changeset: r47022:604e55dccba6
Date: 2011-09-02 15:13 +0200
http://bitbucket.org/pypy/pypy/changeset/604e55dccba6/

Log:	add the knowledge that two boxes with that were the result of a
	"new" operation can never alias each other.

diff --git a/pypy/jit/metainterp/heapcache.py b/pypy/jit/metainterp/heapcache.py
--- a/pypy/jit/metainterp/heapcache.py
+++ b/pypy/jit/metainterp/heapcache.py
@@ -8,6 +8,8 @@
     def reset(self):
         # contains boxes where the class is already known
         self.known_class_boxes = {}
+        # store the boxes that contain newly allocated objects:
+        self.new_boxes = {}
         # contains frame boxes that are not virtualizables
         self.nonstandard_virtualizables = {}
         # heap cache
@@ -46,6 +48,8 @@
     def nonstandard_virtualizables_now_known(self, box):
         self.nonstandard_virtualizables[box] = None
 
+    def new(self, box):
+        self.new_boxes[box] = None
 
     def getfield(self, box, descr):
         d = self.heap_cache.get(descr, None)
@@ -59,7 +63,15 @@
         self.heap_cache.setdefault(descr, {})[box] = fieldbox
 
     def setfield(self, box, descr, fieldbox):
-        self.heap_cache[descr] = {box: fieldbox}
+        d = self.heap_cache.get(descr, None)
+        new_d = {box: fieldbox}
+        if not d or box not in self.new_boxes:
+            self.heap_cache[descr] = new_d
+            return
+        for frombox, tobox in d.iteritems():
+            if frombox in self.new_boxes:
+                new_d[frombox] = tobox
+        self.heap_cache[descr] = new_d
 
     def getarrayitem(self, box, descr, indexbox):
         if not isinstance(indexbox, ConstInt):
diff --git a/pypy/jit/metainterp/pyjitpl.py b/pypy/jit/metainterp/pyjitpl.py
--- a/pypy/jit/metainterp/pyjitpl.py
+++ b/pypy/jit/metainterp/pyjitpl.py
@@ -374,6 +374,7 @@
         cpu = self.metainterp.cpu
         cls = heaptracker.descr2vtable(cpu, sizedescr)
         resbox = self.execute(rop.NEW_WITH_VTABLE, ConstInt(cls))
+        self.metainterp.heapcache.new(resbox)
         self.metainterp.heapcache.class_now_know(resbox)
         return resbox
 
diff --git a/pypy/jit/metainterp/test/test_heapcache.py b/pypy/jit/metainterp/test/test_heapcache.py
--- a/pypy/jit/metainterp/test/test_heapcache.py
+++ b/pypy/jit/metainterp/test/test_heapcache.py
@@ -81,7 +81,7 @@
         assert h.getfield(box1, descr2) is None
         assert h.getfield(box3, descr1) is None
 
-    def test_heapcache_fields_multiple(self):
+    def test_heapcache_read_fields_multiple(self):
         h = HeapCache()
         h.getfield_now_known(box1, descr1, box2)
         h.getfield_now_known(box3, descr1, box4)
@@ -96,6 +96,31 @@
         assert h.getfield(box3, descr1) is None
         assert h.getfield(box3, descr2) is None
 
+    def test_heapcache_write_fields_multiple(self):
+        h = HeapCache()
+        h.setfield(box1, descr1, box2)
+        assert h.getfield(box1, descr1) is box2
+        h.setfield(box3, descr1, box4)
+        assert h.getfield(box3, descr1) is box4
+        assert h.getfield(box1, descr1) is None # box1 and box3 can alias
+
+        h = HeapCache()
+        h.new(box1)
+        h.setfield(box1, descr1, box2)
+        assert h.getfield(box1, descr1) is box2
+        h.setfield(box3, descr1, box4)
+        assert h.getfield(box3, descr1) is box4
+        assert h.getfield(box1, descr1) is None # box1 and box3 can alias
+
+        h = HeapCache()
+        h.new(box1)
+        h.new(box3)
+        h.setfield(box1, descr1, box2)
+        assert h.getfield(box1, descr1) is box2
+        h.setfield(box3, descr1, box4)
+        assert h.getfield(box3, descr1) is box4
+        assert h.getfield(box1, descr1) is box2 # box1 and box3 cannot alias
+
 
     def test_heapcache_arrays(self):
         h = HeapCache()
diff --git a/pypy/jit/metainterp/test/test_tracingopts.py b/pypy/jit/metainterp/test/test_tracingopts.py
--- a/pypy/jit/metainterp/test/test_tracingopts.py
+++ b/pypy/jit/metainterp/test/test_tracingopts.py
@@ -423,8 +423,8 @@
             return a1.x + a2.x + a1.x + a2.x
         res = self.interp_operations(fn, [7])
         assert res == 2 * 7 + 2 * 6
-        self.check_operations_history(getfield_gc=2)
+        self.check_operations_history(getfield_gc=0)
         res = self.interp_operations(fn, [-7])
         assert res == 2 * -7 + 2 * -8
-        self.check_operations_history(getfield_gc=2)
+        self.check_operations_history(getfield_gc=0)
 


More information about the pypy-commit mailing list