[pypy-svn] r71381 - in pypy/trunk/pypy/jit/metainterp: . test

arigo at codespeak.net arigo at codespeak.net
Sun Feb 21 15:31:57 CET 2010


Author: arigo
Date: Sun Feb 21 15:31:55 2010
New Revision: 71381

Modified:
   pypy/trunk/pypy/jit/metainterp/codewriter.py
   pypy/trunk/pypy/jit/metainterp/effectinfo.py
   pypy/trunk/pypy/jit/metainterp/optimizeopt.py
   pypy/trunk/pypy/jit/metainterp/pyjitpl.py
   pypy/trunk/pypy/jit/metainterp/test/test_codewriter.py
   pypy/trunk/pypy/jit/metainterp/test/test_optimizefindnode.py
   pypy/trunk/pypy/jit/metainterp/test/test_optimizeopt.py
Log:
Fix one of the issues that I've been fighting for since a week: the
accesses to the 'forced' field of virtualrefs is not recorded in the
effectinfo, thus from time to time invalid code is generated -- by
delaying the SETFIELD_GC for too long.  This is how force_virtual()
occasionally showed invalid VIRTUAL_REF structures: because the
structure was not fully updated yet.

This fix also simplifies things: the effectinfos that used to have the
flag 'forces_virtual_or_virtualizable' are now always stored just as
None.  I think that there is not a lot of benefits from optimizing field
reads or writes around calls to functions that can force anyway.

This is a merge from r71373+r71374 in branch/debug-vref2.


Modified: pypy/trunk/pypy/jit/metainterp/codewriter.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/codewriter.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/codewriter.py	Sun Feb 21 15:31:55 2010
@@ -337,10 +337,12 @@
         assert RESULT == FUNC.RESULT
         # ok
         if consider_effects_of is not None:
-            effectinfo = effectinfo_from_writeanalyze(
+            if self.virtualizable_analyzer.analyze(consider_effects_of):
+                effectinfo = None    # forcing virtualizable or vrefs
+            else:
+                effectinfo = effectinfo_from_writeanalyze(
                     self.readwrite_analyzer.analyze(consider_effects_of),
-                    self.cpu,
-                    self.virtualizable_analyzer.analyze(consider_effects_of))
+                    self.cpu)
             calldescr = self.cpu.calldescrof(FUNC, tuple(NON_VOID_ARGS), RESULT, effectinfo)
         else:
             calldescr = self.cpu.calldescrof(FUNC, tuple(NON_VOID_ARGS), RESULT)
@@ -1259,8 +1261,7 @@
             loopinvariant = getattr(func, "_jit_loop_invariant_", False)
             if pure or loopinvariant:
                 effectinfo = calldescr.get_extra_info()
-                assert (effectinfo is not None and
-                        not effectinfo.forces_virtual_or_virtualizable)
+                assert effectinfo is not None
         try:
             canraise = self.codewriter.raise_analyzer.can_raise(op)
         except lltype.DelayedPointer:

Modified: pypy/trunk/pypy/jit/metainterp/effectinfo.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/effectinfo.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/effectinfo.py	Sun Feb 21 15:31:55 2010
@@ -8,24 +8,20 @@
     _cache = {}
 
     def __new__(cls, readonly_descrs_fields,
-                write_descrs_fields, write_descrs_arrays,
-                forces_virtual_or_virtualizable=False):
+                write_descrs_fields, write_descrs_arrays):
         key = (frozenset(readonly_descrs_fields),
                frozenset(write_descrs_fields),
-               frozenset(write_descrs_arrays),
-               forces_virtual_or_virtualizable)
+               frozenset(write_descrs_arrays))
         if key in cls._cache:
             return cls._cache[key]
         result = object.__new__(cls)
         result.readonly_descrs_fields = readonly_descrs_fields
         result.write_descrs_fields = write_descrs_fields
         result.write_descrs_arrays = write_descrs_arrays
-        result.forces_virtual_or_virtualizable= forces_virtual_or_virtualizable
         cls._cache[key] = result
         return result
 
-def effectinfo_from_writeanalyze(effects, cpu,
-                                 forces_virtual_or_virtualizable=False):
+def effectinfo_from_writeanalyze(effects, cpu):
     from pypy.translator.backendopt.writeanalyze import top_set
     if effects is top_set:
         return None
@@ -61,8 +57,7 @@
             assert 0
     return EffectInfo(readonly_descrs_fields,
                       write_descrs_fields,
-                      write_descrs_arrays,
-                      forces_virtual_or_virtualizable)
+                      write_descrs_arrays)
 
 def consider_struct(TYPE, fieldname):
     if fieldType(TYPE, fieldname) is lltype.Void:

Modified: pypy/trunk/pypy/jit/metainterp/optimizeopt.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/optimizeopt.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/optimizeopt.py	Sun Feb 21 15:31:55 2010
@@ -1024,7 +1024,7 @@
         if (opnum == rop.CALL or
             opnum == rop.CALL_MAY_FORCE or
             opnum == rop.CALL_ASSEMBLER):
-            if opnum == rop.CALL_ASSEMBLER:
+            if opnum != rop.CALL:
                 effectinfo = None
             else:
                 effectinfo = op.descr.get_extra_info()

Modified: pypy/trunk/pypy/jit/metainterp/pyjitpl.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/pyjitpl.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/pyjitpl.py	Sun Feb 21 15:31:55 2010
@@ -1073,7 +1073,7 @@
 
     def do_residual_call(self, argboxes, descr, exc):
         effectinfo = descr.get_extra_info()
-        if effectinfo is None or effectinfo.forces_virtual_or_virtualizable:
+        if effectinfo is None:
             # residual calls require attention to keep virtualizables in-sync
             self.metainterp.vable_and_vrefs_before_residual_call()
             # xxx do something about code duplication

Modified: pypy/trunk/pypy/jit/metainterp/test/test_codewriter.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/test/test_codewriter.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/test/test_codewriter.py	Sun Feb 21 15:31:55 2010
@@ -306,7 +306,6 @@
         assert calldescrs[0][4] is not None
         assert not calldescrs[0][4].write_descrs_fields
         assert not calldescrs[0][4].write_descrs_arrays
-        assert not calldescrs[0][4].forces_virtual_or_virtualizable
 
     def test_oosend_look_inside_only_one(self):
         class A:
@@ -453,9 +452,9 @@
         effectinfo_g1 = calldescrs[1][4]
         effectinfo_g2 = calldescrs[2][4]
         effectinfo_h  = calldescrs[3][4]
-        assert effectinfo_g1.forces_virtual_or_virtualizable
-        assert effectinfo_g2.forces_virtual_or_virtualizable
-        assert not effectinfo_h.forces_virtual_or_virtualizable
+        assert effectinfo_g1 is None
+        assert effectinfo_g2 is None
+        assert effectinfo_h is not None
 
     def make_vrefinfo(self):
         from pypy.jit.metainterp.virtualref import VirtualRefInfo

Modified: pypy/trunk/pypy/jit/metainterp/test/test_optimizefindnode.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/test/test_optimizefindnode.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/test/test_optimizefindnode.py	Sun Feb 21 15:31:55 2010
@@ -111,9 +111,7 @@
                                       EffectInfo([], [adescr], [arraydescr]))
     readadescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
                                  EffectInfo([adescr], [], []))
-    mayforcevirtdescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
-                 EffectInfo([nextdescr], [], [],
-                            forces_virtual_or_virtualizable=True))
+    mayforcevirtdescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT)
     class LoopToken(AbstractDescr):
         pass
     asmdescr = LoopToken() # it can be whatever, it's not a descr though

Modified: pypy/trunk/pypy/jit/metainterp/test/test_optimizeopt.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/test/test_optimizeopt.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/test/test_optimizeopt.py	Sun Feb 21 15:31:55 2010
@@ -2564,7 +2564,6 @@
         #
         call_may_force(i1, descr=mayforcevirtdescr)
         guard_not_forced() [i1]
-        setfield_gc(p0, NULL, descr=nextdescr)
         #
         p1 = new_with_vtable(ConstClass(node_vtable))
         p1b = new_with_vtable(ConstClass(node_vtable))
@@ -2573,6 +2572,7 @@
         setfield_gc(p2, p1, descr=virtualforceddescr)
         setfield_gc(p2, -2, descr=virtualtokendescr)
         #
+        setfield_gc(p0, NULL, descr=nextdescr)
         jump(p0, i1)
         """
         self.optimize_loop(ops, 'Not, Not', expected)
@@ -2606,7 +2606,6 @@
         #
         call_may_force(i1, descr=mayforcevirtdescr)
         guard_not_forced(descr=fdescr) [p2, i1]
-        setfield_gc(p0, NULL, descr=nextdescr)
         #
         p1 = new_with_vtable(ConstClass(node_vtable))
         p1b = new_with_vtable(ConstClass(node_vtable))
@@ -2615,6 +2614,7 @@
         setfield_gc(p2, p1, descr=virtualforceddescr)
         setfield_gc(p2, -2, descr=virtualtokendescr)
         #
+        setfield_gc(p0, NULL, descr=nextdescr)
         jump(p0, i1)
         """
         # the point of this test is that 'i1' should show up in the fail_args
@@ -2664,6 +2664,32 @@
             where p1b is a node_vtable, valuedescr=i1
             ''')
 
+    def test_vref_nonvirtual_and_lazy_setfield(self):
+        self.make_fail_descr()
+        ops = """
+        [i1, p1]
+        p2 = virtual_ref(p1, 23)
+        escape(p2)
+        virtual_ref_finish(p2, p1)
+        call_may_force(i1, descr=mayforcevirtdescr)
+        guard_not_forced() [i1]
+        jump(i1, p1)
+        """
+        expected = """
+        [i1, p1]
+        i3 = force_token()
+        p2 = new_with_vtable(ConstClass(jit_virtual_ref_vtable))
+        setfield_gc(p2, i3, descr=virtualtokendescr)
+        setfield_gc(p2, 23, descr=virtualrefindexdescr)
+        escape(p2)
+        setfield_gc(p2, p1, descr=virtualforceddescr)
+        setfield_gc(p2, -2, descr=virtualtokendescr)
+        call_may_force(i1, descr=mayforcevirtdescr)
+        guard_not_forced() [i1]
+        jump(i1, p1)
+        """
+        self.optimize_loop(ops, 'Not, Not', expected)
+
 
 class TestOOtype(BaseTestOptimizeOpt, OOtypeMixin):
 



More information about the Pypy-commit mailing list