[pypy-svn] r69702 - in pypy/branch/virtual-forcing/pypy/jit/metainterp: . test
arigo at codespeak.net
arigo at codespeak.net
Fri Nov 27 16:04:38 CET 2009
Author: arigo
Date: Fri Nov 27 16:04:37 2009
New Revision: 69702
Modified:
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_virtualizable.py
Log:
(pedronis, fijal?, arigo)
Simplify a bit virtualizables: when it escapes, then we abort tracing
instead of generating a trace with the escaped virtualizable. Such
a trace is horribly horribly bad anyway.
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 Nov 27 16:04:37 2009
@@ -1318,8 +1318,8 @@
# residual calls require attention to keep virtualizables in-sync.
# CALL_PURE doesn't need it because so far 'promote_virtualizable'
# as an operation is enough to make the called function non-pure.
- require_attention = (opnum == rop.CALL or opnum == rop.OOSEND)
- if require_attention and not self.is_blackholing():
+ is_a_call = (opnum == rop.CALL or opnum == rop.OOSEND)
+ if is_a_call:
self.before_residual_call()
# execute the operation
profiler = self.staticdata.profiler
@@ -1328,17 +1328,14 @@
if self.is_blackholing():
profiler.count_ops(opnum, BLACKHOLED_OPS)
else:
- if require_attention:
- require_attention = self.after_residual_call()
# check if the operation can be constant-folded away
argboxes = list(argboxes)
if rop._ALWAYS_PURE_FIRST <= opnum <= rop._ALWAYS_PURE_LAST:
resbox = self._record_helper_pure_varargs(opnum, resbox, descr, argboxes)
else:
resbox = self._record_helper_nonpure_varargs(opnum, resbox, descr, argboxes)
- # if we are blackholing require_attention has the initial meaning
- if require_attention:
- self.after_generate_residual_call()
+ if is_a_call:
+ self.after_residual_call()
return resbox
def _record_helper_pure(self, opnum, resbox, descr, *argboxes):
@@ -1725,6 +1722,8 @@
vinfo.clear_vable_rti(virtualizable)
def before_residual_call(self):
+ if self.is_blackholing():
+ return
vinfo = self.staticdata.virtualizable_info
if vinfo is not None:
virtualizable_box = self.virtualizable_boxes[-1]
@@ -1732,26 +1731,21 @@
vinfo.tracing_before_residual_call(virtualizable)
def after_residual_call(self):
- vinfo = self.staticdata.virtualizable_info
- if vinfo is not None:
- virtualizable_box = self.virtualizable_boxes[-1]
- virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box)
- if vinfo.tracing_after_residual_call(virtualizable):
- # This is after the residual call is done, but before it
- # is actually generated. We first generate a store-
- # everything-back, *without actually performing it now*
- # as it contains the old values (before the call)!
- self.gen_store_back_in_virtualizable_no_perform()
- return True # must call after_generate_residual_call()
- # otherwise, don't call after_generate_residual_call()
- return False
-
- def after_generate_residual_call(self):
- # Called after generating a residual call, and only if
- # after_residual_call() returned True, i.e. if code in the residual
- # call causes the virtualizable to escape. Reload the modified
- # fields of the virtualizable.
- self.gen_load_fields_from_virtualizable()
+ if self.is_blackholing():
+ vable_escapes = True
+ else:
+ vable_escapes = False
+ vinfo = self.staticdata.virtualizable_info
+ if vinfo is not None:
+ virtualizable_box = self.virtualizable_boxes[-1]
+ virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box)
+ if vinfo.tracing_after_residual_call(virtualizable):
+ # We just did the residual call, and it shows that the
+ # virtualizable escapes.
+ self.switch_to_blackhole()
+ vable_escapes = True
+ if vable_escapes:
+ self.load_fields_from_virtualizable()
def handle_exception(self):
etype = self.cpu.get_exception()
@@ -1809,27 +1803,17 @@
virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box)
vinfo.write_boxes(virtualizable, self.virtualizable_boxes)
- def gen_load_fields_from_virtualizable(self):
+ def load_fields_from_virtualizable(self):
+ # Force a reload of the virtualizable fields into the local
+ # boxes (called only in escaping cases)
+ assert self.is_blackholing()
vinfo = self.staticdata.virtualizable_info
if vinfo is not None:
- vbox = self.virtualizable_boxes[-1]
- for i in range(vinfo.num_static_extra_boxes):
- descr = vinfo.static_field_descrs[i]
- fieldbox = self.execute_and_record(rop.GETFIELD_GC, descr,
- vbox)
- self.virtualizable_boxes[i] = fieldbox
- i = vinfo.num_static_extra_boxes
- virtualizable = vinfo.unwrap_virtualizable_box(vbox)
- for k in range(vinfo.num_arrays):
- descr = vinfo.array_field_descrs[k]
- abox = self.execute_and_record(rop.GETFIELD_GC, descr, vbox)
- descr = vinfo.array_descrs[k]
- for j in range(vinfo.get_array_length(virtualizable, k)):
- itembox = self.execute_and_record(rop.GETARRAYITEM_GC,
- descr, abox, ConstInt(j))
- self.virtualizable_boxes[i] = itembox
- i += 1
- assert i + 1 == len(self.virtualizable_boxes)
+ virtualizable_box = self.virtualizable_boxes[-1]
+ virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box)
+ self.virtualizable_boxes = vinfo.read_boxes(self.cpu,
+ virtualizable)
+ self.virtualizable_boxes.append(virtualizable_box)
def gen_store_back_in_virtualizable(self):
vinfo = self.staticdata.virtualizable_info
@@ -1853,29 +1837,6 @@
abox, ConstInt(j), itembox)
assert i + 1 == len(self.virtualizable_boxes)
- def gen_store_back_in_virtualizable_no_perform(self):
- vinfo = self.staticdata.virtualizable_info
- # xxx only write back the fields really modified
- vbox = self.virtualizable_boxes[-1]
- for i in range(vinfo.num_static_extra_boxes):
- fieldbox = self.virtualizable_boxes[i]
- self.history.record(rop.SETFIELD_GC, [vbox, fieldbox], None,
- descr=vinfo.static_field_descrs[i])
- i = vinfo.num_static_extra_boxes
- virtualizable = vinfo.unwrap_virtualizable_box(vbox)
- for k in range(vinfo.num_arrays):
- abox = vinfo.BoxArray()
- self.history.record(rop.GETFIELD_GC, [vbox], abox,
- descr=vinfo.array_field_descrs[k])
- for j in range(vinfo.get_array_length(virtualizable, k)):
- itembox = self.virtualizable_boxes[i]
- i += 1
- self.history.record(rop.SETARRAYITEM_GC,
- [abox, ConstInt(j), itembox],
- None,
- descr=vinfo.array_descrs[k])
- assert i + 1 == len(self.virtualizable_boxes)
-
def replace_box(self, oldbox, newbox):
for frame in self.framestack:
boxes = frame.env
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 Nov 27 16:04:37 2009
@@ -50,8 +50,8 @@
assert get_stats().enter_count <= count
def check_jumps(self, maxcount):
assert get_stats().exec_jumps <= maxcount
- def check_aborted_count(self, maxcount):
- assert get_stats().aborted_count == maxcount
+ def check_aborted_count(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_virtualizable.py
==============================================================================
--- pypy/branch/virtual-forcing/pypy/jit/metainterp/test/test_virtualizable.py (original)
+++ pypy/branch/virtual-forcing/pypy/jit/metainterp/test/test_virtualizable.py Fri Nov 27 16:04:37 2009
@@ -200,72 +200,6 @@
assert res == 134
self.check_loops(getfield_gc=1, setfield_gc=1)
- def test_external_read_while_tracing(self):
- myjitdriver = JitDriver(greens = [], reds = ['n', 'm', 'xy'],
- virtualizables = ['xy'])
- class Outer:
- pass
- outer = Outer()
- def ext():
- xy = outer.xy
- promote_virtualizable(xy, 'inst_x')
- return xy.inst_x + 2
- def f(n):
- xy = self.setup()
- xy.inst_x = 10
- outer.xy = xy
- m = 0
- while n > 0:
- myjitdriver.can_enter_jit(xy=xy, n=n, m=m)
- myjitdriver.jit_merge_point(xy=xy, n=n, m=m)
- promote_virtualizable(xy, 'inst_x')
- xy.inst_x = n + 9998 # virtualized away
- m += ext() # 2x setfield_gc, 2x getfield_gc
- promote_virtualizable(xy, 'inst_x')
- xy.inst_x = 10 # virtualized away
- n -= 1
- return m
- assert f(20) == 10000*20 + (20*21)/2
- res = self.meta_interp(f, [20], policy=StopAtXPolicy(ext))
- assert res == 10000*20 + (20*21)/2
- # there are no getfields because the optimizer gets rid of them
- self.check_loops(call=1, getfield_gc=0, setfield_gc=2)
- # xxx for now a call that forces the virtualizable during tracing
- # is supposed to always force it later too.
-
- def test_external_write_while_tracing(self):
- myjitdriver = JitDriver(greens = [], reds = ['n', 'm', 'xy'],
- virtualizables = ['xy'])
- class Outer:
- pass
- outer = Outer()
- def ext():
- xy = outer.xy
- promote_virtualizable(xy, 'inst_x')
- xy.inst_x += 2
- def f(n):
- xy = self.setup()
- xy.inst_x = 10
- outer.xy = xy
- m = 0
- while n > 0:
- myjitdriver.can_enter_jit(xy=xy, n=n, m=m)
- myjitdriver.jit_merge_point(xy=xy, n=n, m=m)
- promote_virtualizable(xy, 'inst_x')
- xy.inst_x = n + 9998 # virtualized away
- ext() # 2x setfield_gc, 2x getfield_gc
- promote_virtualizable(xy, 'inst_x')
- m += xy.inst_x # virtualized away
- n -= 1
- return m
- res = self.meta_interp(f, [20], policy=StopAtXPolicy(ext))
- assert res == f(20)
- # the getfield_gc of inst_node is optimized away, because ext does not
- # write to it
- self.check_loops(call=1, getfield_gc=1, setfield_gc=2)
- # xxx for now a call that forces the virtualizable during tracing
- # is supposed to always force it later too.
-
# ------------------------------
XY2 = lltype.GcStruct(
@@ -649,7 +583,8 @@
res = self.meta_interp(f, [123], policy=StopAtXPolicy(g))
assert res == f(123)
-
+ self.check_aborted_count(2)
+ self.check_tree_loop_count(0)
def test_external_write(self):
jitdriver = JitDriver(greens = [], reds = ['frame'],
@@ -680,6 +615,8 @@
res = self.meta_interp(f, [240], policy=StopAtXPolicy(g))
assert res == f(240)
+ self.check_aborted_count(3)
+ self.check_tree_loop_count(0)
def test_external_read_sometimes(self):
py.test.skip("known bug: access the frame in a residual call but"
More information about the Pypy-commit
mailing list