Commits

Maciej Fijalkowski committed 8001b03

Implement a hint to call gen_store_back by hand. useful for generators

  • Participants
  • Parent commits a6063d1
  • Branches kill-gen-store-back-in

Comments (0)

Files changed (4)

rpython/jit/codewriter/jtransform.py

             op1 = SpaceOperation('str_guard_value', [op.args[0], c, descr],
                                  op.result)
             return [SpaceOperation('-live-', [], None), op1, None]
+        if hints.get('force_virtualizable'):
+            return SpaceOperation('hint_force_virtualizable', [op.args[0]], None)
         else:
             log.WARNING('ignoring hint %r at %r' % (hints, self.graph))
 

rpython/jit/metainterp/blackhole.py

     def bhimpl_force_virtualizable(cpu, v, descr):
         cpu.bh_force_virtualizable(v, descr)
 
+    @arguments("r")
+    def bhimpl_hint_force_virtualizable(r):
+        pass
+
     @arguments("cpu", "d", returns="r")
     def bhimpl_new(cpu, descr):
         return cpu.bh_new(descr)

rpython/jit/metainterp/pyjitpl.py

     opimpl_raw_load_i = _opimpl_raw_load
     opimpl_raw_load_f = _opimpl_raw_load
 
+    @arguments("box")
+    def opimpl_hint_force_virtualizable(self, box):
+        self.metainterp.gen_store_back_in_vable(box)
+
     @arguments("box", "descr", "descr", "orgpc")
     def opimpl_record_quasiimmut_field(self, box, fielddescr,
                                        mutatefielddescr, orgpc):
                                                         virtualizable)
             self.virtualizable_boxes.append(virtualizable_box)
 
+            vinfo = self.jitdriver_sd.virtualizable_info
+
+    def gen_store_back_in_vable(self, box):
+        vinfo = self.jitdriver_sd.virtualizable_info
+        if vinfo is not None:
+            # xxx only write back the fields really modified
+            vbox = self.virtualizable_boxes[-1]
+            if vbox is not box:
+                return # ignore the hint on non-standard virtualizable
+            for i in range(vinfo.num_static_extra_boxes):
+                fieldbox = self.virtualizable_boxes[i]
+                descr = vinfo.static_field_descrs[i]
+                self.execute_and_record(rop.SETFIELD_GC, descr, vbox, 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.virtualizable_boxes[i]
+                    i += 1
+                    self.execute_and_record(rop.SETARRAYITEM_GC, descr,
+                                            abox, ConstInt(j), itembox)
+            assert i + 1 == len(self.virtualizable_boxes)
+
+
     def replace_box(self, oldbox, newbox):
         assert isinstance(oldbox, Box)
         for frame in self.framestack:

rpython/jit/metainterp/test/test_virtualizable.py

 from rpython.jit.codewriter import heaptracker
 from rpython.jit.codewriter.policy import StopAtXPolicy
 from rpython.jit.metainterp.optimizeopt.test.test_util import LLtypeMixin
-from rpython.jit.metainterp.test.support import LLJitMixin, OOJitMixin
-from rpython.jit.metainterp.warmspot import get_translator
+from rpython.jit.metainterp.test.support import LLJitMixin
+from rpython.jit.metainterp.warmspot import get_translator, get_stats
+from rpython.jit.metainterp.resoperation import rop
 from rpython.rlib.jit import JitDriver, hint, dont_look_inside, promote, virtual_ref
 from rpython.rlib.rarithmetic import intmask
 from rpython.rtyper.annlowlevel import hlstr
         return lltype_to_annotation(lltype.Void)
 
     def specialize_call(self, hop):
-        op = self.instance    # the LLOp object that was called
         args_v = [hop.inputarg(hop.args_r[0], 0),
                   hop.inputconst(lltype.Void, hop.args_v[1].value),
                   hop.inputconst(lltype.Void, {})]
         res = self.meta_interp(f, [])
         assert res == f()
 
+    def test_force_virtualizable_by_hint(self):
+        class Frame(object):
+            _virtualizable_ = ['x']
+
+        driver = JitDriver(greens = [], reds = ['i', 'frame'],
+                           virtualizables = ['frame'])
+
+        def f(frame, i):
+            while i > 0:
+                driver.jit_merge_point(i=i, frame=frame)
+                i -= 1
+                frame.x += 1
+            hint(frame, force_virtualizable=True)
+
+        def main():
+            frame = Frame()
+            frame.x = 0
+            s = 0
+            for i in range(20):
+                f(frame, 4)
+                s += frame.x
+            return s
+
+        r = self.meta_interp(main, [])
+        assert r == main()
+        # fish the bridge
+        loop = get_stats().get_all_loops()[0]
+        d = loop.operations[-3].getdescr()
+        bridge = getattr(d, '_llgraph_bridge', None)
+        if bridge is not None:
+            l = [op for op in
+                 bridge.operations if op.getopnum() == rop.SETFIELD_GC]
+            assert len(l) == 2
 
 class TestLLtype(ExplicitVirtualizableTests,
                  ImplicitVirtualizableTests,