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

arigo at codespeak.net arigo at codespeak.net
Thu Feb 25 18:23:54 CET 2010


Author: arigo
Date: Thu Feb 25 18:23:52 2010
New Revision: 71499

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:
Merge branch/debug-vref3:

Revert r71374, as it appears that there are cases in which
the performance matters -- i.e. the fact that some fields
may remain virtual across a call to a function that can
force virtualrefs or virtualizables.  (According to fijal
he sees a 30% difference on one benchmark.)

Fix it differently in optimizeopt.py, by saying that calls
to such functions always force at least the 'forced' field
of virtualrefs (but not necessarily other fields).



Modified: pypy/trunk/pypy/jit/metainterp/codewriter.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/codewriter.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/codewriter.py	Thu Feb 25 18:23:52 2010
@@ -337,12 +337,10 @@
         assert RESULT == FUNC.RESULT
         # ok
         if consider_effects_of is not None:
-            if self.virtualizable_analyzer.analyze(consider_effects_of):
-                effectinfo = None    # forcing virtualizable or vrefs
-            else:
-                effectinfo = effectinfo_from_writeanalyze(
+            effectinfo = effectinfo_from_writeanalyze(
                     self.readwrite_analyzer.analyze(consider_effects_of),
-                    self.cpu)
+                    self.cpu,
+                    self.virtualizable_analyzer.analyze(consider_effects_of))
             calldescr = self.cpu.calldescrof(FUNC, tuple(NON_VOID_ARGS), RESULT, effectinfo)
         else:
             calldescr = self.cpu.calldescrof(FUNC, tuple(NON_VOID_ARGS), RESULT)
@@ -1261,7 +1259,8 @@
             loopinvariant = getattr(func, "_jit_loop_invariant_", False)
             if pure or loopinvariant:
                 effectinfo = calldescr.get_extra_info()
-                assert effectinfo is not None
+                assert (effectinfo is not None and
+                        not effectinfo.forces_virtual_or_virtualizable)
         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	Thu Feb 25 18:23:52 2010
@@ -8,20 +8,24 @@
     _cache = {}
 
     def __new__(cls, readonly_descrs_fields,
-                write_descrs_fields, write_descrs_arrays):
+                write_descrs_fields, write_descrs_arrays,
+                forces_virtual_or_virtualizable=False):
         key = (frozenset(readonly_descrs_fields),
                frozenset(write_descrs_fields),
-               frozenset(write_descrs_arrays))
+               frozenset(write_descrs_arrays),
+               forces_virtual_or_virtualizable)
         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):
+def effectinfo_from_writeanalyze(effects, cpu,
+                                 forces_virtual_or_virtualizable=False):
     from pypy.translator.backendopt.writeanalyze import top_set
     if effects is top_set:
         return None
@@ -57,7 +61,8 @@
             assert 0
     return EffectInfo(readonly_descrs_fields,
                       write_descrs_fields,
-                      write_descrs_arrays)
+                      write_descrs_arrays,
+                      forces_virtual_or_virtualizable)
 
 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	Thu Feb 25 18:23:52 2010
@@ -794,7 +794,7 @@
         # typically a PyPy PyFrame, and now is the end of its execution, so
         # forcing it now does not have catastrophic effects.
         vrefinfo = self.metainterp_sd.virtualref_info
-        assert op.args[1].nonnull()
+        # op.args[1] should really never point to null here
         # - set 'forced' to point to the real object
         op1 = ResOperation(rop.SETFIELD_GC, op.args, None,
                           descr = vrefinfo.descr_forced)
@@ -1024,7 +1024,7 @@
         if (opnum == rop.CALL or
             opnum == rop.CALL_MAY_FORCE or
             opnum == rop.CALL_ASSEMBLER):
-            if opnum != rop.CALL:
+            if opnum == rop.CALL_ASSEMBLER:
                 effectinfo = None
             else:
                 effectinfo = op.descr.get_extra_info()
@@ -1044,6 +1044,11 @@
                         del self.cached_arrayitems[arraydescr]
                     except KeyError:
                         pass
+                if effectinfo.forces_virtual_or_virtualizable:
+                    vrefinfo = self.optimizer.metainterp_sd.virtualref_info
+                    self.force_lazy_setfield(vrefinfo.descr_forced)
+                    # ^^^ we only need to force this field; the other fields
+                    # of virtualref_info and virtualizable_info are not gcptrs.
                 return
             self.force_all_lazy_setfields()
         elif op.is_final() or (not we_are_translated() and

Modified: pypy/trunk/pypy/jit/metainterp/pyjitpl.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/pyjitpl.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/pyjitpl.py	Thu Feb 25 18:23:52 2010
@@ -1073,7 +1073,7 @@
 
     def do_residual_call(self, argboxes, descr, exc):
         effectinfo = descr.get_extra_info()
-        if effectinfo is None:
+        if effectinfo is None or effectinfo.forces_virtual_or_virtualizable:
             # 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	Thu Feb 25 18:23:52 2010
@@ -306,6 +306,7 @@
         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:
@@ -452,9 +453,9 @@
         effectinfo_g1 = calldescrs[1][4]
         effectinfo_g2 = calldescrs[2][4]
         effectinfo_h  = calldescrs[3][4]
-        assert effectinfo_g1 is None
-        assert effectinfo_g2 is None
-        assert effectinfo_h is not None
+        assert effectinfo_g1.forces_virtual_or_virtualizable
+        assert effectinfo_g2.forces_virtual_or_virtualizable
+        assert not effectinfo_h.forces_virtual_or_virtualizable
 
     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	Thu Feb 25 18:23:52 2010
@@ -111,7 +111,9 @@
                                       EffectInfo([], [adescr], [arraydescr]))
     readadescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
                                  EffectInfo([adescr], [], []))
-    mayforcevirtdescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT)
+    mayforcevirtdescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
+                 EffectInfo([nextdescr], [], [],
+                            forces_virtual_or_virtualizable=True))
     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	Thu Feb 25 18:23:52 2010
@@ -2565,14 +2565,13 @@
         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))
         setfield_gc(p1b, 252, descr=valuedescr)
         setfield_gc(p1, p1b, descr=nextdescr)
         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)
@@ -2607,14 +2606,13 @@
         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))
         setfield_gc(p1b, i1, descr=valuedescr)
         setfield_gc(p1, p1b, descr=nextdescr)
         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 +2662,34 @@
             where p1b is a node_vtable, valuedescr=i1
             ''')
 
+    def test_vref_virtual_after_finish(self):
+        self.make_fail_descr()
+        ops = """
+        [i1]
+        p1 = new_with_vtable(ConstClass(node_vtable))
+        p2 = virtual_ref(p1, 7)
+        escape(p2)
+        virtual_ref_finish(p2, p1)
+        call_may_force(i1, descr=mayforcevirtdescr)
+        guard_not_forced() []
+        jump(i1)
+        """
+        expected = """
+        [i1]
+        i3 = force_token()
+        p2 = new_with_vtable(ConstClass(jit_virtual_ref_vtable))
+        setfield_gc(p2, i3, descr=virtualtokendescr)
+        setfield_gc(p2, 7, descr=virtualrefindexdescr)
+        escape(p2)
+        p1 = new_with_vtable(ConstClass(node_vtable))
+        setfield_gc(p2, p1, descr=virtualforceddescr)
+        setfield_gc(p2, -2, descr=virtualtokendescr)
+        call_may_force(i1, descr=mayforcevirtdescr)
+        guard_not_forced() []
+        jump(i1)
+        """
+        self.optimize_loop(ops, 'Not', expected)
+
     def test_vref_nonvirtual_and_lazy_setfield(self):
         self.make_fail_descr()
         ops = """



More information about the Pypy-commit mailing list