[pypy-svn] r69884 - in pypy/branch/virtual-forcing/pypy/jit/metainterp: . test
arigo at codespeak.net
arigo at codespeak.net
Thu Dec 3 23:55:10 CET 2009
Author: arigo
Date: Thu Dec 3 23:55:09 2009
New Revision: 69884
Added:
pypy/branch/virtual-forcing/pypy/jit/metainterp/vref.py (contents, props changed)
Modified:
pypy/branch/virtual-forcing/pypy/jit/metainterp/pyjitpl.py
pypy/branch/virtual-forcing/pypy/jit/metainterp/test/test_virtualizable.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/warmspot.py
Log:
Support for virtual_ref(), step 2: implement a logic that seems a bit
more correct now. It allows us to at least detect during tracing when
some place forces a virtual, and give up tracing.
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 Thu Dec 3 23:55:09 2009
@@ -5,7 +5,7 @@
from pypy.rlib.unroll import unrolling_iterable
from pypy.rlib.debug import debug_start, debug_stop, debug_print
-from pypy.jit.metainterp import history, compile, resume
+from pypy.jit.metainterp import history, compile, resume, vref
from pypy.jit.metainterp.history import Const, ConstInt, Box
from pypy.jit.metainterp.resoperation import rop
from pypy.jit.metainterp import codewriter, executor
@@ -238,7 +238,7 @@
for _opimpl in ['int_is_true', 'int_neg', 'int_invert', 'bool_not',
'cast_ptr_to_int', 'cast_float_to_int',
'cast_int_to_float', 'float_neg', 'float_abs',
- 'float_is_true', 'virtual_ref',
+ 'float_is_true',
]:
exec py.code.Source('''
@arguments("box")
@@ -886,6 +886,14 @@
return self.metainterp.finishframe_exception(self.exception_box,
self.exc_value_box)
+ @arguments("box")
+ def opimpl_virtual_ref(self, box):
+ obj = box.getref_base()
+ res = vref.virtual_ref_during_tracing(self.metainterp, obj)
+ resbox = history.BoxPtr(res)
+ self.metainterp.history.record(rop.VIRTUAL_REF, [box], resbox)
+ self.make_result_box(resbox)
+
# ------------------------------
def setup_call(self, argboxes):
@@ -994,6 +1002,7 @@
# xxx do something about code duplication
resbox = self.metainterp.execute_and_record_varargs(
rop.CALL_MAY_FORCE, argboxes, descr=descr)
+ self.metainterp.virtual_after_residual_call()
self.metainterp.vable_after_residual_call()
if resbox is not None:
self.make_result_box(resbox)
@@ -1194,6 +1203,7 @@
class MetaInterp(object):
in_recursion = 0
_already_allocated_resume_virtuals = None
+ _force_token_mem = None
def __init__(self, staticdata):
self.staticdata = staticdata
@@ -1755,6 +1765,15 @@
if vable_escapes:
self.load_fields_from_virtualizable()
+ def virtual_after_residual_call(self):
+ if self.is_blackholing() or not vref.was_forced(self):
+ 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
+ # assembler from there, we will get assembler that probably always
+ # forces a vref. So we just cancel now.
+ self.switch_to_blackhole()
+
def handle_exception(self):
etype = self.cpu.get_exception()
evalue = self.cpu.get_exc_value()
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 Thu Dec 3 23:55:09 2009
@@ -944,9 +944,11 @@
for block, op in graph.iterblockops()
if op.opname == 'direct_call']
- assert direct_calls(f_graph) == ['__init__', 'force_if_necessary', 'll_portal_runner']
- assert direct_calls(portal_graph) == ['force_if_necessary', 'maybe_enter_jit']
-
+ assert direct_calls(f_graph) == ['__init__',
+ 'force_virtualizable_if_necessary',
+ 'll_portal_runner']
+ assert direct_calls(portal_graph)==['force_virtualizable_if_necessary',
+ 'maybe_enter_jit']
assert direct_calls(init_graph) == []
def test_virtual_child_frame(self):
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 Thu Dec 3 23:55:09 2009
@@ -20,7 +20,36 @@
self.interp_operations(f, [])
self.check_operations_history(virtual_ref=1)
+ def test_make_vref_and_force(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)
+ total += force_me() - 100
+ return total
+ #
+ res = self.meta_interp(f, [-4])
+ assert res == 16 * 19
+ self.check_loops({}) # because we aborted tracing
+
def test_simple_no_access(self):
+ py.test.skip("in-progress")
myjitdriver = JitDriver(greens = [], reds = ['n'])
#
class XY:
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 Thu Dec 3 23:55:09 2009
@@ -153,15 +153,16 @@
def finish(self):
#
- def force_if_necessary(virtualizable):
+ def force_virtualizable_if_necessary(virtualizable):
if virtualizable.vable_token:
self.force_now(virtualizable)
- force_if_necessary._always_inline_ = True
+ force_virtualizable_if_necessary._always_inline_ = True
#
all_graphs = self.warmrunnerdesc.translator.graphs
ts = self.warmrunnerdesc.cpu.ts
(_, FUNCPTR) = ts.get_FuncType([self.VTYPEPTR], lltype.Void)
- funcptr = self.warmrunnerdesc.helper_func(FUNCPTR, force_if_necessary)
+ funcptr = self.warmrunnerdesc.helper_func(
+ FUNCPTR, force_virtualizable_if_necessary)
rvirtualizable2.replace_force_virtualizable_with_call(
all_graphs, self.VTYPEPTR, funcptr)
Added: pypy/branch/virtual-forcing/pypy/jit/metainterp/vref.py
==============================================================================
--- (empty file)
+++ pypy/branch/virtual-forcing/pypy/jit/metainterp/vref.py Thu Dec 3 23:55:09 2009
@@ -0,0 +1,74 @@
+from pypy.rpython.rmodel import inputconst, log
+from pypy.rpython.lltypesystem import lltype, llmemory, rffi, rclass
+
+
+def replace_force_virtual_with_call(graphs, funcptr):
+ # 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)
+ count = 0
+ for graph in graphs:
+ for block in graph.iterblocks():
+ for op in block.operations:
+ if op.opname == 'jit_force_virtual':
+ op.opname = 'direct_call'
+ op.args = [c_funcptr, op.args[0]]
+ count += 1
+ log("replaced %d 'jit_force_virtual' with %r" % (count, funcptr))
+
+# ____________________________________________________________
+
+
+# we make the low-level type of an RPython class directly
+JIT_VIRTUAL_REF = lltype.GcStruct('JitVirtualRef',
+ ('super', rclass.OBJECT),
+ ('force_token', llmemory.Address),
+ ('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')
+
+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):
+ 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.forced = lltype.cast_opaque_ptr(rclass.OBJECTPTR, real_object)
+ assert vref.forced
+ return lltype.cast_opaque_ptr(llmemory.GCREF, vref)
+
+# ____________________________________________________________
+
+def force_virtual_if_necessary(inst):
+ if not inst or inst.typeptr != jit_virtual_ref_vtable:
+ return inst # common, fast case
+ return force_virtual(inst)
+
+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
+ 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 Thu Dec 3 23:55:09 2009
@@ -1,4 +1,4 @@
-import sys
+import sys, py
from pypy.rpython.lltypesystem import lltype, llmemory, rclass, rstr
from pypy.rpython.ootypesystem import ootype
from pypy.rpython.annlowlevel import llhelper, MixLevelHelperAnnotator,\
@@ -17,7 +17,7 @@
from pypy.translator.unsimplify import call_final_function
from pypy.jit.metainterp import codewriter
-from pypy.jit.metainterp import support, history, pyjitpl, gc
+from pypy.jit.metainterp import support, history, pyjitpl, gc, vref
from pypy.jit.metainterp.pyjitpl import MetaInterpStaticData, MetaInterp
from pypy.jit.metainterp.policy import JitPolicy
from pypy.jit.metainterp.typesystem import LLTypeHelper, OOTypeHelper
@@ -177,6 +177,7 @@
)
self.rewrite_can_enter_jit()
self.rewrite_set_param()
+ self.rewrite_force_virtual()
self.add_profiler_finish()
self.metainterp_sd.finish_setup(optimizer=optimizer)
@@ -599,6 +600,15 @@
op.opname = 'direct_call'
op.args[:3] = [closures[funcname]]
+ 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)
+
def decode_hp_hint_args(op):
# Returns (list-of-green-vars, list-of-red-vars) without Voids.
More information about the Pypy-commit
mailing list