def optimize_call_pure(self, op, start_index=0): # Step 1: check if all arguments are constant for i in range(start_index, op.numargs()): self.optimizer.force_box(op.getarg(i)) # XXX hack to ensure that virtuals that are # constant are presented that way result = self._can_optimize_call_pure(op, start_index=start_index) if result is not None: # this removes a CALL_PURE with all constant arguments. self.make_constant(op, result) self.last_emitted_operation = REMOVED return # Step 2: check if all arguments are the same as a previous # CALL_PURE. for pos in self.call_pure_positions: old_op = self.optimizer._newoperations[pos] if self.optimize_call_pure_old(op, old_op, start_index): return if self.extra_call_pure: for i, old_op in enumerate(self.extra_call_pure): if self.optimize_call_pure_old(op, old_op, start_index): if isinstance(old_op, PreambleOp): old_op = self.optimizer.force_op_from_preamble(old_op) self.extra_call_pure[i] = old_op return # replace CALL_PURE with just CALL (but keep COND_CALL_VALUE) if start_index == 0: opnum = OpHelpers.call_for_descr(op.getdescr()) newop = self.optimizer.replace_op_with(op, opnum) else: newop = op return self.emit_result(CallPureOptimizationResult(self, newop))
def optimize_CALL_PURE_I(self, op): # Step 1: check if all arguments are constant for arg in op.getarglist(): self.optimizer.force_box(arg) # XXX hack to ensure that virtuals that are # constant are presented that way result = self._can_optimize_call_pure(op) if result is not None: # this removes a CALL_PURE with all constant arguments. self.make_constant(op, result) self.last_emitted_operation = REMOVED return # Step 2: check if all arguments are the same as a previous # CALL_PURE. for pos in self.call_pure_positions: old_op = self.optimizer._newoperations[pos] if self.optimize_call_pure(op, old_op): return if self.extra_call_pure: for i, old_op in enumerate(self.extra_call_pure): if self.optimize_call_pure(op, old_op): if isinstance(old_op, PreambleOp): old_op = self.optimizer.force_op_from_preamble(old_op) self.extra_call_pure[i] = old_op return # replace CALL_PURE with just CALL opnum = OpHelpers.call_for_descr(op.getdescr()) newop = self.optimizer.replace_op_with(op, opnum) self.emit_operation(newop) self.call_pure_positions.append( len(self.optimizer._newoperations) - 1)
def optimize_call_pure(self, op, start_index=0): # Step 1: check if all arguments are constant for i in range(start_index, op.numargs()): self.optimizer.force_box(op.getarg(i)) # XXX hack to ensure that virtuals that are # constant are presented that way result = self._can_optimize_call_pure(op, start_index=start_index) if result is not None: # this removes a CALL_PURE with all constant arguments. self.make_constant(op, result) self.last_emitted_operation = REMOVED return # Step 2: check if all arguments are the same as a previous # CALL_PURE. for pos in self.call_pure_positions: old_op = self.optimizer._newoperations[pos] if self.optimize_call_pure_old(op, old_op, start_index): return if self.extra_call_pure: for i, old_op in enumerate(self.extra_call_pure): if self.optimize_call_pure_old(op, old_op, start_index): if isinstance(old_op, PreambleOp): old_op = self.optimizer.force_op_from_preamble(old_op) self.extra_call_pure[i] = old_op return # replace CALL_PURE with just CALL (but keep COND_CALL_VALUE) if start_index == 0: opnum = OpHelpers.call_for_descr(op.getdescr()) newop = self.optimizer.replace_op_with(op, opnum) else: newop = op return self.emit_result(CallPureOptimizationResult(self, newop))
def optimize_CALL_PURE_I(self, op): # Step 1: check if all arguments are constant for arg in op.getarglist(): self.optimizer.force_box(arg) # XXX hack to ensure that virtuals that are # constant are presented that way result = self._can_optimize_call_pure(op) if result is not None: # this removes a CALL_PURE with all constant arguments. self.make_constant(op, result) self.last_emitted_operation = REMOVED return # Step 2: check if all arguments are the same as a previous # CALL_PURE. for pos in self.call_pure_positions: old_op = self.optimizer._newoperations[pos] if self.optimize_call_pure(op, old_op): return if self.extra_call_pure: for i, old_op in enumerate(self.extra_call_pure): if self.optimize_call_pure(op, old_op): if isinstance(old_op, PreambleOp): old_op = self.optimizer.force_op_from_preamble(old_op) self.extra_call_pure[i] = old_op return # replace CALL_PURE with just CALL opnum = OpHelpers.call_for_descr(op.getdescr()) newop = self.optimizer.replace_op_with(op, opnum) self.emit_operation(newop) self.call_pure_positions.append(len(self.optimizer._newoperations) - 1)
def compile_tmp_callback(cpu, jitdriver_sd, greenboxes, redargtypes, memory_manager=None): """Make a LoopToken that corresponds to assembler code that just calls back the interpreter. Used temporarily: a fully compiled version of the code may end up replacing it. """ jitcell_token = make_jitcell_token(jitdriver_sd) # # record the target of a temporary callback to the interpreter jl.tmp_callback(jitcell_token) # nb_red_args = jitdriver_sd.num_red_args assert len(redargtypes) == nb_red_args inputargs = [] for kind in redargtypes: if kind == history.INT: box = InputArgInt() elif kind == history.REF: box = InputArgRef() elif kind == history.FLOAT: box = InputArgFloat() else: raise AssertionError inputargs.append(box) k = jitdriver_sd.portal_runner_adr funcbox = history.ConstInt(adr2int(k)) callargs = [funcbox] + greenboxes + inputargs # jd = jitdriver_sd opnum = OpHelpers.call_for_descr(jd.portal_calldescr) call_op = ResOperation(opnum, callargs, descr=jd.portal_calldescr) if call_op.type != 'v' is not None: finishargs = [call_op] else: finishargs = [] # faildescr = jitdriver_sd.propagate_exc_descr operations = [ call_op, ResOperation(rop.GUARD_NO_EXCEPTION, [], descr=faildescr), ResOperation(rop.FINISH, finishargs, descr=jd.portal_finishtoken) ] operations[1].setfailargs([]) operations = get_deep_immutable_oplist(operations) cpu.compile_loop(inputargs, operations, jitcell_token, log=False) if memory_manager is not None: # for tests memory_manager.keep_loop_alive(jitcell_token) return jitcell_token
def compile_tmp_callback(cpu, jitdriver_sd, greenboxes, redargtypes, memory_manager=None): """Make a LoopToken that corresponds to assembler code that just calls back the interpreter. Used temporarily: a fully compiled version of the code may end up replacing it. """ jitcell_token = make_jitcell_token(jitdriver_sd) # # record the target of a temporary callback to the interpreter jl.tmp_callback(jitcell_token) # nb_red_args = jitdriver_sd.num_red_args assert len(redargtypes) == nb_red_args inputargs = [] for kind in redargtypes: if kind == history.INT: box = InputArgInt() elif kind == history.REF: box = InputArgRef() elif kind == history.FLOAT: box = InputArgFloat() else: raise AssertionError inputargs.append(box) k = jitdriver_sd.portal_runner_adr funcbox = history.ConstInt(heaptracker.adr2int(k)) callargs = [funcbox] + greenboxes + inputargs # jd = jitdriver_sd opnum = OpHelpers.call_for_descr(jd.portal_calldescr) call_op = ResOperation(opnum, callargs, descr=jd.portal_calldescr) if call_op.type != 'v' is not None: finishargs = [call_op] else: finishargs = [] # faildescr = jitdriver_sd.propagate_exc_descr operations = [ call_op, ResOperation(rop.GUARD_NO_EXCEPTION, [], descr=faildescr), ResOperation(rop.FINISH, finishargs, descr=jd.portal_finishtoken) ] operations[1].setfailargs([]) operations = get_deep_immutable_oplist(operations) cpu.compile_loop(inputargs, operations, jitcell_token, log=False) if memory_manager is not None: # for tests memory_manager.keep_loop_alive(jitcell_token) return jitcell_token
def optimize_CALL_LOOPINVARIANT_I(self, op): arg = op.getarg(0) # 'arg' must be a Const, because residual_call in codewriter # expects a compile-time constant assert isinstance(arg, Const) key = make_hashable_int(arg.getint()) resvalue = self.loop_invariant_results.get(key, None) if resvalue is not None: resvalue = self.optimizer.force_op_from_preamble(resvalue) self.loop_invariant_results[key] = resvalue self.make_equal_to(op, resvalue) self.last_emitted_operation = REMOVED return # change the op to be a normal call, from the backend's point of view # there is no reason to have a separate operation for this newop = self.replace_op_with(op, OpHelpers.call_for_descr(op.getdescr())) return self.emit_result(CallLoopinvariantOptimizationResult(self, newop, op))
def optimize_CALL_LOOPINVARIANT_I(self, op): arg = op.getarg(0) # 'arg' must be a Const, because residual_call in codewriter # expects a compile-time constant assert isinstance(arg, Const) key = make_hashable_int(arg.getint()) resvalue = self.loop_invariant_results.get(key, None) if resvalue is not None: resvalue = self.optimizer.force_op_from_preamble(resvalue) self.loop_invariant_results[key] = resvalue self.make_equal_to(op, resvalue) self.last_emitted_operation = REMOVED return # change the op to be a normal call, from the backend's point of view # there is no reason to have a separate operation for this newop = self.replace_op_with(op, OpHelpers.call_for_descr(op.getdescr())) return self.emit_result(CallLoopinvariantOptimizationResult(self, newop, op))
def optimize_CALL_LOOPINVARIANT_I(self, op): opnum = OpHelpers.call_for_descr(op.getdescr()) op = op.copy_and_change(opnum) return self.emit(op)
def optimize_CALL_PURE_I(self, op): opnum = OpHelpers.call_for_descr(op.getdescr()) newop = self.optimizer.replace_op_with(op, opnum) return self.emit(newop)
def optimize_CALL_LOOPINVARIANT_I(self, op): opnum = OpHelpers.call_for_descr(op.getdescr()) op = op.copy_and_change(opnum) self.emit_operation(op)
def optimize_CALL_PURE_I(self, op): opnum = OpHelpers.call_for_descr(op.getdescr()) newop = self.optimizer.replace_op_with(op, opnum) self.emit_operation(newop)