[pypy-svn] r69897 - in pypy/branch/virtual-forcing/pypy/jit/metainterp: . test
arigo at codespeak.net
arigo at codespeak.net
Fri Dec 4 15:58:02 CET 2009
Author: arigo
Date: Fri Dec 4 15:58:01 2009
New Revision: 69897
Modified:
pypy/branch/virtual-forcing/pypy/jit/metainterp/pyjitpl.py
pypy/branch/virtual-forcing/pypy/jit/metainterp/test/test_vref.py
pypy/branch/virtual-forcing/pypy/jit/metainterp/virtualizable.py
pypy/branch/virtual-forcing/pypy/jit/metainterp/vref.py
pypy/branch/virtual-forcing/pypy/jit/metainterp/warmspot.py
Log:
Small progress, clean-ups, unification of some concepts with
virtualizable.py.
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 4 15:58:01 2009
@@ -889,9 +889,16 @@
@arguments("box")
def opimpl_virtual_ref(self, box):
obj = box.getref_base()
- res = vref.virtual_ref_during_tracing(self.metainterp, obj)
+ res = vref.virtual_ref_during_tracing(obj)
+ self.metainterp.all_virtual_refs.append(res)
resbox = history.BoxPtr(res)
self.metainterp.history.record(rop.VIRTUAL_REF, [box], resbox)
+ # Note: we create a JIT_VIRTUAL_REF here, in order to detect when
+ # the virtual escapes during tracing already. We record it as a
+ # VIRTUAL_REF operation, although the backend sees this operation
+ # as a no-op. The point is that the backend should not really see
+ # it in practice, as optimizeopt.py should either kill it or
+ # replace it with a NEW_WITH_VTABLE followed by SETFIELD_GCs.
self.make_result_box(resbox)
# ------------------------------
@@ -1203,13 +1210,13 @@
class MetaInterp(object):
in_recursion = 0
_already_allocated_resume_virtuals = None
- _force_token_mem = None
def __init__(self, staticdata):
self.staticdata = staticdata
self.cpu = staticdata.cpu
self.portal_trace_positions = []
self.greenkey_of_huge_function = None
+ self.all_virtual_refs = []
def is_blackholing(self):
return self.history is None
@@ -1766,7 +1773,12 @@
self.load_fields_from_virtualizable()
def virtual_after_residual_call(self):
- if self.is_blackholing() or not vref.was_forced(self):
+ if self.is_blackholing():
+ return
+ for gcref in self.all_virtual_refs:
+ if vref.was_forced(gcref):
+ break
+ else:
return
# during tracing, more precisely during the CALL_MAY_FORCE, at least
# one of the vrefs was read. If we continue to trace and make
Modified: pypy/branch/virtual-forcing/pypy/jit/metainterp/test/test_vref.py
==============================================================================
--- pypy/branch/virtual-forcing/pypy/jit/metainterp/test/test_vref.py (original)
+++ pypy/branch/virtual-forcing/pypy/jit/metainterp/test/test_vref.py Fri Dec 4 15:58:01 2009
@@ -1,5 +1,6 @@
import py
from pypy.rlib.jit import JitDriver, dont_look_inside, virtual_ref
+from pypy.rlib.objectmodel import compute_unique_id
from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
@@ -59,7 +60,9 @@
exctx = ExCtx()
#
@dont_look_inside
- def externalfn():
+ def externalfn(n):
+ if n > 1000:
+ return compute_unique_id(exctx.topframeref())
return 1
#
def f(n):
@@ -67,12 +70,14 @@
myjitdriver.can_enter_jit(n=n)
myjitdriver.jit_merge_point(n=n)
xy = XY()
+ xy.next1 = XY()
+ xy.next2 = XY()
exctx.topframeref = virtual_ref(xy)
- n -= externalfn()
+ n -= externalfn(n)
exctx.topframeref = None
#
self.meta_interp(f, [15])
- self.check_loops(new_with_vtable=0)
+ self.check_loops(new_with_vtable=1) # the vref, not the XYs
def test_simple_force_always(self):
py.test.skip("in-progress")
Modified: pypy/branch/virtual-forcing/pypy/jit/metainterp/virtualizable.py
==============================================================================
--- pypy/branch/virtual-forcing/pypy/jit/metainterp/virtualizable.py (original)
+++ pypy/branch/virtual-forcing/pypy/jit/metainterp/virtualizable.py Fri Dec 4 15:58:01 2009
@@ -11,8 +11,8 @@
class VirtualizableInfo:
- token_none = 0
- token_tracing = -1
+ TOKEN_NONE = 0
+ TOKEN_TRACING = -1
def __init__(self, warmrunnerdesc):
self.warmrunnerdesc = warmrunnerdesc
@@ -177,7 +177,7 @@
return rvirtualizable2.match_virtualizable_type(TYPE, self.VTYPEPTR)
def reset_vable_token(self, virtualizable):
- virtualizable.vable_token = self.token_none
+ virtualizable.vable_token = self.TOKEN_NONE
def clear_vable_token(self, virtualizable):
if virtualizable.vable_token:
@@ -186,14 +186,14 @@
def tracing_before_residual_call(self, virtualizable):
assert not virtualizable.vable_token
- virtualizable.vable_token = self.token_tracing
+ virtualizable.vable_token = self.TOKEN_TRACING
def tracing_after_residual_call(self, virtualizable):
if virtualizable.vable_token:
# not modified by the residual call; assert that it is still
# set to 'tracing_vable_rti' and clear it.
- assert virtualizable.vable_token == self.token_tracing
- virtualizable.vable_token = self.token_none
+ assert virtualizable.vable_token == self.TOKEN_TRACING
+ virtualizable.vable_token = self.TOKEN_NONE
return False
else:
# marker "modified during residual call" set.
@@ -201,10 +201,10 @@
def force_now(self, virtualizable):
token = virtualizable.vable_token
- virtualizable.vable_token = self.token_none
- if token == self.token_tracing:
+ virtualizable.vable_token = self.TOKEN_NONE
+ if token == self.TOKEN_TRACING:
# The values in the virtualizable are always correct during
- # tracing. We only need to reset vable_token to token_none
+ # tracing. We only need to reset vable_token to TOKEN_NONE
# as a marker for the tracing, to tell it that this
# virtualizable escapes.
pass
@@ -220,11 +220,11 @@
# The 'vable_token' field of a virtualizable is either 0, -1, or points
# into the CPU stack to a particular field in the current frame. It is:
#
-# 1. 0 (token_none) if not in the JIT at all, except as described below.
+# 1. 0 (TOKEN_NONE) if not in the JIT at all, except as described below.
#
# 2. equal to 0 when tracing is in progress; except:
#
-# 3. equal to -1 (token_tracing) during tracing when we do a residual call,
+# 3. equal to -1 (TOKEN_TRACING) during tracing when we do a residual call,
# calling random unknown other parts of the interpreter; it is
# reset to 0 as soon as something occurs to the virtualizable.
#
Modified: pypy/branch/virtual-forcing/pypy/jit/metainterp/vref.py
==============================================================================
--- pypy/branch/virtual-forcing/pypy/jit/metainterp/vref.py (original)
+++ pypy/branch/virtual-forcing/pypy/jit/metainterp/vref.py Fri Dec 4 15:58:01 2009
@@ -2,20 +2,29 @@
from pypy.rpython.lltypesystem import lltype, llmemory, rffi, rclass
-def replace_force_virtual_with_call(graphs, funcptr):
+def replace_force_virtual_with_call(make_helper_func, graphs):
# similar to rvirtualizable2.replace_force_virtualizable_with_call().
- # funcptr should be an ll function pointer with a signature
- # OBJECTPTR -> OBJECTPTR.
- c_funcptr = inputconst(lltype.typeOf(funcptr), funcptr)
+ c_funcptr = None
count = 0
for graph in graphs:
for block in graph.iterblocks():
for op in block.operations:
if op.opname == 'jit_force_virtual':
+ # first compute c_funcptr, but only if there is any
+ # 'jit_force_virtual' around
+ if c_funcptr is None:
+ FUNC = lltype.FuncType([rclass.OBJECTPTR],
+ rclass.OBJECTPTR)
+ funcptr = make_helper_func(
+ lltype.Ptr(FUNC),
+ force_virtual_if_necessary)
+ c_funcptr = inputconst(lltype.typeOf(funcptr), funcptr)
+ #
op.opname = 'direct_call'
op.args = [c_funcptr, op.args[0]]
count += 1
- log("replaced %d 'jit_force_virtual' with %r" % (count, funcptr))
+ if c_funcptr is not None:
+ log("replaced %d 'jit_force_virtual' with %r" % (count, funcptr))
# ____________________________________________________________
@@ -23,39 +32,32 @@
# we make the low-level type of an RPython class directly
JIT_VIRTUAL_REF = lltype.GcStruct('JitVirtualRef',
('super', rclass.OBJECT),
- ('force_token', llmemory.Address),
+ ('virtual_token', lltype.Signed),
('forced', rclass.OBJECTPTR))
jit_virtual_ref_vtable = lltype.malloc(rclass.OBJECT_VTABLE, zero=True,
flavor='raw')
-class ForceTokenMem(object):
- def __init__(self):
- self.allocated = lltype.malloc(rffi.CArray(lltype.Signed), 1,
- flavor='raw')
- self.allocated[0] = 0
-
- def __del__(self):
- lltype.free(self.allocated, flavor='raw')
+# The 'virtual_token' field has the same meaning as the 'vable_token' field
+# of a virtualizable. It is equal to:
+# * -1 (TOKEN_TRACING) when tracing;
+# * addr in the CPU stack (set by FORCE_TOKEN) when running the assembler;
+# * 0 (TOKEN_NONE) after the virtual is forced, if it is forced at all.
+TOKEN_NONE = 0
+TOKEN_TRACING = -1
-def get_force_token(metainterp):
- if not metainterp._force_token_mem:
- metainterp._force_token_mem = ForceTokenMem()
- return llmemory.cast_ptr_to_adr(metainterp._force_token_mem.allocated)
-
-def was_forced(metainterp):
- if not metainterp._force_token_mem:
- return False
- return metainterp._force_token_mem.allocated[0] == -1
-
-def virtual_ref_during_tracing(metainterp, real_object):
+def virtual_ref_during_tracing(real_object):
+ assert real_object
vref = lltype.malloc(JIT_VIRTUAL_REF)
p = lltype.cast_pointer(rclass.OBJECTPTR, vref)
p.typeptr = jit_virtual_ref_vtable
- vref.force_token = get_force_token(metainterp)
+ vref.virtual_token = TOKEN_TRACING
vref.forced = lltype.cast_opaque_ptr(rclass.OBJECTPTR, real_object)
- assert vref.forced
return lltype.cast_opaque_ptr(llmemory.GCREF, vref)
+def was_forced(gcref):
+ vref = lltype.cast_opaque_ptr(lltype.Ptr(JIT_VIRTUAL_REF), gcref)
+ return vref.virtual_token != TOKEN_TRACING
+
# ____________________________________________________________
def force_virtual_if_necessary(inst):
@@ -65,10 +67,8 @@
def force_virtual(inst):
vref = lltype.cast_pointer(lltype.Ptr(JIT_VIRTUAL_REF), inst)
- if vref.force_token:
- if not vref.forced:
- xxxx
- vref.force_token.signed[0] = -1
- vref.force_token = llmemory.NULL
+ if not vref.forced:
+ xxxx
+ vref.virtual_token = TOKEN_NONE
return vref.forced
force_virtual._dont_inline_ = True
Modified: pypy/branch/virtual-forcing/pypy/jit/metainterp/warmspot.py
==============================================================================
--- pypy/branch/virtual-forcing/pypy/jit/metainterp/warmspot.py (original)
+++ pypy/branch/virtual-forcing/pypy/jit/metainterp/warmspot.py Fri Dec 4 15:58:01 2009
@@ -603,11 +603,8 @@
def rewrite_force_virtual(self):
if self.cpu.ts.name != 'lltype':
py.test.skip("rewrite_force_virtual: port it to ootype")
- FUNC = lltype.FuncType([rclass.OBJECTPTR], rclass.OBJECTPTR)
- funcptr = self.helper_func(lltype.Ptr(FUNC),
- vref.force_virtual_if_necessary)
all_graphs = self.translator.graphs
- vref.replace_force_virtual_with_call(all_graphs, funcptr)
+ vref.replace_force_virtual_with_call(self.helper_func, all_graphs)
def decode_hp_hint_args(op):
More information about the Pypy-commit
mailing list