[pypy-svn] r52390 - pypy/branch/jit-hotpath/pypy/jit/rainbow
arigo at codespeak.net
arigo at codespeak.net
Tue Mar 11 20:23:48 CET 2008
Author: arigo
Date: Tue Mar 11 20:23:47 2008
New Revision: 52390
Modified:
pypy/branch/jit-hotpath/pypy/jit/rainbow/hotpath.py
pypy/branch/jit-hotpath/pypy/jit/rainbow/rhotpath.py
Log:
Roughly finished the FallbackPoint logic.
Next missing piece is the fallback interpreter itself.
Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/hotpath.py
==============================================================================
--- pypy/branch/jit-hotpath/pypy/jit/rainbow/hotpath.py (original)
+++ pypy/branch/jit-hotpath/pypy/jit/rainbow/hotpath.py Tue Mar 11 20:23:47 2008
@@ -67,11 +67,14 @@
state = HotEnterState()
def jit_may_enter(*args):
- if not state.machine_code:
- state.counter += 1
- if state.counter < self.threshold:
+ counter = state.counter
+ if counter >= 0:
+ counter += 1
+ if counter < self.threshold:
+ state.counter = counter
+ return
+ if not state.compile():
return
- state.compile()
maybe_on_top_of_llinterp(self, state.machine_code)(*args)
HotEnterState.compile.im_func._dont_inline_ = True
@@ -112,13 +115,15 @@
class HotEnterState:
def __init__(self):
self.machine_code = lltype.nullptr(rewriter.RESIDUAL_FUNCTYPE)
- self.counter = 0
+ self.counter = 0 # -1 means "compiled"
def compile(self):
try:
self._compile()
+ return True
except Exception, e:
rhotpath.report_compile_time_exception(e)
+ return False
def _compile(self):
interp = rewriter.interpreter
@@ -144,6 +149,7 @@
FUNCPTR = lltype.Ptr(rewriter.RESIDUAL_FUNCTYPE)
self.machine_code = gv_generated.revealconst(FUNCPTR)
+ self.counter = -1 # compiled
return HotEnterState
Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/rhotpath.py
==============================================================================
--- pypy/branch/jit-hotpath/pypy/jit/rainbow/rhotpath.py (original)
+++ pypy/branch/jit-hotpath/pypy/jit/rainbow/rhotpath.py Tue Mar 11 20:23:47 2008
@@ -42,12 +42,11 @@
builder = jitstate.curbuilder
builder.start_writing()
try:
- try:
- interp.bytecode_loop()
- except GenerateReturn:
- pass
+ interp.bytecode_loop()
except FinishedCompiling:
pass
+ except GenerateReturn:
+ leave_graph(interp)
else:
leave_graph(interp)
builder.end()
@@ -64,10 +63,9 @@
traceback.print_exc()
print >> sys.stderr
pdb.post_mortem(sys.exc_info()[2])
- # XXX I think compile-time errors don't have to be fatal
- # any more
- lloperation.llop.debug_fatalerror(
- lltype.Void, "compilation-time error %s" % e)
+ else:
+ msg = 'Note: the JIT got a compile-time exception: %s' % (e,)
+ lloperation.llop.debug_print(lltype.Void, msg)
# ____________________________________________________________
@@ -85,24 +83,55 @@
def __init__(self, ERASED, interpreter, threshold):
self.exceptiondesc = interpreter.exceptiondesc
+ self.gv_constant_one = interpreter.rgenop.constPrebuiltGlobal(1)
def ll_reach_fallback_point(fallback_point_ptr, value, framebase):
try:
- promotion_point = _cast_base_ptr_to_promotion_point(
- promotion_point_ptr)
- path = [None]
- root = promotion_point.promotion_path.follow_path(path)
- gv_value = root.rgenop.genconst(value)
- resuminginfo = ResumingInfo(promotion_point, gv_value, path)
- root.reach_fallback_point(resuminginfo)
- interpreter.portalstate.compile_more_functions()
+ fbp = fallback_point_ptr # XXX cast
+ assert lltype.typeOf(value) is lltype.Bool # XXX for now
+ if value:
+ counter = fbp.truepath_counter
+ else:
+ counter = fbp.falsepath_counter
+ assert counter >= 0, (
+ "reaching a fallback point for an already-compiled path")
+ counter += 1
+
+ if counter >= threshold:
+ # this is a hot path, compile it
+ gv_value = fbp.getrgenop().genconst(value)
+ fbp.compile_hot_path()
+ if value:
+ fbp.truepath_counter = -1 # mean "compiled"
+ else:
+ fbp.falsepath_counter = -1 # mean "compiled"
+ # Done. We return 1, which causes our caller
+ # (machine code produced by hotsplit()) to loop back to
+ # the flexswitch and execute the newly-generated code.
+ return 1
+ else:
+ # path is still cold
+ if value:
+ fbp.truepath_counter = counter
+ else:
+ fbp.falsepath_counter = counter
+
except Exception, e:
report_compile_time_exception(e)
+
+ # exceptions below at run-time exceptions, we let them propagate
+ fbp.run_fallback_interpreter(framebase)
+ # the fallback interpreter reached the next jit_merge_point();
+ # we return 0, causing the machine code that called us to exit
+ # and go back to its own caller, which is jit_may_enter() from
+ # hotpath.py.
+ return 0
+
self.ll_reach_fallback_point = ll_reach_fallback_point
- ll_reach_fallback_point._debugexc = True
+ #ll_reach_fallback_point._debugexc = True
FUNCTYPE = lltype.FuncType([base_ptr_lltype(), ERASED,
- llmemory.Address], lltype.Void)
+ llmemory.Address], lltype.Signed)
FUNCPTRTYPE = lltype.Ptr(FUNCTYPE)
self.FUNCPTRTYPE = FUNCPTRTYPE
self.sigtoken = interpreter.rgenop.sigToken(FUNCTYPE)
@@ -123,6 +152,8 @@
truepath_counter = 0 # -1 after this path was compiled
def __init__(self, jitstate, flexswitch, frameinfo):
+ # XXX we should probably trim down the jitstate once our caller
+ # is done with it, to avoid keeping too much stuff in memory
self.saved_jitstate = jitstate
self.flexswitch = flexswitch
self.frameinfo = frameinfo
@@ -130,6 +161,9 @@
# its GenVars, so that we can fish these values to pass them
# to the fallback interpreter
+ def getrgenop(self):
+ return self.saved_jitstate.curbuilder.rgenop
+
# hack for testing: make the llinterpreter believe this is a Ptr to base
# instance
_TYPE = base_ptr_lltype()
@@ -137,7 +171,7 @@
def hotsplit(jitstate, hotpromotiondesc, switchbox):
# produce a Bool flexswitch for now
- incoming = jitstate.enter_block()
+ incoming = jitstate.enter_block_sweep_virtualizables()
switchblock = rtimeshift.enter_next_block(jitstate, incoming)
gv_switchvar = switchbox.genvar
incoming_gv = [box.genvar for box in incoming]
@@ -152,21 +186,25 @@
gv_switchvar = switchbox.genvar
gv_fnptr = hotpromotiondesc.get_gv_reach_fallback_point(default_builder)
gv_framebase = default_builder.genop_get_frame_base()
- default_builder.genop_call(hotpromotiondesc.sigtoken,
- gv_fnptr,
- [gv_fbp, gv_switchvar, gv_framebase])
- # loop back to 'switchblock' unless an exception occurred
- # (only "real" run-time exceptions should arrive here, not
- # compile-time exceptions)
- exceptiondesc = hotpromotiondesc.exceptiondesc
- gv_exc_type = exceptiondesc.genop_get_exc_type(default_builder)
- gv_occurred = default_builder.genop_ptr_nonzero(
- exceptiondesc.exc_type_token, gv_exc_type)
- excpath_builder = default_builder.jump_if_true(gv_occurred, [])
+ gv_res = default_builder.genop_call(hotpromotiondesc.sigtoken,
+ gv_fnptr,
+ [gv_fbp, gv_switchvar, gv_framebase])
+ # There are three ways the call above can return:
+ # * 1: continue running by looping back to 'switchblock'
+ # * 0: leave the machine code now, as with a return
+ # * exception: leave the machine code now, propagating the exception
+ # (only "real" run-time exceptions should arrive here, not
+ # compile-time exceptions)
+ # As a minor hack, we know by the way the exception transformer works
+ # that in the third case the return value we get is -1, so we can
+ # just leave the machine code if we can any value != 1.
+ gv_leave_flag = default_builder.genop2("int_ne", gv_res,
+ hotpromotiondesc.gv_constant_one)
+ leaving_builder = default_builder.jump_if_true(gv_leave_flag, [])
default_builder.finish_and_goto(incoming_gv, switchblock)
- jitstate.curbuilder = excpath_builder
- excpath_builder.start_writing()
+ jitstate.curbuilder = leaving_builder
+ leaving_builder.start_writing()
raise GenerateReturn
# ____________________________________________________________
More information about the Pypy-commit
mailing list