[pypy-svn] r69702 - in pypy/branch/virtual-forcing/pypy/jit/metainterp: . test

arigo at codespeak.net arigo at codespeak.net
Fri Nov 27 16:04:38 CET 2009


Author: arigo
Date: Fri Nov 27 16:04:37 2009
New Revision: 69702

Modified:
   pypy/branch/virtual-forcing/pypy/jit/metainterp/pyjitpl.py
   pypy/branch/virtual-forcing/pypy/jit/metainterp/test/test_basic.py
   pypy/branch/virtual-forcing/pypy/jit/metainterp/test/test_virtualizable.py
Log:
(pedronis, fijal?, arigo)
Simplify a bit virtualizables: when it escapes, then we abort tracing
instead of generating a trace with the escaped virtualizable.  Such
a trace is horribly horribly bad anyway.


Modified: pypy/branch/virtual-forcing/pypy/jit/metainterp/pyjitpl.py
==============================================================================
--- pypy/branch/virtual-forcing/pypy/jit/metainterp/pyjitpl.py	(original)
+++ pypy/branch/virtual-forcing/pypy/jit/metainterp/pyjitpl.py	Fri Nov 27 16:04:37 2009
@@ -1318,8 +1318,8 @@
         # residual calls require attention to keep virtualizables in-sync.
         # CALL_PURE doesn't need it because so far 'promote_virtualizable'
         # as an operation is enough to make the called function non-pure.
-        require_attention = (opnum == rop.CALL or opnum == rop.OOSEND)
-        if require_attention and not self.is_blackholing():
+        is_a_call = (opnum == rop.CALL or opnum == rop.OOSEND)
+        if is_a_call:
             self.before_residual_call()
         # execute the operation
         profiler = self.staticdata.profiler
@@ -1328,17 +1328,14 @@
         if self.is_blackholing():
             profiler.count_ops(opnum, BLACKHOLED_OPS)
         else:
-            if require_attention:
-                require_attention = self.after_residual_call()
             # check if the operation can be constant-folded away
             argboxes = list(argboxes)
             if rop._ALWAYS_PURE_FIRST <= opnum <= rop._ALWAYS_PURE_LAST:
                 resbox = self._record_helper_pure_varargs(opnum, resbox, descr, argboxes)
             else:
                 resbox = self._record_helper_nonpure_varargs(opnum, resbox, descr, argboxes)
-        # if we are blackholing require_attention has the initial meaning
-        if require_attention:
-            self.after_generate_residual_call()
+        if is_a_call:
+            self.after_residual_call()
         return resbox
 
     def _record_helper_pure(self, opnum, resbox, descr, *argboxes): 
@@ -1725,6 +1722,8 @@
         vinfo.clear_vable_rti(virtualizable)
 
     def before_residual_call(self):
+        if self.is_blackholing():
+            return
         vinfo = self.staticdata.virtualizable_info
         if vinfo is not None:
             virtualizable_box = self.virtualizable_boxes[-1]
@@ -1732,26 +1731,21 @@
             vinfo.tracing_before_residual_call(virtualizable)
 
     def after_residual_call(self):
-        vinfo = self.staticdata.virtualizable_info
-        if vinfo is not None:
-            virtualizable_box = self.virtualizable_boxes[-1]
-            virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box)
-            if vinfo.tracing_after_residual_call(virtualizable):
-                # This is after the residual call is done, but before it
-                # is actually generated.  We first generate a store-
-                # everything-back, *without actually performing it now*
-                # as it contains the old values (before the call)!
-                self.gen_store_back_in_virtualizable_no_perform()
-                return True    # must call after_generate_residual_call()
-        # otherwise, don't call after_generate_residual_call()
-        return False
-
-    def after_generate_residual_call(self):
-        # Called after generating a residual call, and only if
-        # after_residual_call() returned True, i.e. if code in the residual
-        # call causes the virtualizable to escape.  Reload the modified
-        # fields of the virtualizable.
-        self.gen_load_fields_from_virtualizable()
+        if self.is_blackholing():
+            vable_escapes = True
+        else:
+            vable_escapes = False
+            vinfo = self.staticdata.virtualizable_info
+            if vinfo is not None:
+                virtualizable_box = self.virtualizable_boxes[-1]
+                virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box)
+                if vinfo.tracing_after_residual_call(virtualizable):
+                    # We just did the residual call, and it shows that the
+                    # virtualizable escapes.
+                    self.switch_to_blackhole()
+                    vable_escapes = True
+        if vable_escapes:
+            self.load_fields_from_virtualizable()
 
     def handle_exception(self):
         etype = self.cpu.get_exception()
@@ -1809,27 +1803,17 @@
         virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box)
         vinfo.write_boxes(virtualizable, self.virtualizable_boxes)
 
-    def gen_load_fields_from_virtualizable(self):
+    def load_fields_from_virtualizable(self):
+        # Force a reload of the virtualizable fields into the local
+        # boxes (called only in escaping cases)
+        assert self.is_blackholing()
         vinfo = self.staticdata.virtualizable_info
         if vinfo is not None:
-            vbox = self.virtualizable_boxes[-1]
-            for i in range(vinfo.num_static_extra_boxes):
-                descr = vinfo.static_field_descrs[i]
-                fieldbox = self.execute_and_record(rop.GETFIELD_GC, descr,
-                                                   vbox)
-                self.virtualizable_boxes[i] = fieldbox
-            i = vinfo.num_static_extra_boxes
-            virtualizable = vinfo.unwrap_virtualizable_box(vbox)
-            for k in range(vinfo.num_arrays):
-                descr = vinfo.array_field_descrs[k]
-                abox = self.execute_and_record(rop.GETFIELD_GC, descr, vbox)
-                descr = vinfo.array_descrs[k]
-                for j in range(vinfo.get_array_length(virtualizable, k)):
-                    itembox = self.execute_and_record(rop.GETARRAYITEM_GC,
-                                                      descr, abox, ConstInt(j))
-                    self.virtualizable_boxes[i] = itembox
-                    i += 1
-            assert i + 1 == len(self.virtualizable_boxes)
+            virtualizable_box = self.virtualizable_boxes[-1]
+            virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box)
+            self.virtualizable_boxes = vinfo.read_boxes(self.cpu,
+                                                        virtualizable)
+            self.virtualizable_boxes.append(virtualizable_box)
 
     def gen_store_back_in_virtualizable(self):
         vinfo = self.staticdata.virtualizable_info
@@ -1853,29 +1837,6 @@
                                             abox, ConstInt(j), itembox)
             assert i + 1 == len(self.virtualizable_boxes)
 
-    def gen_store_back_in_virtualizable_no_perform(self):
-        vinfo = self.staticdata.virtualizable_info
-        # xxx only write back the fields really modified
-        vbox = self.virtualizable_boxes[-1]
-        for i in range(vinfo.num_static_extra_boxes):
-            fieldbox = self.virtualizable_boxes[i]
-            self.history.record(rop.SETFIELD_GC, [vbox, fieldbox], None,
-                                descr=vinfo.static_field_descrs[i])
-        i = vinfo.num_static_extra_boxes
-        virtualizable = vinfo.unwrap_virtualizable_box(vbox)
-        for k in range(vinfo.num_arrays):
-            abox = vinfo.BoxArray()
-            self.history.record(rop.GETFIELD_GC, [vbox], abox,
-                                descr=vinfo.array_field_descrs[k])
-            for j in range(vinfo.get_array_length(virtualizable, k)):
-                itembox = self.virtualizable_boxes[i]
-                i += 1
-                self.history.record(rop.SETARRAYITEM_GC,
-                                    [abox, ConstInt(j), itembox],
-                                    None,
-                                    descr=vinfo.array_descrs[k])
-        assert i + 1 == len(self.virtualizable_boxes)
-
     def replace_box(self, oldbox, newbox):
         for frame in self.framestack:
             boxes = frame.env

Modified: pypy/branch/virtual-forcing/pypy/jit/metainterp/test/test_basic.py
==============================================================================
--- pypy/branch/virtual-forcing/pypy/jit/metainterp/test/test_basic.py	(original)
+++ pypy/branch/virtual-forcing/pypy/jit/metainterp/test/test_basic.py	Fri Nov 27 16:04:37 2009
@@ -50,8 +50,8 @@
         assert get_stats().enter_count <= count
     def check_jumps(self, maxcount):
         assert get_stats().exec_jumps <= maxcount
-    def check_aborted_count(self, maxcount):
-        assert get_stats().aborted_count == maxcount
+    def check_aborted_count(self, count):
+        assert get_stats().aborted_count == count
 
     def meta_interp(self, *args, **kwds):
         kwds['CPUClass'] = self.CPUClass

Modified: pypy/branch/virtual-forcing/pypy/jit/metainterp/test/test_virtualizable.py
==============================================================================
--- pypy/branch/virtual-forcing/pypy/jit/metainterp/test/test_virtualizable.py	(original)
+++ pypy/branch/virtual-forcing/pypy/jit/metainterp/test/test_virtualizable.py	Fri Nov 27 16:04:37 2009
@@ -200,72 +200,6 @@
         assert res == 134
         self.check_loops(getfield_gc=1, setfield_gc=1)
 
-    def test_external_read_while_tracing(self):
-        myjitdriver = JitDriver(greens = [], reds = ['n', 'm', 'xy'],
-                                virtualizables = ['xy'])
-        class Outer:
-            pass
-        outer = Outer()
-        def ext():
-            xy = outer.xy
-            promote_virtualizable(xy, 'inst_x')
-            return xy.inst_x + 2
-        def f(n):
-            xy = self.setup()
-            xy.inst_x = 10
-            outer.xy = xy
-            m = 0
-            while n > 0:
-                myjitdriver.can_enter_jit(xy=xy, n=n, m=m)
-                myjitdriver.jit_merge_point(xy=xy, n=n, m=m)
-                promote_virtualizable(xy, 'inst_x')
-                xy.inst_x = n + 9998     # virtualized away
-                m += ext()               # 2x setfield_gc, 2x getfield_gc
-                promote_virtualizable(xy, 'inst_x')
-                xy.inst_x = 10           # virtualized away
-                n -= 1
-            return m
-        assert f(20) == 10000*20 + (20*21)/2
-        res = self.meta_interp(f, [20], policy=StopAtXPolicy(ext))
-        assert res == 10000*20 + (20*21)/2
-        # there are no getfields because the optimizer gets rid of them
-        self.check_loops(call=1, getfield_gc=0, setfield_gc=2)
-        # xxx for now a call that forces the virtualizable during tracing
-        # is supposed to always force it later too.
-
-    def test_external_write_while_tracing(self):
-        myjitdriver = JitDriver(greens = [], reds = ['n', 'm', 'xy'],
-                                virtualizables = ['xy'])
-        class Outer:
-            pass
-        outer = Outer()
-        def ext():
-            xy = outer.xy
-            promote_virtualizable(xy, 'inst_x')
-            xy.inst_x += 2
-        def f(n):
-            xy = self.setup()
-            xy.inst_x = 10
-            outer.xy = xy
-            m = 0
-            while n > 0:
-                myjitdriver.can_enter_jit(xy=xy, n=n, m=m)
-                myjitdriver.jit_merge_point(xy=xy, n=n, m=m)
-                promote_virtualizable(xy, 'inst_x')
-                xy.inst_x = n + 9998     # virtualized away
-                ext()                    # 2x setfield_gc, 2x getfield_gc
-                promote_virtualizable(xy, 'inst_x')
-                m += xy.inst_x           # virtualized away
-                n -= 1
-            return m
-        res = self.meta_interp(f, [20], policy=StopAtXPolicy(ext))
-        assert res == f(20)
-        # the getfield_gc of inst_node is optimized away, because ext does not
-        # write to it
-        self.check_loops(call=1, getfield_gc=1, setfield_gc=2)
-        # xxx for now a call that forces the virtualizable during tracing
-        # is supposed to always force it later too.
-
     # ------------------------------
 
     XY2 = lltype.GcStruct(
@@ -649,7 +583,8 @@
 
         res = self.meta_interp(f, [123], policy=StopAtXPolicy(g))
         assert res == f(123)
-
+        self.check_aborted_count(2)
+        self.check_tree_loop_count(0)
 
     def test_external_write(self):
         jitdriver = JitDriver(greens = [], reds = ['frame'],
@@ -680,6 +615,8 @@
 
         res = self.meta_interp(f, [240], policy=StopAtXPolicy(g))
         assert res == f(240)
+        self.check_aborted_count(3)
+        self.check_tree_loop_count(0)
 
     def test_external_read_sometimes(self):
         py.test.skip("known bug: access the frame in a residual call but"



More information about the Pypy-commit mailing list