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 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()