[pypy-svn] r65964 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test

arigo at codespeak.net arigo at codespeak.net
Thu Jun 25 16:55:36 CEST 2009


Author: arigo
Date: Thu Jun 25 16:55:31 2009
New Revision: 65964

Modified:
   pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py
   pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py
   pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py
Log:
Handle correctly the situation where we access another
virtualizable (i.e. another frame) than the 'standard' one.


Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py	(original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py	Thu Jun 25 16:55:31 2009
@@ -813,14 +813,16 @@
             if self.is_virtualizable_getset(op):
                 vinfo = self.codewriter.metainterp_sd.virtualizable_info
                 index = vinfo.static_field_to_extra_box[op.args[1].value]
-                self.emit('getfield_vable', index)
+                self.emit('getfield_vable',
+                          self.var_position(v_inst),
+                          index)
                 self.register_var(op.result)
                 return
         except VirtualizableArrayField:
             # xxx hack hack hack
             vinfo = self.codewriter.metainterp_sd.virtualizable_info
-            index = vinfo.array_field_counter[op.args[1].value]
-            self.vable_array_vars[op.result] = index
+            arrayindex = vinfo.array_field_counter[op.args[1].value]
+            self.vable_array_vars[op.result] = (op.args[0], arrayindex)
             return
         # check for deepfrozen structures that force constant-folding
         if deref(v_inst.concretetype)._hints.get('immutable'):
@@ -851,7 +853,10 @@
         if self.is_virtualizable_getset(op):
             vinfo = self.codewriter.metainterp_sd.virtualizable_info
             index = vinfo.static_field_to_extra_box[op.args[1].value]
-            self.emit('setfield_vable', index, self.var_position(v_value))
+            self.emit('setfield_vable',
+                      self.var_position(v_inst),
+                      index,
+                      self.var_position(v_value))
             return
         argname = getattr(deref(v_inst.concretetype), '_gckind', 'gc')
         self.emit('setfield_%s' % (argname,))
@@ -868,8 +873,9 @@
                 deref(op.args[0].concretetype)._hints.get('typeptr'))
 
     def is_virtualizable_getset(self, op):
-        # XXX check more carefully; for now assumes that every access of
-        # an object of exactly the type VTYPEPTR is a virtualizable access
+        # every access of an object of exactly the type VTYPEPTR is
+        # likely to be a virtualizable access, but we still have to
+        # check it in pyjitpl.py.
         vinfo = self.codewriter.metainterp_sd.virtualizable_info
         if vinfo is None:
             return False
@@ -896,8 +902,10 @@
         if self._array_of_voids(ARRAY):
             return
         if op.args[0] in self.vable_array_vars:     # for virtualizables
+            (v_base, arrayindex) = self.vable_array_vars[op.args[0]]
             self.emit('getarrayitem_vable',
-                      self.vable_array_vars[op.args[0]],
+                      self.var_position(v_base),
+                      arrayindex,
                       self.var_position(op.args[1]))
             self.register_var(op.result)
             return
@@ -915,8 +923,10 @@
         if self._array_of_voids(ARRAY):
             return
         if op.args[0] in self.vable_array_vars:     # for virtualizables
+            (v_base, arrayindex) = self.vable_array_vars[op.args[0]]
             self.emit('setarrayitem_vable',
-                      self.vable_array_vars[op.args[0]],
+                      self.var_position(v_base),
+                      arrayindex,
                       self.var_position(op.args[1]),
                       self.var_position(op.args[2]))
             return
@@ -931,8 +941,10 @@
         ARRAY = op.args[0].concretetype.TO
         assert ARRAY._gckind == 'gc'
         if op.args[0] in self.vable_array_vars:     # for virtualizables
+            (v_base, arrayindex) = self.vable_array_vars[op.args[0]]
             self.emit('arraylen_vable',
-                      self.vable_array_vars[op.args[0]])
+                      self.var_position(v_base),
+                      arrayindex)
             self.register_var(op.result)
             return
         # normal case follows
@@ -1191,8 +1203,10 @@
         #
         if oopspec_name == 'list.setitem':
             if args[0] in self.vable_array_vars:     # virtualizable array
+                (v_base, arrayindex) = self.vable_array_vars[args[0]]
                 self.emit('setarrayitem_vable',
-                          self.vable_array_vars[args[0]],
+                          self.var_position(v_base),
+                          arrayindex,
                           self.var_position(args[1]),
                           self.var_position(args[2]))
                 return True
@@ -1210,8 +1224,10 @@
         if (oopspec_name == 'list.len' or
             oopspec_name == 'list.len_foldable'):
             if args[0] in self.vable_array_vars:     # virtualizable array
+                (v_base, arrayindex) = self.vable_array_vars[args[0]]
                 self.emit('arraylen_vable',
-                          self.vable_array_vars[args[0]])
+                          self.var_position(v_base),
+                          arrayindex)
                 self.register_var(op.result)
                 return True
             self.emit('arraylen_gc')
@@ -1224,8 +1240,10 @@
 
     def handle_list_getitem(self, op, arraydescr, args, opname):
         if args[0] in self.vable_array_vars:     # virtualizable array
+            (v_base, arrayindex) = self.vable_array_vars[args[0]]
             self.emit('getarrayitem_vable',
-                      self.vable_array_vars[args[0]],
+                      self.var_position(v_base),
+                      arrayindex,
                       self.var_position(args[1]))
             self.register_var(op.result)
             return True

Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py	(original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py	Thu Jun 25 16:55:31 2009
@@ -453,13 +453,44 @@
     def opimpl_setfield_raw(self, box, fielddesc, valuebox):
         self.execute(rop.SETFIELD_RAW, [box, valuebox], descr=fielddesc)
 
-    @arguments("int")
-    def opimpl_getfield_vable(self, index):
+    def _nonstandard_virtualizable(self, pc, box):
+        # returns True if 'box' is actually not the "standard" virtualizable
+        # that is stored in metainterp.virtualizable_boxes[-1]
+        standard_box = self.metainterp.virtualizable_boxes[-1]
+        if standard_box is box:
+            return False
+        eqbox = self.metainterp.execute_and_record(rop.OOIS,
+                                                   [box, standard_box])
+        eqbox = self.implement_guard_value(pc, eqbox)
+        return not eqbox.getint()
+
+    def _get_virtualizable_field_descr(self, index):
+        vinfo = self.metainterp.staticdata.virtualizable_info
+        return vinfo.static_field_descrs[index]
+
+    def _get_virtualizable_array_field_descr(self, index):
+        vinfo = self.metainterp.staticdata.virtualizable_info
+        return vinfo.array_field_descrs[index]
+
+    def _get_virtualizable_array_descr(self, index):
+        vinfo = self.metainterp.staticdata.virtualizable_info
+        return vinfo.array_descrs[index]
+
+    @arguments("orgpc", "box", "int")
+    def opimpl_getfield_vable(self, pc, basebox, index):
+        if self._nonstandard_virtualizable(pc, basebox):
+            self.execute(rop.GETFIELD_GC, [basebox],
+                         descr=self._get_virtualizable_field_descr(index))
+            return
         self.metainterp.check_synchronized_virtualizable()
         resbox = self.metainterp.virtualizable_boxes[index]
         self.make_result_box(resbox)
-    @arguments("int", "box")
-    def opimpl_setfield_vable(self, index, valuebox):
+    @arguments("orgpc", "box", "int", "box")
+    def opimpl_setfield_vable(self, pc, basebox, index, valuebox):
+        if self._nonstandard_virtualizable(pc, basebox):
+            self.execute(rop.SETFIELD_GC, [basebox, valuebox],
+                         descr=self._get_virtualizable_field_descr(index))
+            return
         self.metainterp.virtualizable_boxes[index] = valuebox
         self.metainterp.synchronize_virtualizable()
         # XXX only the index'th field needs to be synchronized, really
@@ -475,20 +506,45 @@
         assert 0 <= index < vinfo.get_array_length(virtualizable, arrayindex)
         return vinfo.get_index_in_array(virtualizable, arrayindex, index)
 
-    @arguments("orgpc", "int", "box")
-    def opimpl_getarrayitem_vable(self, pc, arrayindex, indexbox):
+    @arguments("orgpc", "box", "int", "box")
+    def opimpl_getarrayitem_vable(self, pc, basebox, arrayindex, indexbox):
+        if self._nonstandard_virtualizable(pc, basebox):
+            arraybox = self.metainterp.execute_and_record(
+                rop.GETFIELD_GC, [basebox],
+                descr=self._get_virtualizable_array_field_descr(arrayindex))
+            self.execute(
+                rop.GETARRAYITEM_GC, [arraybox, indexbox],
+                descr=self._get_virtualizable_array_descr(arrayindex))
+            return
         self.metainterp.check_synchronized_virtualizable()
         index = self._get_arrayitem_vable_index(pc, arrayindex, indexbox)
         resbox = self.metainterp.virtualizable_boxes[index]
         self.make_result_box(resbox)
-    @arguments("orgpc", "int", "box", "box")
-    def opimpl_setarrayitem_vable(self, pc, arrayindex, indexbox, valuebox):
+    @arguments("orgpc", "box", "int", "box", "box")
+    def opimpl_setarrayitem_vable(self, pc, basebox, arrayindex, indexbox,
+                                  valuebox):
+        if self._nonstandard_virtualizable(pc, basebox):
+            arraybox = self.metainterp.execute_and_record(
+                rop.GETFIELD_GC, [basebox],
+                descr=self._get_virtualizable_array_field_descr(arrayindex))
+            self.execute(
+                rop.SETARRAYITEM_GC, [arraybox, indexbox, valuebox],
+                descr=self._get_virtualizable_array_descr(arrayindex))
+            return
         index = self._get_arrayitem_vable_index(pc, arrayindex, indexbox)
         self.metainterp.virtualizable_boxes[index] = valuebox
         self.metainterp.synchronize_virtualizable()
         # XXX only the index'th field needs to be synchronized, really
-    @arguments("int")
-    def opimpl_arraylen_vable(self, arrayindex):
+    @arguments("orgpc", "box", "int")
+    def opimpl_arraylen_vable(self, pc, basebox, arrayindex):
+        if self._nonstandard_virtualizable(pc, basebox):
+            arraybox = self.metainterp.execute_and_record(
+                rop.GETFIELD_GC, [basebox],
+                descr=self._get_virtualizable_array_field_descr(arrayindex))
+            self.execute(
+                rop.ARRAYLEN_GC, [arraybox],
+                descr=self._get_virtualizable_array_descr(arrayindex))
+            return
         vinfo = self.metainterp.staticdata.virtualizable_info
         virtualizable_box = self.metainterp.virtualizable_boxes[-1]
         virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box)

Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py	(original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py	Thu Jun 25 16:55:31 2009
@@ -151,6 +151,28 @@
         assert res == 50 * 4
         self.check_loops(getfield_gc=0, setfield_gc=0)
 
+    def test_double_frame(self):
+        myjitdriver = JitDriver(greens = [], reds = ['n', 'xy', 'other'],
+                                virtualizables = ['xy'])
+        def f(n):
+            xy = self.setup()
+            xy.inst_x = 10
+            other = self.setup()
+            other.inst_x = 15
+            while n > 0:
+                myjitdriver.can_enter_jit(xy=xy, n=n, other=other)
+                myjitdriver.jit_merge_point(xy=xy, n=n, other=other)
+                promote_virtualizable(lltype.Void, other, 'inst_x')
+                value = other.inst_x         # getfield_gc
+                other.inst_x = value + 1     # setfield_gc
+                promote_virtualizable(lltype.Void, xy, 'inst_x')
+                xy.inst_x = value + 100      # virtualized away
+                n -= 1
+            return xy.inst_x
+        res = self.meta_interp(f, [20])
+        assert res == 134
+        self.check_loops(getfield_gc=1, setfield_gc=1)
+
     # ------------------------------
 
     XY2 = lltype.GcStruct(
@@ -283,6 +305,42 @@
         self.check_loops(getfield_gc=0, setfield_gc=0,
                          getarrayitem_gc=0, arraylen_gc=1, call=1)
 
+    def test_double_frame_array(self):
+        myjitdriver = JitDriver(greens = [], reds = ['n', 'xy2', 'other'],
+                                virtualizables = ['xy2'])
+        ARRAY = lltype.GcArray(lltype.Signed)
+        def f(n):
+            xy2 = self.setup2()
+            xy2.inst_x = 10
+            xy2.inst_l1 = lltype.malloc(ARRAY, 1)
+            xy2.inst_l1[0] = 1982731
+            xy2.inst_l2 = lltype.malloc(ARRAY, 1)
+            xy2.inst_l2[0] = 10000
+            other = self.setup2()
+            other.inst_x = 15
+            other.inst_l1 = lltype.malloc(ARRAY, 2)
+            other.inst_l1[0] = 189182
+            other.inst_l1[1] = 58421
+            other.inst_l2 = lltype.malloc(ARRAY, 2)
+            other.inst_l2[0] = 181
+            other.inst_l2[1] = 189
+            while n > 0:
+                myjitdriver.can_enter_jit(xy2=xy2, n=n, other=other)
+                myjitdriver.jit_merge_point(xy2=xy2, n=n, other=other)
+                promote_virtualizable(lltype.Void, other, 'inst_l2')
+                length = len(other.inst_l2)       # getfield_gc/arraylen_gc
+                value = other.inst_l2[0]          # getfield_gc/getarrayitem_gc
+                other.inst_l2[0] = value + length # getfield_gc/setarrayitem_gc
+                promote_virtualizable(lltype.Void, xy2, 'inst_l2')
+                xy2.inst_l2[0] = value + 100      # virtualized away
+                n -= 1
+            return xy2.inst_l2[0]
+        expected = f(20)
+        res = self.meta_interp(f, [20])
+        assert res == expected
+        self.check_loops(getfield_gc=3, setfield_gc=0,
+                         arraylen_gc=1, getarrayitem_gc=1, setarrayitem_gc=1)
+
     # ------------------------------
 
     XY2SUB = lltype.GcStruct(



More information about the Pypy-commit mailing list