[pypy-svn] r70072 - in pypy/branch/virtual-forcing/pypy: jit/backend/llgraph jit/backend/test jit/backend/x86 jit/metainterp jit/metainterp/test rlib
arigo at codespeak.net
arigo at codespeak.net
Fri Dec 11 17:58:42 CET 2009
Author: arigo
Date: Fri Dec 11 17:58:41 2009
New Revision: 70072
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/codewriter.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
pypy/branch/virtual-forcing/pypy/jit/metainterp/virtualref.py
pypy/branch/virtual-forcing/pypy/rlib/jit.py
Log:
Add a new operation 'virtual_ref_check', documented in rlib/jit.
Implement it to replace the hack of the previous checkin.
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 Fri Dec 11 17:58:41 2009
@@ -154,7 +154,7 @@
'call_may_force' : (('int', 'varargs'), 'intorptr'),
'guard_not_forced': ((), None),
'virtual_ref' : (('ref', 'int'), 'ref'),
- 'virtual_ref_finish':(('ref', 'ref'), None),
+ 'virtual_ref_check': (('varargs',), 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_finish(self, _, vref, virtual):
+ def op_virtual_ref_check(self, _, *args):
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 Fri Dec 11 17:58:41 2009
@@ -786,6 +786,12 @@
'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,
+ [BoxInt(123), BoxInt(234)],
+ 'void')
+
def test_jump(self):
# this test generates small loops where the JUMP passes many
# arguments of various types, shuffling them around.
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 Fri Dec 11 17:58:41 2009
@@ -928,6 +928,9 @@
def consider_debug_merge_point(self, op, ignored):
pass
+ def consider_virtual_ref_check(self, op, ignored):
+ self.possibly_free_vars(op.args)
+
def get_mark_gc_roots(self, gcrootmap):
shape = gcrootmap.get_basic_shape()
for v, val in self.sm.stack_bindings.items():
Modified: pypy/branch/virtual-forcing/pypy/jit/metainterp/codewriter.py
==============================================================================
--- pypy/branch/virtual-forcing/pypy/jit/metainterp/codewriter.py (original)
+++ pypy/branch/virtual-forcing/pypy/jit/metainterp/codewriter.py Fri Dec 11 17:58:41 2009
@@ -1158,16 +1158,20 @@
self.var_position(op.args[3]))
def serialize_op_jit_marker(self, op):
- if op.args[0].value == 'jit_merge_point':
- assert self.portal, "jit_merge_point in non-main graph!"
- self.emit('jit_merge_point')
- assert ([self.var_position(i) for i in op.args[2:]] ==
- range(0, 2*(len(op.args) - 2), 2))
- #for i in range(2, len(op.args)):
- # arg = op.args[i]
- # self._eventualy_builtin(arg)
- elif op.args[0].value == 'can_enter_jit':
- self.emit('can_enter_jit')
+ key = op.args[0].value
+ getattr(self, 'handle_jit_marker__%s' % key)(op)
+
+ def handle_jit_marker__jit_merge_point(self, op):
+ assert self.portal, "jit_merge_point in non-main graph!"
+ self.emit('jit_merge_point')
+ assert ([self.var_position(i) for i in op.args[2:]] ==
+ range(0, 2*(len(op.args) - 2), 2))
+
+ def handle_jit_marker__can_enter_jit(self, op):
+ self.emit('can_enter_jit')
+
+ def handle_jit_marker__virtual_ref_check(self, op):
+ self.emit('virtual_ref_check')
def serialize_op_direct_call(self, op):
kind = self.codewriter.guess_call_kind(op)
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 Fri Dec 11 17:58:41 2009
@@ -226,7 +226,7 @@
def do_virtual_ref(cpu, box1, box2):
raise NotImplementedError
-def do_virtual_ref_finish(cpu, box1, box2):
+def do_virtual_ref_check(cpu):
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 Fri Dec 11 17:58:41 2009
@@ -759,26 +759,29 @@
vrefvalue.setfield(descr_virtual_token, self.getvalue(tokenbox))
vrefvalue.setfield(descr_virtualref_index, self.getvalue(indexbox))
- def optimize_VIRTUAL_REF_FINISH(self, op):
- value = self.getvalue(op.args[1])
- if not value.is_virtual(): # virtual_ref(non-virtual) gives bad
- raise compile.GiveUp # results, so don't bother compiling it
- #
- # 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
- op1 = ResOperation(rop.SETFIELD_GC, [op.args[0], ConstInt(0)], None,
+ 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)
+ 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 Fri Dec 11 17:58:41 2009
@@ -836,6 +836,7 @@
except GiveUp:
self.metainterp.staticdata.profiler.count(ABORT_BRIDGE)
self.metainterp.switch_to_blackhole()
+ self.metainterp.generate_virtual_ref_check()
if self.metainterp.is_blackholing():
self.blackhole_reached_merge_point(self.env)
return True
@@ -888,6 +889,22 @@
@arguments("box")
def opimpl_virtual_ref(self, box):
+ # Details on the content of metainterp.virtualref_boxes:
+ #
+ # * it's a list whose items go two by two, containing first the
+ # virtual box (e.g. the PyFrame) and then the vref box (e.g.
+ # the 'virtual_ref(frame)').
+ #
+ # * if we detect that the virtual box escapes during tracing
+ # already (by generating a CALl_MAY_FORCE that marks the flags
+ # 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
+ # NULL causes tracing to abort. So escaping is fine if there
+ # is no virtual_ref_check() or jit_merge_point before the final
+ # call to virtual_ref_finish().
+ #
metainterp = self.metainterp
if metainterp.is_blackholing():
resbox = box # good enough when blackholing
@@ -913,34 +930,19 @@
# 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():
- 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
+
+ @arguments()
+ def opimpl_virtual_ref_check(self):
+ self.metainterp.generate_virtual_ref_check()
# ------------------------------
@@ -1045,7 +1047,6 @@
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
@@ -1790,8 +1791,6 @@
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 vref when
# it is created, by optimizeopt.py.
@@ -1817,11 +1816,9 @@
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
+ self.stop_tracking_virtualref(i-1)
#
vinfo = self.staticdata.virtualizable_info
if vinfo is not None:
@@ -1837,6 +1834,44 @@
if escapes:
self.load_fields_from_virtualizable()
+ def generate_virtual_ref_check(self):
+ if self.is_blackholing():
+ return
+ # first, 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:
+ pass # not found at all! nothing to do, just ignore it
+
def handle_exception(self):
etype = self.cpu.get_exception()
evalue = self.cpu.get_exc_value()
@@ -1877,8 +1912,6 @@
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/resoperation.py
==============================================================================
--- pypy/branch/virtual-forcing/pypy/jit/metainterp/resoperation.py (original)
+++ pypy/branch/virtual-forcing/pypy/jit/metainterp/resoperation.py Fri Dec 11 17:58:41 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_FINISH/2',
+ 'VIRTUAL_REF_CHECK',
'_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 Fri Dec 11 17:58:41 2009
@@ -1,7 +1,7 @@
import py
from pypy.rpython.lltypesystem import lltype, llmemory, lloperation
-from pypy.rlib.jit import JitDriver, dont_look_inside
-from pypy.rlib.jit import virtual_ref, virtual_ref_finish, vref_None
+from pypy.rlib.jit import JitDriver, dont_look_inside, vref_None
+from pypy.rlib.jit import virtual_ref, virtual_ref_check, virtual_ref_finish
from pypy.rlib.objectmodel import compute_unique_id
from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
from pypy.jit.metainterp.resoperation import rop
@@ -22,6 +22,7 @@
def f():
x = X()
exctx.topframeref = virtual_ref(x)
+ virtual_ref_check()
exctx.topframeref = vref_None
virtual_ref_finish(x)
return 1
@@ -29,7 +30,7 @@
self.interp_operations(f, [])
self.check_operations_history(new_with_vtable=1, # X()
virtual_ref=1,
- virtual_ref_finish=1)
+ virtual_ref_check=1)
def test_make_vref_guard(self):
if not isinstance(self, TestLLtype):
@@ -53,6 +54,7 @@
exctx.topframeref = virtual_ref(x)
def leave():
exctx.topframeref = vref_None
+ virtual_ref_check()
virtual_ref_finish(exctx._frame)
def f(n):
enter(n)
@@ -105,6 +107,7 @@
# here, 'x' should be virtual. (This is ensured because
# we call virtual_ref(x).)
exctx.topframeref = vref_None
+ virtual_ref_check()
virtual_ref_finish(x)
# 'x' is allowed to escape, and even be forced, even after
# the call to finish().
@@ -114,8 +117,72 @@
#
self.meta_interp(f, [10])
self.check_loops(new_with_vtable=2) # the vref, and later the X
+ self.check_aborted_count(0)
+
+ def test_make_vref_and_force_nocheck_1(self):
+ jitdriver = JitDriver(greens = [], reds = ['total', 'n'])
+ #
+ class X:
+ pass
+ class ExCtx:
+ pass
+ exctx = ExCtx()
+ #
+ @dont_look_inside
+ def force_me():
+ return exctx.topframeref().n
+ #
+ def f(n):
+ total = 0
+ while total < 300:
+ jitdriver.can_enter_jit(total=total, n=n)
+ jitdriver.jit_merge_point(total=total, n=n)
+ x = X()
+ x.n = n + 123
+ exctx.topframeref = virtual_ref(x)
+ # --- no virtual_ref_check() here ---
+ total += force_me() - 100
+ virtual_ref_finish(x)
+ exctx.topframeref = vref_None
+ return total
+ #
+ res = self.meta_interp(f, [-4])
+ assert res == 16 * 19
+ self.check_aborted_count(0)
+
+ def test_make_vref_and_force_nocheck_2(self):
+ jitdriver = JitDriver(greens = [], reds = ['total', 'n'])
+ #
+ class X:
+ pass
+ class ExCtx:
+ pass
+ exctx = ExCtx()
+ #
+ @dont_look_inside
+ def force_me():
+ return exctx.topframeref().n
+ #
+ def f(n):
+ total = 0
+ while total < 300:
+ jitdriver.can_enter_jit(total=total, n=n)
+ jitdriver.jit_merge_point(total=total, n=n)
+ x = X()
+ x.n = n + 123
+ exctx.topframeref = virtual_ref(x)
+ virtual_ref_check()
+ total += force_me() - 100
+ # --- but no virtual_ref_check() there ---
+ virtual_ref_finish(x)
+ exctx.topframeref = vref_None
+ return total
+ #
+ res = self.meta_interp(f, [-4])
+ assert res == 16 * 19
+ self.check_aborted_count(0)
- def test_make_vref_and_force(self):
+ def test_make_vref_and_force_check(self):
jitdriver = JitDriver(greens = [], reds = ['total', 'n'])
#
class X:
@@ -137,6 +204,7 @@
x.n = n + 123
exctx.topframeref = virtual_ref(x)
total += force_me() - 100
+ virtual_ref_check()
virtual_ref_finish(x)
exctx.topframeref = vref_None
return total
@@ -175,11 +243,13 @@
xy.next1 = None
xy.next2 = None
xy.next3 = None
+ virtual_ref_check()
virtual_ref_finish(xy)
#
self.meta_interp(f, [15])
self.check_loops(new_with_vtable=2) # the vref, and xy so far,
# but not xy.next1/2/3
+ self.check_aborted_count(0)
def test_simple_force_always(self):
myjitdriver = JitDriver(greens = [], reds = ['n'])
@@ -204,6 +274,7 @@
xy.n = n
exctx.topframeref = virtual_ref(xy)
n -= externalfn(n)
+ virtual_ref_check()
virtual_ref_finish(xy)
exctx.topframeref = vref_None
#
@@ -234,6 +305,7 @@
xy.n = n
exctx.topframeref = virtual_ref(xy)
n -= externalfn(n)
+ virtual_ref_check()
virtual_ref_finish(xy)
exctx.topframeref = vref_None
return exctx.m
@@ -241,6 +313,7 @@
res = self.meta_interp(f, [30])
assert res == 13
self.check_loop_count(1)
+ self.check_aborted_count(0)
def test_blackhole_forces(self):
myjitdriver = JitDriver(greens = [], reds = ['n'])
@@ -267,12 +340,14 @@
externalfn(n)
n -= 1
exctx.topframeref = vref_None
+ virtual_ref_check()
virtual_ref_finish(xy)
return exctx.m
#
res = self.meta_interp(f, [30])
assert res == 13
self.check_loop_count(1)
+ self.check_aborted_count(0)
def test_bridge_forces(self):
myjitdriver = JitDriver(greens = [], reds = ['n'])
@@ -299,12 +374,14 @@
externalfn(n)
n -= 1
exctx.topframeref = vref_None
+ virtual_ref_check()
virtual_ref_finish(xy)
return exctx.m
#
res = self.meta_interp(f, [72])
assert res == 6
self.check_loop_count(1) # the bridge should not be compiled
+ self.check_aborted_count_at_least(1)
def test_access_vref_later(self):
myjitdriver = JitDriver(greens = [], reds = ['n'])
@@ -320,7 +397,6 @@
return exctx.later().n
#
def f(n):
- later = None
while n > 0:
myjitdriver.can_enter_jit(n=n)
myjitdriver.jit_merge_point(n=n)
@@ -330,11 +406,13 @@
exctx.later = exctx.topframeref
n -= 1
exctx.topframeref = vref_None
+ virtual_ref_check()
virtual_ref_finish(xy)
return g()
#
res = self.meta_interp(f, [15])
assert res == 1
+ self.check_aborted_count(0)
def test_jit_force_virtual_seen(self):
myjitdriver = JitDriver(greens = [], reds = ['n'])
@@ -354,6 +432,7 @@
exctx.topframeref = virtual_ref(xy)
n = exctx.topframeref().n - 1
exctx.topframeref = vref_None
+ virtual_ref_check()
virtual_ref_finish(xy)
return 1
#
Modified: pypy/branch/virtual-forcing/pypy/jit/metainterp/virtualref.py
==============================================================================
--- pypy/branch/virtual-forcing/pypy/jit/metainterp/virtualref.py (original)
+++ pypy/branch/virtual-forcing/pypy/jit/metainterp/virtualref.py Fri Dec 11 17:58:41 2009
@@ -76,12 +76,22 @@
vref.forced = lltype.cast_opaque_ptr(rclass.OBJECTPTR, real_object)
return lltype.cast_opaque_ptr(llmemory.GCREF, vref)
+def is_virtual_ref(gcref):
+ if not gcref:
+ return False
+ inst = lltype.cast_opaque_ptr(rclass.OBJECTPTR, gcref)
+ return inst.typeptr == jit_virtual_ref_vtable
+
def tracing_before_residual_call(gcref):
+ if not is_virtual_ref(gcref):
+ return
vref = lltype.cast_opaque_ptr(lltype.Ptr(JIT_VIRTUAL_REF), gcref)
assert not vref.virtual_token
vref.virtual_token = TOKEN_TRACING_RESCALL
def tracing_after_residual_call(gcref):
+ if not is_virtual_ref(gcref):
+ return False
vref = lltype.cast_opaque_ptr(lltype.Ptr(JIT_VIRTUAL_REF), gcref)
if vref.virtual_token:
# not modified by the residual call; assert that it is still
@@ -94,6 +104,8 @@
return True
def forced_single_vref(gcref, real_object):
+ if not is_virtual_ref(gcref):
+ return
assert real_object
vref = lltype.cast_opaque_ptr(lltype.Ptr(JIT_VIRTUAL_REF), gcref)
assert (vref.virtual_token != TOKEN_NONE and
@@ -102,6 +114,8 @@
vref.forced = lltype.cast_opaque_ptr(rclass.OBJECTPTR, real_object)
def continue_tracing(gcref, real_object):
+ if not is_virtual_ref(gcref):
+ return
vref = lltype.cast_opaque_ptr(lltype.Ptr(JIT_VIRTUAL_REF), gcref)
assert vref.virtual_token != TOKEN_TRACING_RESCALL
vref.virtual_token = TOKEN_NONE
Modified: pypy/branch/virtual-forcing/pypy/rlib/jit.py
==============================================================================
--- pypy/branch/virtual-forcing/pypy/rlib/jit.py (original)
+++ pypy/branch/virtual-forcing/pypy/rlib/jit.py Fri Dec 11 17:58:41 2009
@@ -112,11 +112,18 @@
dereferenced (by the call syntax 'vref()') before the
virtual_ref_finish, then we get out of the assembler. If it is not
dereferenced at all, or only after the virtual_ref_finish, then
- nothing special occurs.
+ nothing special occurs. Note that the checks for 'being virtual'
+ only occurs when virtual_ref_check() is called (mostly for testing),
+ or when jit_merge_point is called by JITted code in a recursive call.
"""
return DirectJitVRef(x)
virtual_ref.oopspec = 'virtual_ref(x)'
+def virtual_ref_check():
+ from pypy.rpython.lltypesystem import lltype, lloperation
+ lloperation.llop.jit_marker(lltype.Void,
+ lloperation.void('virtual_ref_check'))
+
def virtual_ref_finish(x):
"""See docstring in virtual_ref(x). Note that virtual_ref_finish
takes as argument the real object, not the vref."""
More information about the Pypy-commit
mailing list