def exc_handling(guard_op): # operations need to start with correct GUARD_EXCEPTION if guard_op._exc_box is None: op = ResOperation(rop.GUARD_NO_EXCEPTION, [], None) else: op = ResOperation(rop.GUARD_EXCEPTION, [guard_op._exc_box], BoxPtr()) op.setdescr(BasicFailDescr()) op.setfailargs([]) return op
def produce_into(self, builder, r): fail_subset = builder.subset_of_intvars(r) original_intvars = builder.intvars[:] super(AbstractOvfOperation, self).produce_into(builder, r) if builder.fakemetainterp._got_exc: # overflow detected assert isinstance(builder.fakemetainterp._got_exc, OverflowError) op = ResOperation(rop.GUARD_OVERFLOW, [], None) # the overflowed result should not be used any more, but can # be used on the failure path: recompute fail_subset including # the result, and then remove it from builder.intvars. fail_subset = builder.subset_of_intvars(r) builder.intvars[:] = original_intvars else: op = ResOperation(rop.GUARD_NO_OVERFLOW, [], None) op.setdescr(BasicFailDescr()) op.setfailargs(fail_subset) builder.loop.operations.append(op)
def propagate_all_forward(self): loop = self.optimizer.loop self.optimizer.clear_newoperations() 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 jumpop = loop.operations[-1] if jumpop.getopnum() == rop.JUMP or jumpop.getopnum() == rop.LABEL: loop.operations = loop.operations[:-1] else: jumpop = None self.import_state(start_label) self.optimizer.propagate_all_forward(clear=False) if not jumpop: return cell_token = jumpop.getdescr() assert isinstance(cell_token, JitCellToken) stop_label = ResOperation(rop.LABEL, jumpop.getarglist(), None, TargetToken(cell_token)) if jumpop.getopnum() == rop.JUMP: if self.jump_to_already_compiled_trace(jumpop): # Found a compiled trace to jump to if self.short: # Construct our short preamble assert start_label self.close_bridge(start_label) return if start_label and self.jump_to_start_label(start_label, stop_label): # Initial label matches, jump to it jumpop = ResOperation(rop.JUMP, stop_label.getarglist(), None, descr=start_label.getdescr()) if self.short: # Construct our short preamble self.close_loop(start_label, jumpop) else: self.optimizer.send_extra_operation(jumpop) return if cell_token.target_tokens: limit = self.optimizer.metainterp_sd.warmrunnerdesc.memory_manager.retrace_limit if cell_token.retraced_count < limit: cell_token.retraced_count += 1 debug_print('Retracing (%d/%d)' % (cell_token.retraced_count, limit)) else: debug_print("Retrace count reached, jumping to preamble") assert cell_token.target_tokens[0].virtual_state is None jumpop.setdescr(cell_token.target_tokens[0]) self.optimizer.send_extra_operation(jumpop) return # Found nothing to jump to, emit a label instead if self.short: # Construct our short preamble assert start_label self.close_bridge(start_label) self.optimizer.flush() KillHugeIntBounds(self.optimizer).apply() loop.operations = self.optimizer.get_newoperations() self.export_state(stop_label) loop.operations.append(stop_label)
def propagate_all_forward(self): loop = self.optimizer.loop jumpop = loop.operations[-1] if jumpop.getopnum() == rop.JUMP: loop.operations = loop.operations[:-1] else: loopop = None self.optimizer.propagate_all_forward() if jumpop: assert jumpop.getdescr() is loop.token jump_args = jumpop.getarglist() jumpop.initarglist([]) self.optimizer.flush() KillHugeIntBounds(self.optimizer).apply() loop.preamble.operations = self.optimizer.newoperations jump_args = [self.getvalue(a).get_key_box() for a in jump_args] start_resumedescr = loop.preamble.start_resumedescr.clone_if_mutable() self.start_resumedescr = start_resumedescr assert isinstance(start_resumedescr, ResumeGuardDescr) start_resumedescr.rd_snapshot = self.fix_snapshot(loop, jump_args, start_resumedescr.rd_snapshot) modifier = VirtualStateAdder(self.optimizer) virtual_state = modifier.get_virtual_state(jump_args) values = [self.getvalue(arg) for arg in jump_args] inputargs = virtual_state.make_inputargs(values) short_inputargs = virtual_state.make_inputargs(values, keyboxes=True) self.constant_inputargs = {} for box in jump_args: const = self.get_constant_box(box) if const: self.constant_inputargs[box] = const sb = ShortBoxes(self.optimizer, inputargs + self.constant_inputargs.keys()) self.short_boxes = sb preamble_optimizer = self.optimizer loop.preamble.quasi_immutable_deps = self.optimizer.quasi_immutable_deps self.optimizer = self.optimizer.new() loop.quasi_immutable_deps = self.optimizer.quasi_immutable_deps logops = self.optimizer.loop.logops if logops: args = ", ".join([logops.repr_of_arg(arg) for arg in inputargs]) debug_print("inputargs: " + args) args = ", ".join([logops.repr_of_arg(arg) for arg in short_inputargs]) debug_print("short inputargs: " + args) self.short_boxes.debug_print(logops) # Force virtuals amoung the jump_args of the preamble to get the # operations needed to setup the proper state of those virtuals # in the peeled loop inputarg_setup_ops = [] preamble_optimizer.newoperations = [] seen = {} for box in inputargs: if box in seen: continue seen[box] = True value = preamble_optimizer.getvalue(box) inputarg_setup_ops.extend(value.make_guards(box)) for box in short_inputargs: if box in seen: continue seen[box] = True value = preamble_optimizer.getvalue(box) value.force_box() preamble_optimizer.flush() inputarg_setup_ops += preamble_optimizer.newoperations # Setup the state of the new optimizer by emiting the # short preamble operations and discarding the result self.optimizer.emitting_dissabled = True for op in inputarg_setup_ops: self.optimizer.send_extra_operation(op) seen = {} for op in self.short_boxes.operations(): self.ensure_short_op_emitted(op, self.optimizer, seen) if op and op.result: # The order of these guards is not important as # self.optimizer.emitting_dissabled is False value = preamble_optimizer.getvalue(op.result) for guard in value.make_guards(op.result): self.optimizer.send_extra_operation(guard) newresult = self.optimizer.getvalue(op.result).get_key_box() if newresult is not op.result: self.short_boxes.alias(newresult, op.result) self.optimizer.flush() self.optimizer.emitting_dissabled = False # XXX Hack to prevent the arraylen/strlen/unicodelen ops generated # by value.make_guards() from ending up in pure_operations for key, op in self.optimizer.pure_operations.items(): if not self.short_boxes.has_producer(op.result): del self.optimizer.pure_operations[key] initial_inputargs_len = len(inputargs) self.inliner = Inliner(loop.inputargs, jump_args) short = self.inline(inputargs, self.cloned_operations, loop.inputargs, short_inputargs, virtual_state) loop.inputargs = inputargs args = [preamble_optimizer.getvalue(self.short_boxes.original(a)).force_box() for a in inputargs] jmp = ResOperation(rop.JUMP, args, None) jmp.setdescr(loop.token) loop.preamble.operations.append(jmp) loop.operations = self.optimizer.newoperations maxguards = self.optimizer.metainterp_sd.warmrunnerdesc.memory_manager.max_retrace_guards if self.optimizer.emitted_guards > maxguards: loop.preamble.token.retraced_count = sys.maxint if short: assert short[-1].getopnum() == rop.JUMP short[-1].setdescr(loop.token) # Turn guards into conditional jumps to the preamble for i in range(len(short)): op = short[i] if op.is_guard(): op = op.clone() op.setfailargs(None) descr = self.start_resumedescr.clone_if_mutable() op.setdescr(descr) short[i] = op short_loop = TreeLoop("short preamble") short_loop.inputargs = short_inputargs short_loop.operations = short # Clone ops and boxes to get private versions and boxmap = {} newargs = [None] * len(short_loop.inputargs) for i in range(len(short_loop.inputargs)): a = short_loop.inputargs[i] if a in boxmap: newargs[i] = boxmap[a] else: newargs[i] = a.clonebox() boxmap[a] = newargs[i] inliner = Inliner(short_loop.inputargs, newargs) for box, const in self.constant_inputargs.items(): inliner.argmap[box] = const short_loop.inputargs = newargs ops = [inliner.inline_op(op) for op in short_loop.operations] short_loop.operations = ops descr = self.start_resumedescr.clone_if_mutable() inliner.inline_descr_inplace(descr) short_loop.start_resumedescr = descr assert isinstance(loop.preamble.token, LoopToken) if loop.preamble.token.short_preamble: loop.preamble.token.short_preamble.append(short_loop) else: loop.preamble.token.short_preamble = [short_loop] short_loop.virtual_state = virtual_state # Forget the values to allow them to be freed for box in short_loop.inputargs: box.forget_value() for op in short_loop.operations: if op.result: op.result.forget_value()
def create_short_preamble(self, preamble, loop): #return None # Dissable preamble_ops = preamble.operations loop_ops = loop.operations boxmap = BoxMap() state = ExeState(self.optimizer) short_preamble = [] loop_i = preamble_i = 0 while preamble_i < len(preamble_ops): op = preamble_ops[preamble_i] try: newop = self.inliner.inline_op(op, ignore_result=True, ignore_failargs=True) except KeyError: debug_print("create_short_preamble failed due to", "new boxes created during optimization.", "op:", op.getopnum(), "at preamble position: ", preamble_i, "loop position: ", loop_i) return None if self.sameop(newop, loop_ops[loop_i]) \ and loop_i < len(loop_ops): try: boxmap.link_ops(op, loop_ops[loop_i]) except ImpossibleLink: debug_print("create_short_preamble failed due to", "impossible link of " "op:", op.getopnum(), "at preamble position: ", preamble_i, "loop position: ", loop_i) return None loop_i += 1 else: if not state.safe_to_move(op): debug_print("create_short_preamble failed due to", "unsafe op:", op.getopnum(), "at preamble position: ", preamble_i, "loop position: ", loop_i) return None short_preamble.append(op) state.update(op) preamble_i += 1 if loop_i < len(loop_ops): debug_print("create_short_preamble failed due to", "loop contaning ops not in preamble" "at position", loop_i) return None jumpargs = [] for i in range(len(loop.inputargs)): try: jumpargs.append(boxmap.get_preamblebox(loop.inputargs[i])) except KeyError: debug_print("create_short_preamble failed due to", "input arguments not located") return None jmp = ResOperation(rop.JUMP, jumpargs[:], None) jmp.setdescr(loop.token) short_preamble.append(jmp) # Check that boxes used as arguemts are produced. seen = {} for box in preamble.inputargs: seen[box] = True for op in short_preamble: for box in op.getarglist(): if isinstance(box, Const): continue if box not in seen: debug_print("create_short_preamble failed due to", "op arguments not produced") return None if op.result: seen[op.result] = True return short_preamble
def propagate_all_forward(self): loop = self.optimizer.loop jumpop = loop.operations[-1] if jumpop.getopnum() == rop.JUMP: loop.operations = loop.operations[:-1] else: loopop = None self.optimizer.propagate_all_forward() if jumpop: assert jumpop.getdescr() is loop.token jump_args = jumpop.getarglist() jumpop.initarglist([]) #virtual_state = [self.getvalue(a).is_virtual() for a in jump_args] modifier = VirtualStateAdder(self.optimizer) virtual_state = modifier.get_virtual_state(jump_args) loop.preamble.operations = self.optimizer.newoperations loop.preamble.quasi_immutable_deps = ( self.optimizer.quasi_immutable_deps) self.optimizer = self.optimizer.reconstruct_for_next_iteration() inputargs = self.inline(self.cloned_operations, loop.inputargs, jump_args) loop.inputargs = inputargs jmp = ResOperation(rop.JUMP, loop.inputargs[:], None) jmp.setdescr(loop.token) loop.preamble.operations.append(jmp) loop.operations = self.optimizer.newoperations loop.quasi_immutable_deps = self.optimizer.quasi_immutable_deps start_resumedescr = loop.preamble.start_resumedescr.clone_if_mutable() assert isinstance(start_resumedescr, ResumeGuardDescr) snapshot = start_resumedescr.rd_snapshot while snapshot is not None: snapshot_args = snapshot.boxes new_snapshot_args = [] for a in snapshot_args: if not isinstance(a, Const): a = loop.preamble.inputargs[jump_args.index(a)] new_snapshot_args.append(a) snapshot.boxes = new_snapshot_args snapshot = snapshot.prev short = self.create_short_preamble(loop.preamble, loop) if short: if False: # FIXME: This should save some memory but requires # a lot of tests to be fixed... loop.preamble.operations = short[:] # Turn guards into conditional jumps to the preamble for i in range(len(short)): op = short[i] if op.is_guard(): op = op.clone() op.setfailargs(None) op.setdescr(start_resumedescr.clone_if_mutable()) short[i] = op short_loop = TreeLoop('short preamble') short_loop.inputargs = loop.preamble.inputargs[:] short_loop.operations = short # Clone ops and boxes to get private versions and newargs = [a.clonebox() for a in short_loop.inputargs] inliner = Inliner(short_loop.inputargs, newargs) short_loop.inputargs = newargs ops = [inliner.inline_op(op) for op in short_loop.operations] short_loop.operations = ops descr = start_resumedescr.clone_if_mutable() inliner.inline_descr_inplace(descr) short_loop.start_resumedescr = descr assert isinstance(loop.preamble.token, LoopToken) if loop.preamble.token.short_preamble: loop.preamble.token.short_preamble.append(short_loop) else: loop.preamble.token.short_preamble = [short_loop] short_loop.virtual_state = virtual_state # Forget the values to allow them to be freed for box in short_loop.inputargs: box.forget_value() for op in short_loop.operations: if op.result: op.result.forget_value()