[pypy-svn] r70078 - in pypy/branch/virtual-forcing/pypy/jit: backend/llgraph backend/test backend/x86 metainterp metainterp/test
arigo at codespeak.net
arigo at codespeak.net
Sat Dec 12 13:59:55 CET 2009
Author: arigo
Date: Sat Dec 12 13:59:55 2009
New Revision: 70078
Modified:
pypy/branch/virtual-forcing/pypy/jit/backend/llgraph/llimpl.py
pypy/branch/virtual-forcing/pypy/jit/backend/test/runner_test.py
pypy/branch/virtual-forcing/pypy/jit/backend/x86/regalloc.py
pypy/branch/virtual-forcing/pypy/jit/metainterp/executor.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/resoperation.py
pypy/branch/virtual-forcing/pypy/jit/metainterp/test/test_virtualref.py
Log:
Do it another way. Much simpler and does not suffer from the
issue that virtualref_boxes is out-of-sync if we mangle past
VIRTUAL_REF_CHECK instructions in the trace.
Modified: pypy/branch/virtual-forcing/pypy/jit/backend/llgraph/llimpl.py
==============================================================================
--- pypy/branch/virtual-forcing/pypy/jit/backend/llgraph/llimpl.py (original)
+++ pypy/branch/virtual-forcing/pypy/jit/backend/llgraph/llimpl.py Sat Dec 12 13:59:55 2009
@@ -154,7 +154,7 @@
'call_may_force' : (('int', 'varargs'), 'intorptr'),
'guard_not_forced': ((), None),
'virtual_ref' : (('ref', 'int'), 'ref'),
- 'virtual_ref_check': (('varargs',), None),
+ 'virtual_ref_finish': (('ref', 'ref'), None),
#'getitem' : (('void', 'ref', 'int'), 'int'),
#'setitem' : (('void', 'ref', 'int', 'int'), None),
#'newlist' : (('void', 'varargs'), 'ref'),
@@ -818,7 +818,7 @@
def op_virtual_ref(self, _, virtual, index):
return virtual
- def op_virtual_ref_check(self, _, *args):
+ def op_virtual_ref_finish(self, _, vref, virtual):
pass
Modified: pypy/branch/virtual-forcing/pypy/jit/backend/test/runner_test.py
==============================================================================
--- pypy/branch/virtual-forcing/pypy/jit/backend/test/runner_test.py (original)
+++ pypy/branch/virtual-forcing/pypy/jit/backend/test/runner_test.py Sat Dec 12 13:59:55 2009
@@ -786,9 +786,9 @@
'ref')
assert r.value == u_box.value
- def test_virtual_ref_check(self):
- # if VIRTUAL_REF_CHECK reaches the backend, it is a no-op
- self.execute_operation(rop.VIRTUAL_REF_CHECK,
+ def test_virtual_ref_finish(self):
+ # if VIRTUAL_REF_FINISH reaches the backend, it is a no-op
+ self.execute_operation(rop.VIRTUAL_REF_FINISH,
[BoxInt(123), BoxInt(234)],
'void')
Modified: pypy/branch/virtual-forcing/pypy/jit/backend/x86/regalloc.py
==============================================================================
--- pypy/branch/virtual-forcing/pypy/jit/backend/x86/regalloc.py (original)
+++ pypy/branch/virtual-forcing/pypy/jit/backend/x86/regalloc.py Sat Dec 12 13:59:55 2009
@@ -928,7 +928,7 @@
def consider_debug_merge_point(self, op, ignored):
pass
- def consider_virtual_ref_check(self, op, ignored):
+ def consider_virtual_ref_finish(self, op, ignored):
self.possibly_free_vars(op.args)
def get_mark_gc_roots(self, gcrootmap):
Modified: pypy/branch/virtual-forcing/pypy/jit/metainterp/executor.py
==============================================================================
--- pypy/branch/virtual-forcing/pypy/jit/metainterp/executor.py (original)
+++ pypy/branch/virtual-forcing/pypy/jit/metainterp/executor.py Sat Dec 12 13:59:55 2009
@@ -226,7 +226,7 @@
def do_virtual_ref(cpu, box1, box2):
raise NotImplementedError
-def do_virtual_ref_check(cpu, *boxes):
+def do_virtual_ref_finish(cpu, box1, box2):
raise NotImplementedError
def do_debug_merge_point(cpu, box1):
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 Sat Dec 12 13:59:55 2009
@@ -759,29 +759,27 @@
vrefvalue.setfield(descr_virtual_token, self.getvalue(tokenbox))
vrefvalue.setfield(descr_virtualref_index, self.getvalue(indexbox))
- def optimize_VIRTUAL_REF_CHECK(self, op):
- for i in range(0, len(op.args), 2):
- value = self.getvalue(op.args[i])
- if not value.is_virtual(): # virtual_ref(non-virtual) means it
- raise compile.GiveUp # escaped already, which is bad
- #
- # Set the 'forced' field of the virtual_ref.
- # In good cases, this is all virtual, so has no effect.
- # Otherwise, this forces the real object -- but only now, as
- # opposed to much earlier. This is important because the object is
- # typically a PyPy PyFrame, and now is the end of its execution, so
- # forcing it now does not have catastrophic effects.
- from pypy.jit.metainterp import virtualref
- # - set 'forced' to point to the real object
- args = [op.args[i+1], op.args[i]]
- op1 = ResOperation(rop.SETFIELD_GC, args, None,
- descr = virtualref.get_descr_forced(self.cpu))
- self.optimize_SETFIELD_GC(op1)
- # - set 'virtual_token' to TOKEN_NONE
- args = [op.args[i+1], ConstInt(0)]
- op1 = ResOperation(rop.SETFIELD_GC, args, None,
- descr = virtualref.get_descr_virtual_token(self.cpu))
- self.optimize_SETFIELD_GC(op1)
+ def optimize_VIRTUAL_REF_FINISH(self, op):
+ value = self.getvalue(op.args[1])
+ if not value.is_virtual(): # virtual_ref(non-virtual) means it
+ raise compile.GiveUp # escaped already, which is bad
+ #
+ # Set the 'forced' field of the virtual_ref.
+ # In good cases, this is all virtual, so has no effect.
+ # Otherwise, this forces the real object -- but only now, as
+ # opposed to much earlier. This is important because the object is
+ # typically a PyPy PyFrame, and now is the end of its execution, so
+ # forcing it now does not have catastrophic effects.
+ from pypy.jit.metainterp import virtualref
+ # - set 'forced' to point to the real object
+ op1 = ResOperation(rop.SETFIELD_GC, op.args, None,
+ descr = virtualref.get_descr_forced(self.cpu))
+ self.optimize_SETFIELD_GC(op1)
+ # - set 'virtual_token' to TOKEN_NONE
+ args = [op.args[0], ConstInt(0)]
+ op1 = ResOperation(rop.SETFIELD_GC, args, None,
+ descr = virtualref.get_descr_virtual_token(self.cpu))
+ self.optimize_SETFIELD_GC(op1)
def optimize_GETFIELD_GC(self, op):
value = self.getvalue(op.args[0])
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 Sat Dec 12 13:59:55 2009
@@ -836,7 +836,7 @@
except GiveUp:
self.metainterp.staticdata.profiler.count(ABORT_BRIDGE)
self.metainterp.switch_to_blackhole()
- self.metainterp.generate_virtual_ref_check()
+ self.metainterp.virtual_ref_check()
if self.metainterp.is_blackholing():
self.blackhole_reached_merge_point(self.env)
return True
@@ -900,9 +900,9 @@
# in the vref), then we replace the vref in the list with
# ConstPtr(NULL).
#
- # * at the next virtual_ref_check() or jit_merge_point, any such
+ # * at the next virtual_ref_check() or jit_merge_point(), any such
# NULL causes tracing to abort. So escaping is fine if there
- # is no virtual_ref_check() or jit_merge_point before the final
+ # is no virtual_ref_check()/jit_merge_point() before the final
# call to virtual_ref_finish().
#
metainterp = self.metainterp
@@ -930,19 +930,18 @@
# virtual_ref_finish() assumes that we have a stack-like, last-in
# first-out order.
metainterp = self.metainterp
- if not metainterp.is_blackholing():
- vrefbox = metainterp.virtualref_boxes[-1]
- vref = vrefbox.getref_base()
- if virtualref.is_virtual_ref(vref):
- metainterp.stop_tracking_virtualref(-2)
- #
vrefbox = metainterp.virtualref_boxes.pop()
lastbox = metainterp.virtualref_boxes.pop()
assert box.getref_base() == lastbox.getref_base()
+ if not metainterp.is_blackholing():
+ vref = vrefbox.getref_base()
+ if virtualref.is_virtual_ref(vref):
+ metainterp.history.record(rop.VIRTUAL_REF_FINISH,
+ [vrefbox, lastbox], None)
@arguments()
def opimpl_virtual_ref_check(self):
- self.metainterp.generate_virtual_ref_check()
+ self.metainterp.virtual_ref_check()
# ------------------------------
@@ -1052,7 +1051,7 @@
# xxx do something about code duplication
resbox = self.metainterp.execute_and_record_varargs(
rop.CALL_MAY_FORCE, argboxes, descr=descr)
- self.metainterp.vable_and_vrefs_after_residual_call()
+ self.metainterp.vable_and_vrefs_after_residual_call(argboxes)
if resbox is not None:
self.make_result_box(resbox)
self.generate_guard(self.pc, rop.GUARD_NOT_FORCED, None, [])
@@ -1807,20 +1806,23 @@
force_token_box],
None, descr=vinfo.vable_token_descr)
- def vable_and_vrefs_after_residual_call(self):
+ def vable_and_vrefs_after_residual_call(self, argboxes):
if self.is_blackholing():
escapes = True
else:
escapes = False
#
- for i in range(1, len(self.virtualref_boxes), 2):
- if self.is_blackholing():
- break
- vrefbox = self.virtualref_boxes[i]
+ for i in range(0, len(self.virtualref_boxes), 2):
+ virtualbox = self.virtualref_boxes[i]
+ vrefbox = self.virtualref_boxes[i+1]
vref = vrefbox.getref_base()
- if virtualref.tracing_after_residual_call(vref):
- # this vref escaped during CALL_MAY_FORCE.
- self.stop_tracking_virtualref(i-1)
+ if (virtualref.tracing_after_residual_call(vref) or
+ virtualbox in argboxes): # <-- XXX hack
+ # this vref was really a virtual_ref, but it escaped
+ # during this CALL_MAY_FORCE. Mark this fact by
+ # generating a VIRTUAL_REF_FINISH on it and replacing
+ # it by ConstPtr(NULL).
+ self.stop_tracking_virtualref(i)
#
vinfo = self.staticdata.virtualizable_info
if vinfo is not None:
@@ -1836,43 +1838,28 @@
if escapes:
self.load_fields_from_virtualizable()
- def generate_virtual_ref_check(self):
+ def stop_tracking_virtualref(self, i):
+ virtualbox = self.virtualref_boxes[i]
+ vrefbox = self.virtualref_boxes[i+1]
+ # record VIRTUAL_REF_FINISH just before the current CALL_MAY_FORCE
+ call_may_force_op = self.history.operations.pop()
+ assert call_may_force_op.opnum == rop.CALL_MAY_FORCE
+ self.history.record(rop.VIRTUAL_REF_FINISH,
+ [vrefbox, virtualbox], None)
+ self.history.operations.append(call_may_force_op)
+ # mark by replacing it with ConstPtr(NULL)
+ self.virtualref_boxes[i+1] = self.cpu.ts.CONST_NULL
+
+ def virtual_ref_check(self):
if self.is_blackholing():
return
- # first, abort tracing if we reach this point with an escaped virtual
+ # abort tracing if we reach this point with an escaped virtual
for i in range(1, len(self.virtualref_boxes), 2):
vrefbox = self.virtualref_boxes[i]
vref = vrefbox.getref_base()
if not virtualref.is_virtual_ref(vref):
self.switch_to_blackhole()
- return
- # then record VIRTUAL_REF_CHECK, with no argument so far.
- # Arguments may be added by stop_tracking_virtualref().
- self.history.record(rop.VIRTUAL_REF_CHECK, [], None)
-
- def stop_tracking_virtualref(self, j):
- # we look for the most recent VIRTUAL_REF_CHECK marker, and add
- # there the pair virtualbox/vrefbox as arguments.
- virtualbox = self.virtualref_boxes[j]
- vrefbox = self.virtualref_boxes[j+1]
- assert virtualref.is_virtual_ref(vrefbox.getref_base())
- self.virtualref_boxes[j+1] = self.cpu.ts.CONST_NULL
- operations = self.history.operations
- for i in range(len(operations)-1, -1, -1):
- op = operations[i]
- if op.opnum == rop.VIRTUAL_REF_CHECK:
- # found
- op.args = op.args + [virtualbox, vrefbox]
break
- if op.result is vrefbox:
- # no VIRTUAL_REF_CHECK exists before the VIRTUAL_REF
- # that created this vref. Replace it with a mere SAME_AS.
- if op.opnum == rop.VIRTUAL_REF:
- op.opnum = rop.SAME_AS
- op.args = [op.args[0]]
- break
- else:
- assert 0, "not found the VIRTUAL_REF nor VIRTUAL_REF_CHECK at all!"
def handle_exception(self):
etype = self.cpu.get_exception()
@@ -1910,8 +1897,6 @@
self, newboxes, resumedescr, expect_virtualizable)
#
# virtual refs: make the vrefs point to the freshly allocated virtuals
- if not self.is_blackholing():
- self.history.record(rop.VIRTUAL_REF_CHECK, [], None)
self.virtualref_boxes = virtualref_boxes
for i in range(0, len(virtualref_boxes), 2):
virtualbox = virtualref_boxes[i]
Modified: pypy/branch/virtual-forcing/pypy/jit/metainterp/resoperation.py
==============================================================================
--- pypy/branch/virtual-forcing/pypy/jit/metainterp/resoperation.py (original)
+++ pypy/branch/virtual-forcing/pypy/jit/metainterp/resoperation.py Sat Dec 12 13:59:55 2009
@@ -223,7 +223,7 @@
'COND_CALL_GC_MALLOC', # [a, b, if_(a<=b)_result, if_(a>b)_call, args...]
# => result (for mallocs)
'DEBUG_MERGE_POINT/1', # debugging only
- 'VIRTUAL_REF_CHECK',
+ 'VIRTUAL_REF_FINISH/2',
'_CANRAISE_FIRST', # ----- start of can_raise operations -----
'CALL',
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 Sat Dec 12 13:59:55 2009
@@ -30,7 +30,7 @@
self.interp_operations(f, [])
self.check_operations_history(new_with_vtable=1, # X()
virtual_ref=1,
- virtual_ref_check=1)
+ virtual_ref_finish=1)
def test_make_vref_guard(self):
if not isinstance(self, TestLLtype):
More information about the Pypy-commit
mailing list