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