[pypy-svn] r70066 - in pypy/branch/virtual-forcing/pypy/jit: backend/test metainterp metainterp/test
arigo at codespeak.net
arigo at codespeak.net
Fri Dec 11 12:10:22 CET 2009
Author: arigo
Date: Fri Dec 11 12:10:21 2009
New Revision: 70066
Modified:
pypy/branch/virtual-forcing/pypy/jit/backend/test/support.py
pypy/branch/virtual-forcing/pypy/jit/metainterp/optimizeopt.py
pypy/branch/virtual-forcing/pypy/jit/metainterp/pyjitpl.py
pypy/branch/virtual-forcing/pypy/jit/metainterp/test/test_basic.py
pypy/branch/virtual-forcing/pypy/jit/metainterp/test/test_virtualref.py
Log:
Finally found a simple workaround for the next issue in the pypy-c-jit.
It's quite a bit hackish but it is easy because it works purely locally
in pyjitpl.py.
Modified: pypy/branch/virtual-forcing/pypy/jit/backend/test/support.py
==============================================================================
--- pypy/branch/virtual-forcing/pypy/jit/backend/test/support.py (original)
+++ pypy/branch/virtual-forcing/pypy/jit/backend/test/support.py Fri Dec 11 12:10:21 2009
@@ -100,6 +100,9 @@
def check_aborted_count(self, *args, **kwds):
pass
+ def check_aborted_count_at_least(self, *args, **kwds):
+ pass
+
def interp_operations(self, *args, **kwds):
py.test.skip("interp_operations test skipped")
Modified: pypy/branch/virtual-forcing/pypy/jit/metainterp/optimizeopt.py
==============================================================================
--- pypy/branch/virtual-forcing/pypy/jit/metainterp/optimizeopt.py (original)
+++ pypy/branch/virtual-forcing/pypy/jit/metainterp/optimizeopt.py Fri Dec 11 12:10:21 2009
@@ -750,7 +750,7 @@
descr_virtualref_index = virtualref.get_descr_virtualref_index(cpu)
#
# Replace the VIRTUAL_REF operation with a virtual structure of type
- # 'vref.JIT_VIRTUAL_REF'. The virtual structure may be forced soon,
+ # 'jit_virtual_ref'. The jit_virtual_ref structure may be forced soon,
# but the point is that doing so does not force the original structure.
op = ResOperation(rop.NEW_WITH_VTABLE, [c_cls], op.result)
vrefvalue = self.make_virtual(c_cls, op.result, op)
Modified: pypy/branch/virtual-forcing/pypy/jit/metainterp/pyjitpl.py
==============================================================================
--- pypy/branch/virtual-forcing/pypy/jit/metainterp/pyjitpl.py (original)
+++ pypy/branch/virtual-forcing/pypy/jit/metainterp/pyjitpl.py Fri Dec 11 12:10:21 2009
@@ -917,8 +917,30 @@
lastbox = metainterp.virtualref_boxes.pop()
assert box.getref_base() == lastbox.getref_base()
if not metainterp.is_blackholing():
+ if vrefbox.getref_base():
+ metainterp.history.record(rop.VIRTUAL_REF_FINISH,
+ [vrefbox, lastbox], None)
+
+ def cancel_tracking_virtual_ref(self, argboxes):
+ # if the most recent vref points to an object that escapes in a
+ # residual call (i.e. is in argboxes), then cancel its special
+ # treatment and allow it to escape. XXX check and document more, or
+ # find another approach -- see test_recursive_call in test_virtualref
+ metainterp = self.metainterp
+ if metainterp.is_blackholing():
+ return
+ if len(metainterp.virtualref_boxes) == 0:
+ return
+ lastbox = metainterp.virtualref_boxes[-2]
+ if lastbox not in argboxes:
+ return
+ vrefbox = metainterp.virtualref_boxes[-1]
+ if vrefbox.getref_base():
metainterp.history.record(rop.VIRTUAL_REF_FINISH,
[vrefbox, lastbox], None)
+ ConstRef = metainterp.cpu.ts.ConstRef
+ nullbox = ConstRef(ConstRef.value)
+ metainterp.virtualref_boxes[-1] = nullbox
# ------------------------------
@@ -1023,6 +1045,7 @@
def do_residual_call(self, argboxes, descr, exc):
effectinfo = descr.get_extra_info()
if effectinfo is None or effectinfo.forces_virtual_or_virtualizable:
+ self.cancel_tracking_virtual_ref(argboxes)
# residual calls require attention to keep virtualizables in-sync
self.metainterp.vable_and_vrefs_before_residual_call()
# xxx do something about code duplication
@@ -1433,6 +1456,7 @@
self.staticdata.stats.aborted()
self.staticdata.profiler.end_tracing()
self.staticdata.profiler.start_blackhole()
+ switch_to_blackhole._dont_inline_ = True
def switch_to_blackhole_if_trace_too_long(self):
if not self.is_blackholing():
@@ -1766,9 +1790,11 @@
for i in range(1, len(self.virtualref_boxes), 2):
vrefbox = self.virtualref_boxes[i]
vref = vrefbox.getref_base()
+ if not vref:
+ continue
virtualref.tracing_before_residual_call(vref)
- # the FORCE_TOKEN is already set at runtime in each vrefs when
- # they are created, by optimizeopt.py.
+ # the FORCE_TOKEN is already set at runtime in each vref when
+ # it is created, by optimizeopt.py.
#
vinfo = self.staticdata.virtualizable_info
if vinfo is not None:
@@ -1791,6 +1817,8 @@
for i in range(1, len(self.virtualref_boxes), 2):
vrefbox = self.virtualref_boxes[i]
vref = vrefbox.getref_base()
+ if not vref:
+ continue
if virtualref.tracing_after_residual_call(vref):
# this vref escaped during CALL_MAY_FORCE.
escapes = True
@@ -1849,6 +1877,8 @@
for i in range(0, len(virtualref_boxes), 2):
virtualbox = virtualref_boxes[i]
vrefbox = virtualref_boxes[i+1]
+ if not vrefbox.getref_base():
+ continue
virtualref.continue_tracing(vrefbox.getref_base(),
virtualbox.getref_base())
#
Modified: pypy/branch/virtual-forcing/pypy/jit/metainterp/test/test_basic.py
==============================================================================
--- pypy/branch/virtual-forcing/pypy/jit/metainterp/test/test_basic.py (original)
+++ pypy/branch/virtual-forcing/pypy/jit/metainterp/test/test_basic.py Fri Dec 11 12:10:21 2009
@@ -52,6 +52,8 @@
assert get_stats().exec_jumps <= maxcount
def check_aborted_count(self, count):
assert get_stats().aborted_count == count
+ def check_aborted_count_at_least(self, count):
+ assert get_stats().aborted_count >= count
def meta_interp(self, *args, **kwds):
kwds['CPUClass'] = self.CPUClass
Modified: pypy/branch/virtual-forcing/pypy/jit/metainterp/test/test_virtualref.py
==============================================================================
--- pypy/branch/virtual-forcing/pypy/jit/metainterp/test/test_virtualref.py (original)
+++ pypy/branch/virtual-forcing/pypy/jit/metainterp/test/test_virtualref.py Fri Dec 11 12:10:21 2009
@@ -106,7 +106,7 @@
# we call virtual_ref(x).)
exctx.topframeref = vref_None
virtual_ref_finish(x)
- # 'vref' is allowed to escape, and even be forced, even after
+ # 'x' is allowed to escape, and even be forced, even after
# the call to finish().
g(vref)
n -= 1
@@ -144,6 +144,7 @@
res = self.meta_interp(f, [-4])
assert res == 16 * 19
self.check_loops({}) # because we aborted tracing
+ self.check_aborted_count_at_least(1)
def test_simple_no_access(self):
myjitdriver = JitDriver(greens = [], reds = ['n'])
@@ -208,6 +209,7 @@
#
self.meta_interp(f, [15])
self.check_loops({}) # because we aborted tracing
+ self.check_aborted_count_at_least(1)
def test_simple_force_sometimes(self):
myjitdriver = JitDriver(greens = [], reds = ['n'])
@@ -344,7 +346,6 @@
exctx = ExCtx()
#
def f(n):
- later = None
while n > 0:
myjitdriver.can_enter_jit(n=n)
myjitdriver.jit_merge_point(n=n)
@@ -359,6 +360,70 @@
res = self.meta_interp(f, [15])
assert res == 1
self.check_loops({}) # because we aborted tracing
+ self.check_aborted_count_at_least(1)
+
+ def test_recursive_call_1(self):
+ myjitdriver = JitDriver(greens = [], reds = ['n', 'frame', 'rec'])
+ #
+ class XY:
+ pass
+ class ExCtx:
+ pass
+ exctx = ExCtx()
+ #
+ def f(frame, n, reclevel):
+ while n > 0:
+ myjitdriver.can_enter_jit(n=n, frame=frame, rec=reclevel)
+ myjitdriver.jit_merge_point(n=n, frame=frame, rec=reclevel)
+ if reclevel == 0:
+ return n
+ xy = XY()
+ exctx.topframeref = virtual_ref(xy)
+ m = f(xy, n, reclevel-1)
+ assert m == n
+ n -= 1
+ exctx.topframeref = vref_None
+ virtual_ref_finish(xy)
+ return 2
+ def main(n, reclevel):
+ return f(XY(), n, reclevel)
+ #
+ res = self.meta_interp(main, [15, 1])
+ assert res == main(15, 1)
+ self.check_aborted_count(0)
+
+ def test_recursive_call_2(self):
+ myjitdriver = JitDriver(greens = [], reds = ['n', 'frame', 'rec'])
+ #
+ class XY:
+ n = 0
+ class ExCtx:
+ pass
+ exctx = ExCtx()
+ #
+ def f(frame, n, reclevel):
+ while n > 0:
+ myjitdriver.can_enter_jit(n=n, frame=frame, rec=reclevel)
+ myjitdriver.jit_merge_point(n=n, frame=frame, rec=reclevel)
+ frame.n += 1
+ xy = XY()
+ xy.n = n
+ exctx.topframeref = virtual_ref(xy)
+ if reclevel > 0:
+ m = f(xy, frame.n, reclevel-1)
+ assert xy.n == m
+ n -= 1
+ else:
+ n -= 2
+ exctx.topframeref = vref_None
+ virtual_ref_finish(xy)
+ return frame.n
+ def main(n, reclevel):
+ return f(XY(), n, reclevel)
+ #
+ res = self.meta_interp(main, [10, 2])
+ assert res == main(10, 2)
+ self.check_aborted_count(0)
class TestLLtype(VRefTests, LLJitMixin):
More information about the Pypy-commit
mailing list