[pypy-commit] pypy jit-targets: a first failed atempt to support retrace, we need to redesign...
hakanardo
noreply at buildbot.pypy.org
Sun Nov 6 14:10:45 CET 2011
Author: Hakan Ardo <hakan at debian.org>
Branch: jit-targets
Changeset: r48820:a91e6cab9119
Date: 2011-11-06 12:46 +0100
http://bitbucket.org/pypy/pypy/changeset/a91e6cab9119/
Log: a first failed atempt to support retrace, we need to redesign...
diff --git a/pypy/jit/metainterp/compile.py b/pypy/jit/metainterp/compile.py
--- a/pypy/jit/metainterp/compile.py
+++ b/pypy/jit/metainterp/compile.py
@@ -94,7 +94,7 @@
def compile_procedure(metainterp, greenkey, start,
inputargs, jumpargs,
- start_resumedescr, full_preamble_needed=True):
+ start_resumedescr, full_preamble_needed=True, partial_trace=None):
"""Try to compile a new procedure by closing the current history back
to the first operation.
"""
@@ -104,22 +104,29 @@
metainterp_sd = metainterp.staticdata
jitdriver_sd = metainterp.jitdriver_sd
- loop = create_empty_loop(metainterp)
- loop.inputargs = inputargs[:]
-
- procedure_token = make_procedure_token(jitdriver_sd)
- part = create_empty_loop(metainterp)
- h_ops = history.operations
- part.start_resumedescr = start_resumedescr
- part.operations = [ResOperation(rop.LABEL, inputargs, None, descr=TargetToken(procedure_token))] + \
- [h_ops[i].clone() for i in range(start, len(h_ops))] + \
- [ResOperation(rop.LABEL, jumpargs, None, descr=TargetToken(procedure_token))]
- try:
- optimize_trace(metainterp_sd, part, jitdriver_sd.warmstate.enable_opts)
- except InvalidLoop:
- return None
+ if partial_trace:
+ part = partial_trace
+ procedure_token = metainterp.get_procedure_token(greenkey)
+ assert procedure_token
+ all_target_tokens = []
+ else:
+ procedure_token = make_procedure_token(jitdriver_sd)
+ part = create_empty_loop(metainterp)
+ part.inputargs = inputargs[:]
+ h_ops = history.operations
+ part.start_resumedescr = start_resumedescr
+ part.operations = [ResOperation(rop.LABEL, inputargs, None, descr=TargetToken(procedure_token))] + \
+ [h_ops[i].clone() for i in range(start, len(h_ops))] + \
+ [ResOperation(rop.LABEL, jumpargs, None, descr=TargetToken(procedure_token))]
+ try:
+ optimize_trace(metainterp_sd, part, jitdriver_sd.warmstate.enable_opts)
+ except InvalidLoop:
+ return None
+ all_target_tokens = [part.operations[0].getdescr()]
+
+ loop = create_empty_loop(metainterp)
+ loop.inputargs = part.inputargs
loop.operations = part.operations
- all_target_tokens = [part.operations[0].getdescr()]
while part.operations[-1].getopnum() == rop.LABEL:
inliner = Inliner(inputargs, jumpargs)
part.operations = [part.operations[-1]] + \
@@ -627,11 +634,11 @@
#
# Attempt to use optimize_bridge(). This may return None in case
# it does not work -- i.e. none of the existing old_loop_tokens match.
- new_loop = create_empty_loop(metainterp)
- new_loop.inputargs = inputargs = metainterp.history.inputargs[:]
+ new_trace = create_empty_loop(metainterp)
+ new_trace.inputargs = inputargs = metainterp.history.inputargs[:]
# clone ops, as optimize_bridge can mutate the ops
- new_loop.operations = [op.clone() for op in metainterp.history.operations]
+ new_trace.operations = [op.clone() for op in metainterp.history.operations]
metainterp_sd = metainterp.staticdata
state = metainterp.jitdriver_sd.warmstate
if isinstance(resumekey, ResumeAtPositionDescr):
@@ -639,20 +646,25 @@
else:
inline_short_preamble = True
try:
- optimize_trace(metainterp_sd, new_loop, state.enable_opts)
+ optimize_trace(metainterp_sd, new_trace, state.enable_opts)
except InvalidLoop:
debug_print("compile_new_bridge: got an InvalidLoop")
# XXX I am fairly convinced that optimize_bridge cannot actually raise
# InvalidLoop
debug_print('InvalidLoop in compile_new_bridge')
return None
- # We managed to create a bridge. Dispatch to resumekey to
- # know exactly what we must do (ResumeGuardDescr/ResumeFromInterpDescr)
- target_token = new_loop.operations[-1].getdescr()
- resumekey.compile_and_attach(metainterp, new_loop)
- record_loop_or_bridge(metainterp_sd, new_loop)
- return target_token
+ if new_trace.operations[-1].getopnum() == rop.JUMP:
+ # We managed to create a bridge. Dispatch to resumekey to
+ # know exactly what we must do (ResumeGuardDescr/ResumeFromInterpDescr)
+ target_token = new_trace.operations[-1].getdescr()
+ resumekey.compile_and_attach(metainterp, new_trace)
+ record_loop_or_bridge(metainterp_sd, new_trace)
+ return target_token
+ else:
+ metainterp.retrace_needed(new_trace)
+ return None
+
# ____________________________________________________________
diff --git a/pypy/jit/metainterp/optimizeopt/unroll.py b/pypy/jit/metainterp/optimizeopt/unroll.py
--- a/pypy/jit/metainterp/optimizeopt/unroll.py
+++ b/pypy/jit/metainterp/optimizeopt/unroll.py
@@ -88,12 +88,18 @@
if not stop_label:
self.optimizer.flush()
loop.operations = self.optimizer.get_newoperations()
+ return
elif not start_label:
- #jumpop = ResOperation(rop.JUMP, stop_label.getarglist(), None, descr=stop_label.getdescr())
- self.optimizer.send_extra_operation(stop_label)
- self.optimizer.flush()
- loop.operations = self.optimizer.get_newoperations()
- elif not self.did_peel_one: # Enforce the previous behaviour of always peeling exactly one iteration (for now)
+ try:
+ self.optimizer.send_extra_operation(stop_label)
+ except RetraceLoop:
+ pass
+ else:
+ self.optimizer.flush()
+ loop.operations = self.optimizer.get_newoperations()
+ return
+
+ if not self.did_peel_one: # Enforce the previous behaviour of always peeling exactly one iteration (for now)
self.optimizer.flush()
KillHugeIntBounds(self.optimizer).apply()
@@ -152,6 +158,7 @@
inputarg_setup_ops, self.optimizer)
def import_state(self, targetop):
+ self.did_peel_one = False
if not targetop:
# FIXME: Set up some sort of empty state with no virtuals?
return
@@ -161,7 +168,6 @@
assert isinstance(target_token, TargetToken)
exported_state = target_token.exported_state
if not exported_state:
- self.did_peel_one = False
# FIXME: Set up some sort of empty state with no virtuals
return
self.did_peel_one = True
@@ -504,29 +510,31 @@
return
debug_stop('jit-log-virtualstate')
- if False: # FIXME: retrace
- retraced_count = loop_token.retraced_count
- limit = self.optimizer.metainterp_sd.warmrunnerdesc.memory_manager.retrace_limit
- if not self.retraced and retraced_count<limit:
- loop_token.retraced_count += 1
- if not loop_token.failed_states:
- debug_print("Retracing (%d of %d)" % (retraced_count,
- limit))
- raise RetraceLoop
- for failed in loop_token.failed_states:
- if failed.generalization_of(virtual_state):
- # Retracing once more will most likely fail again
- break
- else:
- debug_print("Retracing (%d of %d)" % (retraced_count,
- limit))
+ retraced_count = procedure_token.retraced_count
+ limit = self.optimizer.metainterp_sd.warmrunnerdesc.memory_manager.retrace_limit
+ if not self.retraced and retraced_count<limit:
+ procedure_token.retraced_count += 1
+ raise RetraceLoop
- raise RetraceLoop
- else:
- if not loop_token.failed_states:
- loop_token.failed_states=[virtual_state]
- else:
- loop_token.failed_states.append(virtual_state)
+ ## # We should not be failing much anymore...
+ ## if not procedure_token.failed_states:
+ ## debug_print("Retracing (%d of %d)" % (retraced_count,
+ ## limit))
+ ## raise RetraceLoop
+ ## for failed in loop_token.failed_states:
+ ## if failed.generalization_of(virtual_state):
+ ## # Retracing once more will most likely fail again
+ ## break
+ ## else:
+ ## debug_print("Retracing (%d of %d)" % (retraced_count,
+ ## limit))
+
+ ## raise RetraceLoop
+ ## else:
+ ## if not loop_token.failed_states:
+ ## loop_token.failed_states=[virtual_state]
+ ## else:
+ ## loop_token.failed_states.append(virtual_state)
self.emit_operation(op)
class ValueImporter(object):
diff --git a/pypy/jit/metainterp/pyjitpl.py b/pypy/jit/metainterp/pyjitpl.py
--- a/pypy/jit/metainterp/pyjitpl.py
+++ b/pypy/jit/metainterp/pyjitpl.py
@@ -22,7 +22,6 @@
from pypy.jit.codewriter.jitcode import JitCode, SwitchDictDescr
from pypy.jit.codewriter import heaptracker
from pypy.jit.metainterp.optimizeopt.util import args_dict_box
-from pypy.jit.metainterp.optimize import RetraceLoop
# ____________________________________________________________
@@ -1557,10 +1556,17 @@
self.portal_trace_positions = []
self.free_frames_list = []
self.last_exc_value_box = None
- self.retracing_loop_from = None
+ self.partial_trace = None
+ self.retracing_from = -1
self.call_pure_results = args_dict_box()
self.heapcache = HeapCache()
+ def retrace_needed(self, trace):
+ self.partial_trace = trace
+ self.retracing_from = len(self.history)
+ self.heapcache.reset()
+
+
def perform_call(self, jitcode, boxes, greenkey=None):
# causes the metainterp to enter the given subfunction
f = self.newframe(jitcode, greenkey)
@@ -1928,14 +1934,8 @@
# that failed;
# - if self.resumekey is a ResumeFromInterpDescr, it starts directly
# from the interpreter.
- if not self.retracing_loop_from:
- try:
- self.compile_trace(live_arg_boxes)
- except RetraceLoop:
- start = len(self.history.operations)
- self.current_merge_points.append((live_arg_boxes, start))
- self.retracing_loop_from = RetraceState(self, live_arg_boxes)
- return
+ if not self.partial_trace:
+ self.compile_trace(live_arg_boxes)
# raises in case it works -- which is the common case, hopefully,
# at least for bridges starting from a guard.
@@ -1957,14 +1957,9 @@
else:
# Found! Compile it as a loop.
# raises in case it works -- which is the common case
- if self.retracing_loop_from and \
- self.retracing_loop_from.merge_point == j:
- bridge_arg_boxes = self.retracing_loop_from.live_arg_boxes
- self.compile_bridge_and_loop(original_boxes, \
- live_arg_boxes, start,
- bridge_arg_boxes, resumedescr)
- else:
- self.compile_procedure(original_boxes, live_arg_boxes, start, resumedescr)
+ if self.partial_trace:
+ assert start == self.retracing_from # FIXME: Giveup
+ self.compile_procedure(original_boxes, live_arg_boxes, start, resumedescr)
# creation of the loop was cancelled!
self.staticdata.log('cancelled, tracing more...')
#self.staticdata.log('cancelled, stopping tracing')
@@ -2027,11 +2022,12 @@
def compile_procedure(self, original_boxes, live_arg_boxes, start, start_resumedescr):
num_green_args = self.jitdriver_sd.num_green_args
greenkey = original_boxes[:num_green_args]
- assert self.get_procedure_token(greenkey) == None # FIXME: recursion?
+ if not self.partial_trace:
+ assert self.get_procedure_token(greenkey) == None # FIXME: recursion?
procedure_token = compile.compile_procedure(self, greenkey, start,
original_boxes[num_green_args:],
live_arg_boxes[num_green_args:],
- start_resumedescr)
+ start_resumedescr, partial_trace=self.partial_trace)
if procedure_token is not None: # raise if it *worked* correctly
self.jitdriver_sd.warmstate.attach_procedure_to_interp(greenkey, procedure_token)
self.history.inputargs = None
More information about the pypy-commit
mailing list