[pypy-commit] pypy jit-targets: support for bridges in progress
hakanardo
noreply at buildbot.pypy.org
Sun Nov 6 10:46:22 CET 2011
Author: Hakan Ardo <hakan at debian.org>
Branch: jit-targets
Changeset: r48811:5e84c483e93d
Date: 2011-11-06 09:15 +0100
http://bitbucket.org/pypy/pypy/changeset/5e84c483e93d/
Log: support for bridges in progress
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
@@ -119,12 +119,14 @@
except InvalidLoop:
return None
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]] + \
[inliner.inline_op(h_ops[i]) for i in range(start, len(h_ops))] + \
[ResOperation(rop.LABEL, [inliner.inline_arg(a) for a in jumpargs],
None, descr=TargetToken(procedure_token))]
+ all_target_tokens.append(part.operations[0].getdescr())
inputargs = jumpargs
jumpargs = part.operations[-1].getarglist()
@@ -139,7 +141,7 @@
assert isinstance(box, Box)
loop.token = procedure_token
-
+ procedure_token.target_tokens = all_target_tokens
send_loop_to_backend(greenkey, jitdriver_sd, metainterp_sd, loop, "loop")
record_loop_or_bridge(metainterp_sd, loop)
return procedure_token
@@ -206,10 +208,6 @@
metainterp_sd.log("compiled new " + type)
#
metainterp_sd.logger_ops.log_loop(loop.inputargs, loop.operations, n, type, ops_offset)
- short = loop.token.short_preamble
- if short:
- metainterp_sd.logger_ops.log_short_preamble(short[-1].inputargs,
- short[-1].operations)
#
if metainterp_sd.warmrunnerdesc is not None: # for tests
metainterp_sd.warmrunnerdesc.memory_manager.keep_loop_alive(loop.token)
@@ -221,7 +219,8 @@
original_loop_token, operations, n)
if not we_are_translated():
show_loop(metainterp_sd)
- TreeLoop.check_consistency_of(inputargs, operations)
+ seen = dict.fromkeys(inputargs)
+ TreeLoop.check_consistency_of_branch(operations, seen)
metainterp_sd.profiler.start_backend()
operations = get_deep_immutable_oplist(operations)
debug_start("jit-backend")
@@ -596,7 +595,6 @@
class ResumeFromInterpDescr(ResumeDescr):
def __init__(self, original_greenkey):
self.original_greenkey = original_greenkey
- self.procedure_token = ProcedureToken()
def compile_and_attach(self, metainterp, new_loop):
# We managed to create a bridge going from the interpreter
@@ -606,13 +604,13 @@
metainterp_sd = metainterp.staticdata
jitdriver_sd = metainterp.jitdriver_sd
redargs = new_loop.inputargs
- self.procedure_token.outermost_jitdriver_sd = jitdriver_sd
- new_loop.token = self.procedure_token
+ procedure_token = make_procedure_token(jitdriver_sd)
+ new_loop.token = procedure_token
send_loop_to_backend(self.original_greenkey, metainterp.jitdriver_sd,
metainterp_sd, new_loop, "entry bridge")
# send the new_loop to warmspot.py, to be called directly the next time
jitdriver_sd.warmstate.attach_procedure_to_interp(
- self.original_greenkey, self.procedure_token)
+ self.original_greenkey, procedure_token)
def reset_counter_from_failure(self):
pass
@@ -626,15 +624,17 @@
# The history contains new operations to attach as the code for the
# failure of 'resumekey.guard_op'.
- #
+ #
# 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[:]
# clone ops, as optimize_bridge can mutate the ops
- procedure_token = resumekey.procedure_token
- new_loop.operations = [ResOperation(rop.LABEL, inputargs, None, descr=TargetToken(procedure_token))] + \
- [op.clone() for op in metainterp.history.operations]
+
+ # A LABEL with descr=None will be killed by optimizer. Its only use
+ # is to pass along the inputargs to the optimizer
+ #[ResOperation(rop.LABEL, inputargs, None, descr=None)] + \
+ new_loop.operations = [op.clone() for op in metainterp.history.operations]
metainterp_sd = metainterp.staticdata
state = metainterp.jitdriver_sd.warmstate
if isinstance(resumekey, ResumeAtPositionDescr):
diff --git a/pypy/jit/metainterp/history.py b/pypy/jit/metainterp/history.py
--- a/pypy/jit/metainterp/history.py
+++ b/pypy/jit/metainterp/history.py
@@ -734,7 +734,7 @@
was compiled; but the LoopDescr remains alive and points to the
generated assembler.
"""
- short_preamble = None
+ target_tokens = None
failed_states = None
retraced_count = 0
terminating = False # see TerminatingLoopToken in compile.py
diff --git a/pypy/jit/metainterp/optimizeopt/__init__.py b/pypy/jit/metainterp/optimizeopt/__init__.py
--- a/pypy/jit/metainterp/optimizeopt/__init__.py
+++ b/pypy/jit/metainterp/optimizeopt/__init__.py
@@ -85,7 +85,7 @@
"""Optimize loop.operations to remove internal overheadish operations.
"""
- optimizations, unroll = build_opt_chain(metainterp_sd, enable_opts, False, False)
+ optimizations, unroll = build_opt_chain(metainterp_sd, enable_opts, True, False)
if unroll:
optimize_unroll(metainterp_sd, loop, optimizations)
else:
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
@@ -65,46 +65,56 @@
def propagate_all_forward(self):
loop = self.optimizer.loop
- start_targetop = loop.operations[0]
- assert start_targetop.getopnum() == rop.LABEL
- loop.operations = loop.operations[1:]
self.optimizer.clear_newoperations()
- self.optimizer.send_extra_operation(start_targetop)
+
+ import pdb; pdb.set_trace()
+
+ start_label = loop.operations[0]
+ if start_label.getopnum() == rop.LABEL:
+ loop.operations = loop.operations[1:]
+ # We need to emit the label op before import_state() as emitting it
+ # will clear heap caches
+ self.optimizer.send_extra_operation(start_label)
+ else:
+ start_label = None
- self.import_state(start_targetop)
-
- lastop = loop.operations[-1]
- if lastop.getopnum() == rop.LABEL:
+ stop_label = loop.operations[-1]
+ if stop_label.getopnum() == rop.LABEL:
loop.operations = loop.operations[:-1]
else:
- lastop = None
-
+ stop_label = None
+
+ self.import_state(start_label)
self.optimizer.propagate_all_forward(clear=False)
- if not lastop:
+ if not stop_label:
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)
+ 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)
self.optimizer.flush()
KillHugeIntBounds(self.optimizer).apply()
loop.operations = self.optimizer.get_newoperations()
- self.export_state(lastop)
- loop.operations.append(lastop)
+ self.export_state(stop_label)
+ loop.operations.append(stop_label)
else:
- assert lastop.getdescr().procedure_token is start_targetop.getdescr().procedure_token
- jumpop = ResOperation(rop.JUMP, lastop.getarglist(), None, descr=start_targetop.getdescr())
+ assert stop_label.getdescr().procedure_token is start_label.getdescr().procedure_token
+ jumpop = ResOperation(rop.JUMP, stop_label.getarglist(), None, descr=start_label.getdescr())
self.close_loop(jumpop)
- self.finilize_short_preamble(lastop)
- start_targetop.getdescr().short_preamble = self.short
+ self.finilize_short_preamble(start_label)
+ start_label.getdescr().short_preamble = self.short
def export_state(self, targetop):
original_jump_args = targetop.getarglist()
jump_args = [self.getvalue(a).get_key_box() for a in original_jump_args]
+ # FIXME: I dont thnik we need this anymore
start_resumedescr = self.optimizer.loop.start_resumedescr.clone_if_mutable()
assert isinstance(start_resumedescr, ResumeGuardDescr)
start_resumedescr.rd_snapshot = self.fix_snapshot(jump_args, start_resumedescr.rd_snapshot)
@@ -139,12 +149,17 @@
targetop.initarglist(inputargs)
target_token.virtual_state = virtual_state
target_token.short_preamble = [ResOperation(rop.LABEL, short_inputargs, None)]
+ target_token.start_resumedescr = start_resumedescr
target_token.exported_state = ExportedState(constant_inputargs, short_boxes,
- inputarg_setup_ops, self.optimizer,
- start_resumedescr)
+ inputarg_setup_ops, self.optimizer)
def import_state(self, targetop):
+ if not targetop:
+ # FIXME: Set up some sort of empty state with no virtuals?
+ return
target_token = targetop.getdescr()
+ if not target_token:
+ return
assert isinstance(target_token, TargetToken)
exported_state = target_token.exported_state
if not exported_state:
@@ -160,7 +175,6 @@
self.short_seen[box] = True
self.imported_state = exported_state
self.inputargs = targetop.getarglist()
- self.start_resumedescr = exported_state.start_resumedescr
self.initial_virtual_state = target_token.virtual_state
seen = {}
@@ -275,9 +289,11 @@
raise InvalidLoop
debug_stop('jit-log-virtualstate')
- def finilize_short_preamble(self, lastop):
+ def finilize_short_preamble(self, start_label):
short = self.short
assert short[-1].getopnum() == rop.JUMP
+ target_token = start_label.getdescr()
+ assert isinstance(target_token, TargetToken)
# Turn guards into conditional jumps to the preamble
for i in range(len(short)):
@@ -285,7 +301,7 @@
if op.is_guard():
op = op.clone()
op.setfailargs(None)
- descr = self.start_resumedescr.clone_if_mutable()
+ descr = target_token.start_resumedescr.clone_if_mutable()
op.setdescr(descr)
short[i] = op
@@ -306,10 +322,8 @@
for i in range(len(short)):
short[i] = inliner.inline_op(short[i])
- self.start_resumedescr = self.start_resumedescr.clone_if_mutable()
- inliner.inline_descr_inplace(self.start_resumedescr)
- #short_loop.start_resumedescr = descr
- # FIXME: move this to targettoken
+ target_token.start_resumedescr = target_token.start_resumedescr.clone_if_mutable()
+ inliner.inline_descr_inplace(target_token.start_resumedescr)
# Forget the values to allow them to be freed
for box in short[0].getarglist():
@@ -422,66 +436,76 @@
def propagate_forward(self, op):
if op.getopnum() == rop.JUMP:
- loop_token = op.getdescr()
- if not isinstance(loop_token, TargetToken):
+ self.emit_operation(op)
+ return
+ elif op.getopnum() == rop.LABEL:
+ target_token = op.getdescr()
+ assert isinstance(target_token, TargetToken)
+ procedure_token = target_token.procedure_token
+ if not procedure_token.target_tokens:
self.emit_operation(op)
return
- short = loop_token.short_preamble
- if short:
- args = op.getarglist()
- modifier = VirtualStateAdder(self.optimizer)
- virtual_state = modifier.get_virtual_state(args)
- debug_start('jit-log-virtualstate')
- virtual_state.debug_print("Looking for ")
- for sh in short:
- ok = False
- extra_guards = []
+ args = op.getarglist()
+ modifier = VirtualStateAdder(self.optimizer)
+ virtual_state = modifier.get_virtual_state(args)
+ debug_start('jit-log-virtualstate')
+ virtual_state.debug_print("Looking for ")
- bad = {}
- debugmsg = 'Did not match '
- if sh.virtual_state.generalization_of(virtual_state, bad):
- ok = True
- debugmsg = 'Matched '
- else:
- try:
- cpu = self.optimizer.cpu
- sh.virtual_state.generate_guards(virtual_state,
+ for target in procedure_token.target_tokens:
+ if not target.virtual_state:
+ continue
+ ok = False
+ extra_guards = []
+
+ bad = {}
+ debugmsg = 'Did not match '
+ if target.virtual_state.generalization_of(virtual_state, bad):
+ ok = True
+ debugmsg = 'Matched '
+ else:
+ try:
+ cpu = self.optimizer.cpu
+ target.virtual_state.generate_guards(virtual_state,
args, cpu,
extra_guards)
- ok = True
- debugmsg = 'Guarded to match '
- except InvalidLoop:
- pass
- sh.virtual_state.debug_print(debugmsg, bad)
-
- if ok:
- debug_stop('jit-log-virtualstate')
+ ok = True
+ debugmsg = 'Guarded to match '
+ except InvalidLoop:
+ pass
+ target.virtual_state.debug_print(debugmsg, bad)
- values = [self.getvalue(arg)
- for arg in op.getarglist()]
- args = sh.virtual_state.make_inputargs(values, self.optimizer,
+ if ok:
+ debug_stop('jit-log-virtualstate')
+
+ values = [self.getvalue(arg)
+ for arg in op.getarglist()]
+ args = target.virtual_state.make_inputargs(values, self.optimizer,
keyboxes=True)
- inliner = Inliner(sh.inputargs, args)
-
- for guard in extra_guards:
- if guard.is_guard():
- descr = sh.start_resumedescr.clone_if_mutable()
- inliner.inline_descr_inplace(descr)
- guard.setdescr(descr)
- self.emit_operation(guard)
-
- try:
- for shop in sh.operations:
- newop = inliner.inline_op(shop)
- self.emit_operation(newop)
- except InvalidLoop:
- debug_print("Inlining failed unexpectedly",
- "jumping to preamble instead")
- self.emit_operation(op)
- return
- debug_stop('jit-log-virtualstate')
+ short_inputargs = target.short_preamble[0].getarglist()
+ inliner = Inliner(short_inputargs, args)
+
+ for guard in extra_guards:
+ if guard.is_guard():
+ descr = target.start_resumedescr.clone_if_mutable()
+ inliner.inline_descr_inplace(descr)
+ guard.setdescr(descr)
+ self.emit_operation(guard)
+
+ try:
+ for shop in target.short_preamble[1:]:
+ newop = inliner.inline_op(shop)
+ self.emit_operation(newop)
+ except InvalidLoop:
+ debug_print("Inlining failed unexpectedly",
+ "jumping to preamble instead")
+ assert False, "FIXME: Construct jump op"
+ self.emit_operation(op)
+ 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:
@@ -518,11 +542,9 @@
class ExportedState(object):
def __init__(self, constant_inputargs,
- short_boxes, inputarg_setup_ops, optimizer,
- start_resumedescr):
+ short_boxes, inputarg_setup_ops, optimizer):
self.constant_inputargs = constant_inputargs
self.short_boxes = short_boxes
self.inputarg_setup_ops = inputarg_setup_ops
self.optimizer = optimizer
- self.start_resumedescr = start_resumedescr
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
@@ -8,7 +8,7 @@
from pypy.jit.metainterp import history, compile, resume
from pypy.jit.metainterp.history import Const, ConstInt, ConstPtr, ConstFloat
-from pypy.jit.metainterp.history import Box
+from pypy.jit.metainterp.history import Box, TargetToken
from pypy.jit.metainterp.resoperation import rop
from pypy.jit.metainterp import executor
from pypy.jit.metainterp.logger import Logger
@@ -1928,10 +1928,9 @@
# that failed;
# - if self.resumekey is a ResumeFromInterpDescr, it starts directly
# from the interpreter.
- if False: # FIXME
- if not self.retracing_loop_from:
+ if not self.retracing_loop_from:
try:
- self.compile_bridge(live_arg_boxes)
+ self.compile_trace(live_arg_boxes)
except RetraceLoop:
start = len(self.history.operations)
self.current_merge_points.append((live_arg_boxes, start))
@@ -2042,22 +2041,20 @@
def compile_trace(self, live_arg_boxes):
num_green_args = self.jitdriver_sd.num_green_args
greenkey = live_arg_boxes[:num_green_args]
- old_loop_tokens = self.get_compiled_merge_points(greenkey)
- if len(old_loop_tokens) == 0:
+ target_procedure = self.get_procedure_token(greenkey)
+ if not target_procedure:
return
- #if self.resumekey.guard_opnum == rop.GUARD_CLASS:
- # return # Kepp tracing for another iteration
- self.history.record(rop.JUMP, live_arg_boxes[num_green_args:], None)
+
+ self.history.record(rop.LABEL, live_arg_boxes[num_green_args:], None,
+ descr=TargetToken(target_procedure))
try:
- target_loop_token = compile.compile_new_bridge(self,
- old_loop_tokens,
- self.resumekey)
+ target_token = compile.compile_new_bridge(self, self.resumekey)
finally:
self.history.operations.pop() # remove the JUMP
- if target_loop_token is not None: # raise if it *worked* correctly
+ if target_token is not None: # raise if it *worked* correctly
self.history.inputargs = None
self.history.operations = None
- raise GenerateMergePoint(live_arg_boxes, target_loop_token)
+ raise GenerateMergePoint(live_arg_boxes, target_token.procedure_token)
def compile_bridge_and_loop(self, original_boxes, live_arg_boxes, start,
bridge_arg_boxes, start_resumedescr):
@@ -2119,6 +2116,7 @@
else:
assert False
# FIXME: kill TerminatingLoopToken?
+ # FIXME: can we call compile_trace?
self.history.record(rop.FINISH, exits, None, descr=loop_tokens[0].finishdescr)
target_loop_token = compile.compile_new_bridge(self, self.resumekey)
if not target_loop_token:
diff --git a/pypy/jit/metainterp/warmstate.py b/pypy/jit/metainterp/warmstate.py
--- a/pypy/jit/metainterp/warmstate.py
+++ b/pypy/jit/metainterp/warmstate.py
@@ -328,7 +328,7 @@
# set counter to -2, to mean "tracing in effect"
cell.counter = -2
try:
- loop_token = metainterp.compile_and_run_once(jitdriver_sd,
+ procedure_token = metainterp.compile_and_run_once(jitdriver_sd,
*args)
finally:
if cell.counter == -2:
@@ -341,8 +341,8 @@
assert cell.counter == -1
if not confirm_enter_jit(*args):
return
- loop_token = cell.get_entry_loop_token()
- if loop_token is None: # it was a weakref that has been freed
+ procedure_token = cell.get_procedure_token()
+ if procedure_token is None: # it was a weakref that has been freed
cell.counter = 0
return
# machine code was already compiled for these greenargs
@@ -353,14 +353,14 @@
while True: # until interrupted by an exception
metainterp_sd.profiler.start_running()
#debug_start("jit-running")
- fail_descr = warmrunnerdesc.execute_token(loop_token)
+ fail_descr = warmrunnerdesc.execute_token(procedure_token)
#debug_stop("jit-running")
metainterp_sd.profiler.end_running()
- loop_token = None # for test_memmgr
+ procedure_token = None # for test_memmgr
if vinfo is not None:
vinfo.reset_vable_token(virtualizable)
- loop_token = fail_descr.handle_fail(metainterp_sd,
- jitdriver_sd)
+ procedure_token = fail_descr.handle_fail(metainterp_sd,
+ jitdriver_sd)
maybe_compile_and_run._dont_inline_ = True
self.maybe_compile_and_run = maybe_compile_and_run
More information about the pypy-commit
mailing list