[pypy-svn] r70702 - in pypy/branch/cli-jit/pypy: interpreter jit/metainterp jit/metainterp/test module/pypyjit rlib
antocuni at codespeak.net
antocuni at codespeak.net
Tue Jan 19 14:12:00 CET 2010
Author: antocuni
Date: Tue Jan 19 14:11:59 2010
New Revision: 70702
Modified:
pypy/branch/cli-jit/pypy/interpreter/baseobjspace.py
pypy/branch/cli-jit/pypy/interpreter/executioncontext.py
pypy/branch/cli-jit/pypy/interpreter/pyframe.py
pypy/branch/cli-jit/pypy/interpreter/pyopcode.py
pypy/branch/cli-jit/pypy/jit/metainterp/test/test_basic.py
pypy/branch/cli-jit/pypy/jit/metainterp/test/test_warmstate.py
pypy/branch/cli-jit/pypy/jit/metainterp/warmspot.py
pypy/branch/cli-jit/pypy/jit/metainterp/warmstate.py
pypy/branch/cli-jit/pypy/module/pypyjit/interp_jit.py
pypy/branch/cli-jit/pypy/rlib/jit.py
Log:
merge r70415 and r70454 from trunk: merge the jit-trace branch and kill a lot
of "we_are_jitted", to make sys.settrace working inside loops
Modified: pypy/branch/cli-jit/pypy/interpreter/baseobjspace.py
==============================================================================
--- pypy/branch/cli-jit/pypy/interpreter/baseobjspace.py (original)
+++ pypy/branch/cli-jit/pypy/interpreter/baseobjspace.py Tue Jan 19 14:11:59 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 unroll_safe
import os, sys
__all__ = ['ObjSpace', 'OperationError', 'Wrappable', 'W_Root']
@@ -756,8 +756,7 @@
def call_valuestack(self, w_func, nargs, frame):
from pypy.interpreter.function import Function, Method, is_builtin_code
- if (not we_are_jitted() and frame.is_being_profiled and
- is_builtin_code(w_func)):
+ if frame.is_being_profiled and is_builtin_code(w_func):
# XXX: this code is copied&pasted :-( from the slow path below
# call_valuestack().
args = frame.make_arguments(nargs)
@@ -784,7 +783,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/branch/cli-jit/pypy/interpreter/executioncontext.py
==============================================================================
--- pypy/branch/cli-jit/pypy/interpreter/executioncontext.py (original)
+++ pypy/branch/cli-jit/pypy/interpreter/executioncontext.py Tue Jan 19 14:11:59 2010
@@ -3,8 +3,8 @@
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
+from pypy.rlib.jit import we_are_jitted
def app_profile_call(space, w_callable, frame, event, w_arg):
space.call_function(w_callable,
@@ -15,16 +15,21 @@
"""An ExecutionContext holds the state of an execution thread
in the Python interpreter."""
+ # XXX JIT: when tracing (but not when blackholing!), the following
+ # XXX fields should be known to a constant None or False:
+ # XXX self.w_tracefunc, self.profilefunc
+ # XXX frame.is_being_profiled
+
def __init__(self, space):
self.space = space
self._init_frame_chain()
# 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_nohidden(self):
@@ -50,7 +55,6 @@
def leave(self, frame):
if self.profilefunc:
self._trace(frame, 'leaveframe', self.space.w_None)
-
self._unchain(frame)
if self.w_tracefunc is not None and not frame.hide():
@@ -269,7 +273,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:
@@ -277,7 +280,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:
@@ -285,7 +287,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:
@@ -293,7 +294,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:
@@ -301,7 +301,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:
@@ -320,7 +319,14 @@
actionflag.action_dispatcher(self, frame) # slow path
bytecode_trace._always_inline_ = True
- @jit.dont_look_inside
+ def bytecode_trace_after_exception(self, frame):
+ "Like bytecode_trace(), but without increasing the ticker."
+ actionflag = self.space.actionflag
+ ticker = actionflag.get()
+ if ticker & actionflag.interesting_bits: # fast check
+ actionflag.action_dispatcher(self, frame) # slow path
+ bytecode_trace_after_exception._always_inline_ = True
+
def exception_trace(self, frame, operationerr):
"Trace function called upon OperationError."
operationerr.record_interpreter_traceback()
@@ -343,6 +349,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()
@@ -355,16 +362,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
@@ -573,7 +591,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/branch/cli-jit/pypy/interpreter/pyframe.py
==============================================================================
--- pypy/branch/cli-jit/pypy/interpreter/pyframe.py (original)
+++ pypy/branch/cli-jit/pypy/interpreter/pyframe.py Tue Jan 19 14:11:59 2010
@@ -9,7 +9,7 @@
from pypy.interpreter import pytraceback
import opcode
from pypy.rlib.objectmodel import we_are_translated, instantiate
-from pypy.rlib.jit import we_are_jitted, hint
+from pypy.rlib.jit import hint
from pypy.rlib.debug import make_sure_not_resized
from pypy.rlib import jit
@@ -142,8 +142,7 @@
executioncontext = self.space.getexecutioncontext()
executioncontext.enter(self)
try:
- if not we_are_jitted():
- executioncontext.call_trace(self)
+ executioncontext.call_trace(self)
# Execution starts just after the last_instr. Initially,
# last_instr is -1. After a generator suspends it points to
# the YIELD_VALUE instruction.
@@ -154,11 +153,9 @@
rstack.resume_point("execute_frame", self, executioncontext,
returns=w_exitvalue)
except Exception:
- if not we_are_jitted():
- executioncontext.return_trace(self, self.space.w_None)
+ executioncontext.return_trace(self, self.space.w_None)
raise
- if not we_are_jitted():
- executioncontext.return_trace(self, w_exitvalue)
+ executioncontext.return_trace(self, w_exitvalue)
finally:
executioncontext.leave(self)
return w_exitvalue
@@ -392,6 +389,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/branch/cli-jit/pypy/interpreter/pyopcode.py
==============================================================================
--- pypy/branch/cli-jit/pypy/interpreter/pyopcode.py (original)
+++ pypy/branch/cli-jit/pypy/interpreter/pyopcode.py Tue Jan 19 14:11:59 2010
@@ -130,7 +130,7 @@
def handle_operation_error(self, ec, operr, attach_tb=True):
if attach_tb:
- if not jit.we_are_jitted():
+ if 1:
# xxx this is a hack. It allows bytecode_trace() to
# call a signal handler which raises, and catch the
# raised exception immediately. See test_alarm_raise in
@@ -146,15 +146,14 @@
trace = self.w_f_trace
self.w_f_trace = None
try:
- ec.bytecode_trace(self)
+ ec.bytecode_trace_after_exception(self)
finally:
self.w_f_trace = trace
except OperationError, e:
operr = e
pytraceback.record_application_traceback(
self.space, operr, self, self.last_instr)
- if not jit.we_are_jitted():
- ec.exception_trace(self, operr)
+ ec.exception_trace(self, operr)
block = self.unrollstack(SApplicationException.kind)
if block is None:
@@ -913,13 +912,10 @@
arguments = f.popvalues(n_arguments)
args = f.argument_factory(arguments, keywords, keywords_w, w_star, w_starstar)
w_function = f.popvalue()
- if jit.we_are_jitted():
- w_result = f.space.call_args(w_function, args)
+ if f.is_being_profiled and is_builtin_code(w_function):
+ w_result = f.space.call_args_and_c_profile(f, w_function, args)
else:
- if f.is_being_profiled and is_builtin_code(w_function):
- w_result = f.space.call_args_and_c_profile(f, w_function, args)
- else:
- w_result = f.space.call_args(w_function, args)
+ w_result = f.space.call_args(w_function, args)
rstack.resume_point("call_function", f, returns=w_result)
f.pushvalue(w_result)
Modified: pypy/branch/cli-jit/pypy/jit/metainterp/test/test_basic.py
==============================================================================
--- pypy/branch/cli-jit/pypy/jit/metainterp/test/test_basic.py (original)
+++ pypy/branch/cli-jit/pypy/jit/metainterp/test/test_basic.py Tue Jan 19 14:11:59 2010
@@ -377,6 +377,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/branch/cli-jit/pypy/jit/metainterp/test/test_warmstate.py
==============================================================================
--- pypy/branch/cli-jit/pypy/jit/metainterp/test/test_warmstate.py (original)
+++ pypy/branch/cli-jit/pypy/jit/metainterp/test/test_warmstate.py Tue Jan 19 14:11:59 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/branch/cli-jit/pypy/jit/metainterp/warmspot.py
==============================================================================
--- pypy/branch/cli-jit/pypy/jit/metainterp/warmspot.py (original)
+++ pypy/branch/cli-jit/pypy/jit/metainterp/warmspot.py Tue Jan 19 14:11:59 2010
@@ -397,9 +397,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
#
@@ -407,7 +411,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/branch/cli-jit/pypy/jit/metainterp/warmstate.py
==============================================================================
--- pypy/branch/cli-jit/pypy/jit/metainterp/warmstate.py (original)
+++ pypy/branch/cli-jit/pypy/jit/metainterp/warmstate.py Tue Jan 19 14:11:59 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
@@ -225,6 +226,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:
@@ -235,6 +239,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:])
@@ -461,7 +467,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:
@@ -479,3 +484,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/branch/cli-jit/pypy/module/pypyjit/interp_jit.py
==============================================================================
--- pypy/branch/cli-jit/pypy/module/pypyjit/interp_jit.py (original)
+++ pypy/branch/cli-jit/pypy/module/pypyjit/interp_jit.py Tue Jan 19 14:11:59 2010
@@ -47,6 +47,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']
@@ -65,7 +70,8 @@
get_printable_location = get_printable_location,
leave = leave,
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/branch/cli-jit/pypy/rlib/jit.py
==============================================================================
--- pypy/branch/cli-jit/pypy/rlib/jit.py (original)
+++ pypy/branch/cli-jit/pypy/rlib/jit.py Tue Jan 19 14:11:59 2010
@@ -97,6 +97,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)
+
# ____________________________________________________________
# User interface for the hotpath JIT policy
@@ -134,7 +153,8 @@
def __init__(self, greens=None, reds=None, virtualizables=None,
get_jitcell_at=None, set_jitcell_at=None,
can_inline=None, get_printable_location=None,
- leave=None):
+ confirm_enter_jit=None,
+ leave=None): # XXX 'leave' is deprecated
if greens is not None:
self.greens = greens
if reds is not None:
@@ -151,6 +171,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