[pypy-svn] r70415 - in pypy/trunk/pypy: interpreter jit/metainterp jit/metainterp/test module/pypyjit rlib
arigo at codespeak.net
arigo at codespeak.net
Tue Jan 5 12:31:21 CET 2010
Author: arigo
Date: Tue Jan 5 12:31:20 2010
New Revision: 70415
Modified:
pypy/trunk/pypy/interpreter/baseobjspace.py
pypy/trunk/pypy/interpreter/executioncontext.py
pypy/trunk/pypy/interpreter/pyframe.py
pypy/trunk/pypy/jit/metainterp/test/test_basic.py
pypy/trunk/pypy/jit/metainterp/test/test_warmstate.py
pypy/trunk/pypy/jit/metainterp/warmspot.py
pypy/trunk/pypy/jit/metainterp/warmstate.py
pypy/trunk/pypy/module/pypyjit/interp_jit.py
pypy/trunk/pypy/rlib/jit.py
Log:
Merge the branch/jit-trace, trying to be safe JIT-wise
against using the profile or tracing hooks.
Modified: pypy/trunk/pypy/interpreter/baseobjspace.py
==============================================================================
--- pypy/trunk/pypy/interpreter/baseobjspace.py (original)
+++ pypy/trunk/pypy/interpreter/baseobjspace.py Tue Jan 5 12:31:20 2010
@@ -9,7 +9,7 @@
from pypy.rlib.objectmodel import we_are_translated
from pypy.rlib.debug import make_sure_not_resized
from pypy.rlib.timer import DummyTimer, Timer
-from pypy.rlib.jit import we_are_jitted, dont_look_inside, unroll_safe
+from pypy.rlib.jit import we_are_jitted, unroll_safe
import os, sys
__all__ = ['ObjSpace', 'OperationError', 'Wrappable', 'W_Root']
@@ -819,7 +819,6 @@
args = frame.make_arguments(nargs)
return self.call_args(w_func, args)
- @dont_look_inside
def call_args_and_c_profile(self, frame, w_func, args):
ec = self.getexecutioncontext()
ec.c_call_trace(frame, w_func)
Modified: pypy/trunk/pypy/interpreter/executioncontext.py
==============================================================================
--- pypy/trunk/pypy/interpreter/executioncontext.py (original)
+++ pypy/trunk/pypy/interpreter/executioncontext.py Tue Jan 5 12:31:20 2010
@@ -3,7 +3,6 @@
from pypy.interpreter.error import OperationError
from pypy.rlib.rarithmetic import LONG_BIT
from pypy.rlib.unroll import unrolling_iterable
-from pypy.rlib.jit import we_are_jitted
from pypy.rlib import jit
def app_profile_call(space, w_callable, frame, event, w_arg):
@@ -22,10 +21,10 @@
# tracing: space.frame_trace_action.fire() must be called to ensure
# that tracing occurs whenever self.w_tracefunc or self.is_tracing
# is modified.
- self.w_tracefunc = None
+ self.w_tracefunc = None # if not None, no JIT
self.is_tracing = 0
self.compiler = space.createcompiler()
- self.profilefunc = None
+ self.profilefunc = None # if not None, no JIT
self.w_profilefuncarg = None
def gettopframe(self):
@@ -54,15 +53,17 @@
def leave(self, frame):
try:
- if self.profilefunc:
- self._trace(frame, 'leaveframe', self.space.w_None)
+ if not jit.we_are_jitted():
+ if self.profilefunc:
+ self._trace(frame, 'leaveframe', self.space.w_None)
finally:
self.topframeref = frame.f_backref
self.framestackdepth -= 1
jit.virtual_ref_finish(frame)
- if self.w_tracefunc is not None and not frame.hide():
- self.space.frame_trace_action.fire()
+ if not jit.we_are_jitted():
+ if self.w_tracefunc is not None and not frame.hide():
+ self.space.frame_trace_action.fire()
# ________________________________________________________________
@@ -144,7 +145,6 @@
space.setitem(w_globals, w_key, w_value)
return w_globals
- @jit.dont_look_inside
def c_call_trace(self, frame, w_func):
"Profile the call of a builtin function"
if self.profilefunc is None:
@@ -152,7 +152,6 @@
else:
self._trace(frame, 'c_call', w_func)
- @jit.dont_look_inside
def c_return_trace(self, frame, w_retval):
"Profile the return from a builtin function"
if self.profilefunc is None:
@@ -160,7 +159,6 @@
else:
self._trace(frame, 'c_return', w_retval)
- @jit.dont_look_inside
def c_exception_trace(self, frame, w_exc):
"Profile function called upon OperationError."
if self.profilefunc is None:
@@ -168,7 +166,6 @@
else:
self._trace(frame, 'c_exception', w_exc)
- @jit.dont_look_inside
def call_trace(self, frame):
"Trace the call of a function"
if self.w_tracefunc is not None or self.profilefunc is not None:
@@ -176,7 +173,6 @@
if self.profilefunc:
frame.is_being_profiled = True
- @jit.dont_look_inside
def return_trace(self, frame, w_retval):
"Trace the return from a function"
if self.w_tracefunc is not None:
@@ -195,7 +191,6 @@
actionflag.action_dispatcher(self, frame) # slow path
bytecode_trace._always_inline_ = True
- @jit.dont_look_inside
def exception_trace(self, frame, operationerr):
"Trace function called upon OperationError."
operationerr.record_interpreter_traceback()
@@ -218,6 +213,7 @@
if self.space.is_w(w_func, self.space.w_None):
self.w_tracefunc = None
else:
+ self.force_all_frames()
self.w_tracefunc = w_func
self.space.frame_trace_action.fire()
@@ -230,16 +226,27 @@
self.setllprofile(app_profile_call, w_func)
def setllprofile(self, func, w_arg):
- self.profilefunc = func
if func is not None:
if w_arg is None:
raise ValueError("Cannot call setllprofile with real None")
- frame = self.gettopframe_nohidden()
- while frame:
- frame.is_being_profiled = True
- frame = self.getnextframe_nohidden(frame)
+ self.force_all_frames(is_being_profiled=True)
+ self.profilefunc = func
self.w_profilefuncarg = w_arg
+ def force_all_frames(self, is_being_profiled=False):
+ # "Force" all frames in the sense of the jit, and optionally
+ # set the flag 'is_being_profiled' on them. A forced frame is
+ # one out of which the jit will exit: if it is running so far,
+ # in a piece of assembler currently running a CALL_MAY_FORCE,
+ # then being forced means that it will fail the following
+ # GUARD_NOT_FORCED operation, and so fall back to interpreted
+ # execution.
+ frame = self.gettopframe_nohidden()
+ while frame:
+ if is_being_profiled:
+ frame.is_being_profiled = True
+ frame = self.getnextframe_nohidden(frame)
+
def call_tracing(self, w_func, w_args):
is_tracing = self.is_tracing
self.is_tracing = 0
@@ -448,7 +455,7 @@
def fire_after_thread_switch(self):
"""Bit of a hack: fire() the action but only the next time the GIL
- is released and re-acquired (i.e. after a portential thread switch).
+ is released and re-acquired (i.e. after a potential thread switch).
Don't call this if threads are not enabled.
"""
from pypy.module.thread.gil import spacestate
Modified: pypy/trunk/pypy/interpreter/pyframe.py
==============================================================================
--- pypy/trunk/pypy/interpreter/pyframe.py (original)
+++ pypy/trunk/pypy/interpreter/pyframe.py Tue Jan 5 12:31:20 2010
@@ -391,6 +391,7 @@
new_frame.instr_prev = space.int_w(w_instr_prev)
self._setcellvars(cellvars)
+ # XXX what if the frame is in another thread??
space.frame_trace_action.fire()
def hide(self):
Modified: pypy/trunk/pypy/jit/metainterp/test/test_basic.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/test/test_basic.py (original)
+++ pypy/trunk/pypy/jit/metainterp/test/test_basic.py Tue Jan 5 12:31:20 2010
@@ -385,6 +385,26 @@
res = self.meta_interp(f, [55])
assert res == -1
+ def test_confirm_enter_jit(self):
+ def confirm_enter_jit(x, y):
+ return x <= 5
+ myjitdriver = JitDriver(greens = ['x'], reds = ['y'],
+ confirm_enter_jit = confirm_enter_jit)
+ def f(x, y):
+ while y >= 0:
+ myjitdriver.can_enter_jit(x=x, y=y)
+ myjitdriver.jit_merge_point(x=x, y=y)
+ y -= x
+ return y
+ #
+ res = self.meta_interp(f, [10, 84])
+ assert res == -6
+ self.check_loop_count(0)
+ #
+ res = self.meta_interp(f, [3, 19])
+ assert res == -2
+ self.check_loop_count(1)
+
def test_format(self):
def f(n):
return len("<%d>" % n)
Modified: pypy/trunk/pypy/jit/metainterp/test/test_warmstate.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/test/test_warmstate.py (original)
+++ pypy/trunk/pypy/jit/metainterp/test/test_warmstate.py Tue Jan 5 12:31:20 2010
@@ -165,6 +165,7 @@
class FakeWarmRunnerDesc:
can_inline_ptr = None
get_printable_location_ptr = None
+ confirm_enter_jit_ptr = None
green_args_spec = [lltype.Signed, lltype.Float]
class FakeCell:
dont_trace_here = False
@@ -192,6 +193,7 @@
green_args_spec = [lltype.Signed, lltype.Float]
can_inline_ptr = llhelper(CAN_INLINE, can_inline)
get_printable_location_ptr = None
+ confirm_enter_jit_ptr = None
state = WarmEnterState(FakeWarmRunnerDesc())
def jit_getter(*args):
return FakeCell()
@@ -212,7 +214,27 @@
green_args_spec = [lltype.Signed, lltype.Float]
can_inline_ptr = None
get_printable_location_ptr = llhelper(GET_LOCATION, get_location)
+ confirm_enter_jit_ptr = None
state = WarmEnterState(FakeWarmRunnerDesc())
state.make_jitdriver_callbacks()
res = state.get_location_str([BoxInt(5), BoxFloat(42.5)])
assert res == "hi there"
+
+def test_make_jitdriver_callbacks_4():
+ def confirm_enter_jit(x, y, z):
+ assert x == 5
+ assert y == 42.5
+ assert z == 3
+ return True
+ ENTER_JIT = lltype.Ptr(lltype.FuncType([lltype.Signed, lltype.Float,
+ lltype.Signed], lltype.Bool))
+ class FakeWarmRunnerDesc:
+ rtyper = None
+ green_args_spec = [lltype.Signed, lltype.Float]
+ can_inline_ptr = None
+ get_printable_location_ptr = None
+ confirm_enter_jit_ptr = llhelper(ENTER_JIT, confirm_enter_jit)
+ state = WarmEnterState(FakeWarmRunnerDesc())
+ state.make_jitdriver_callbacks()
+ res = state.confirm_enter_jit(5, 42.5, 3)
+ assert res is True
Modified: pypy/trunk/pypy/jit/metainterp/warmspot.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/warmspot.py (original)
+++ pypy/trunk/pypy/jit/metainterp/warmspot.py Tue Jan 5 12:31:20 2010
@@ -402,9 +402,13 @@
annhelper, self.jitdriver.can_inline, annmodel.s_Bool)
self.get_printable_location_ptr = self._make_hook_graph(
annhelper, self.jitdriver.get_printable_location, s_Str)
+ self.confirm_enter_jit_ptr = self._make_hook_graph(
+ annhelper, self.jitdriver.confirm_enter_jit, annmodel.s_Bool,
+ onlygreens=False)
annhelper.finish()
- def _make_hook_graph(self, annhelper, func, s_result, s_first_arg=None):
+ def _make_hook_graph(self, annhelper, func, s_result, s_first_arg=None,
+ onlygreens=True):
if func is None:
return None
#
@@ -412,7 +416,9 @@
if s_first_arg is not None:
extra_args_s.append(s_first_arg)
#
- args_s = self.portal_args_s[:len(self.green_args_spec)]
+ args_s = self.portal_args_s
+ if onlygreens:
+ args_s = args_s[:len(self.green_args_spec)]
graph = annhelper.getgraph(func, extra_args_s + args_s, s_result)
funcptr = annhelper.graph2delayed(graph)
return funcptr
Modified: pypy/trunk/pypy/jit/metainterp/warmstate.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/warmstate.py (original)
+++ pypy/trunk/pypy/jit/metainterp/warmstate.py Tue Jan 5 12:31:20 2010
@@ -196,6 +196,7 @@
get_jitcell = self.make_jitcell_getter()
set_future_values = self.make_set_future_values()
self.make_jitdriver_callbacks()
+ confirm_enter_jit = self.confirm_enter_jit
def maybe_compile_and_run(*args):
"""Entry point to the JIT. Called at the point with the
@@ -227,6 +228,9 @@
cell.counter = n
return
# bound reached; start tracing
+ if not confirm_enter_jit(*args):
+ cell.counter = 0
+ return
from pypy.jit.metainterp.pyjitpl import MetaInterp
metainterp = MetaInterp(metainterp_sd)
try:
@@ -237,6 +241,8 @@
self.disable_noninlinable_function(metainterp)
raise
else:
+ if not confirm_enter_jit(*args):
+ return
# machine code was already compiled for these greenargs
# get the assembler and fill in the boxes
set_future_values(*args[num_green_args:])
@@ -465,7 +471,6 @@
greenargs = unwrap_greenkey(greenkey)
return can_inline(*greenargs)
self.can_inline_callable = can_inline_greenkey
-
#
get_location_ptr = self.warmrunnerdesc.get_printable_location_ptr
if get_location_ptr is None:
@@ -483,3 +488,16 @@
res = hlstr(res)
return res
self.get_location_str = get_location_str
+ #
+ confirm_enter_jit_ptr = self.warmrunnerdesc.confirm_enter_jit_ptr
+ if confirm_enter_jit_ptr is None:
+ def confirm_enter_jit(*args):
+ return True
+ else:
+ rtyper = self.warmrunnerdesc.rtyper
+ #
+ def confirm_enter_jit(*args):
+ fn = support.maybe_on_top_of_llinterp(rtyper,
+ confirm_enter_jit_ptr)
+ return fn(*args)
+ self.confirm_enter_jit = confirm_enter_jit
Modified: pypy/trunk/pypy/module/pypyjit/interp_jit.py
==============================================================================
--- pypy/trunk/pypy/module/pypyjit/interp_jit.py (original)
+++ pypy/trunk/pypy/module/pypyjit/interp_jit.py Tue Jan 5 12:31:20 2010
@@ -41,6 +41,11 @@
def set_jitcell_at(newcell, next_instr, bytecode):
bytecode.jit_cells[next_instr] = newcell
+def confirm_enter_jit(next_instr, bytecode, frame, ec):
+ return (frame.w_f_trace is None and
+ ec.profilefunc is None and
+ ec.w_tracefunc is None)
+
class PyPyJitDriver(JitDriver):
reds = ['frame', 'ec']
@@ -58,7 +63,8 @@
pypyjitdriver = PyPyJitDriver(can_inline = can_inline,
get_printable_location = get_printable_location,
get_jitcell_at = get_jitcell_at,
- set_jitcell_at = set_jitcell_at)
+ set_jitcell_at = set_jitcell_at,
+ confirm_enter_jit = confirm_enter_jit)
class __extend__(PyFrame):
Modified: pypy/trunk/pypy/rlib/jit.py
==============================================================================
--- pypy/trunk/pypy/rlib/jit.py (original)
+++ pypy/trunk/pypy/rlib/jit.py Tue Jan 5 12:31:20 2010
@@ -99,6 +99,25 @@
hop.exception_cannot_occur()
return hop.inputconst(lltype.Signed, _we_are_jitted)
+
+##def force_virtualizable(virtualizable):
+## pass
+
+##class Entry(ExtRegistryEntry):
+## _about_ = force_virtualizable
+
+## def compute_result_annotation(self):
+## from pypy.annotation import model as annmodel
+## return annmodel.s_None
+
+## def specialize_call(self, hop):
+## [vinst] = hop.inputargs(hop.args_r[0])
+## cname = inputconst(lltype.Void, None)
+## cflags = inputconst(lltype.Void, {})
+## hop.exception_cannot_occur()
+## return hop.genop('jit_force_virtualizable', [vinst, cname, cflags],
+## resulttype=lltype.Void)
+
# ____________________________________________________________
# VRefs
@@ -196,6 +215,7 @@
def __init__(self, greens=None, reds=None, virtualizables=None,
get_jitcell_at=None, set_jitcell_at=None,
can_inline=None, get_printable_location=None,
+ confirm_enter_jit=None,
leave=None): # XXX 'leave' is deprecated
if greens is not None:
self.greens = greens
@@ -213,6 +233,7 @@
self.set_jitcell_at = set_jitcell_at
self.get_printable_location = get_printable_location
self.can_inline = can_inline
+ self.confirm_enter_jit = confirm_enter_jit
self.leave = leave
def _freeze_(self):
More information about the Pypy-commit
mailing list