Author: Hakan Ardo <ha...@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 _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit