[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