コード例 #1
0
size_t RemoveRedundantCheckCastsPass::remove_redundant_check_casts(
    DexMethod* method) {
  if (!method || !method->get_code()) {
    return 0;
  }

  auto* code = method->get_code();
  code->build_cfg(/* editable */ false);
  auto& cfg = code->cfg();
  cfg.calculate_exit_block();

  impl::CheckCastAnalysis fixpoint(&cfg, method);
  fixpoint.run(impl::Environment());

  auto redundant_check_casts = fixpoint.collect_redundant_checks_replacement();
  size_t num_redundant_check_casts = redundant_check_casts.size();

  for (const auto& pair : redundant_check_casts) {
    IRInstruction* to_replace = pair.first;
    boost::optional<IRInstruction*> replacement_opt = pair.second;
    if (replacement_opt) {
      code->replace_opcode(to_replace, *replacement_opt);
    } else {
      code->remove_opcode(to_replace);
    }
  }

  return num_redundant_check_casts;
}
コード例 #2
0
SwitchMethodPartitioning::SwitchMethodPartitioning(IRCode* code,
                                                   bool verify_default_case)
    : m_code(code) {
  m_code->build_cfg(/* editable */ true);
  auto& cfg = m_code->cfg();
  // Note that a single-case switch can be compiled as either a switch opcode or
  // a series of if-* opcodes. We can use constant propagation to handle these
  // cases uniformly: to determine the case key, we use the inferred value of
  // the operand to the branching opcode in the successor blocks.
  cp::intraprocedural::FixpointIterator fixpoint(
      cfg, cp::ConstantPrimitiveAnalyzer());
  fixpoint.run(ConstantEnvironment());

  auto determining_reg =
      compute_prologue_blocks(&cfg, fixpoint, verify_default_case);

  // Find all the outgoing edges from the prologue blocks
  std::vector<cfg::Edge*> cases;
  for (const cfg::Block* prologue : m_prologue_blocks) {
    for (cfg::Edge* e : prologue->succs()) {
      if (std::find(m_prologue_blocks.begin(), m_prologue_blocks.end(),
                    e->target()) == m_prologue_blocks.end()) {
        cases.push_back(e);
      }
    }
  }

  for (auto edge : cases) {
    auto case_block = edge->target();
    auto env = fixpoint.get_entry_state_at(case_block);
    auto case_key = env.get<SignedConstantDomain>(*determining_reg);
    if (case_key.is_top() && verify_default_case) {
      auto last_insn_it = case_block->get_last_insn();
      always_assert_log(last_insn_it != case_block->end() &&
                            last_insn_it->insn->opcode() == OPCODE_THROW,
                        "Could not determine key for block that does not look "
                        "like it throws an IllegalArgumentException: %d in %s",
                        case_block->id(), SHOW(cfg));
    } else if (!case_key.is_top()) {
      const auto& c = case_key.get_constant();
      if (c != boost::none) {
        m_key_to_block[*c] = case_block;
      } else {
        // handle multiple case keys that map to a single block
        always_assert(edge->type() == cfg::EDGE_BRANCH);
        const auto& edge_case_key = edge->case_key();
        always_assert(edge_case_key != boost::none);
        m_key_to_block[*edge_case_key] = case_block;
      }
    }
  }
}
コード例 #3
0
ファイル: ISPCATBuilder.cpp プロジェクト: alexjordan/otawa
  void ISPCATBuilder::processCFG(WorkSpace *ws, CFG *cfg) {
    ISPProblem problem(_isp_size);
    DefaultListener<ISPProblem> listener(ws, problem,true);
    DefaultFixPoint<DefaultListener<ISPProblem> > fixpoint(listener);
    HalfAbsInt<DefaultFixPoint<DefaultListener<ISPProblem> > > halfabsint(fixpoint, *ws);
    halfabsint.solve();
	
    for(CFG::BBIterator bb(cfg); bb; bb++) {
      if (bb->isEntry() || bb->isExit())
	continue;
      FunctionBlock *fb = FUNCTION_BLOCK(bb);
      if (fb) {
	ISPProblem::Domain dom(*listener.results[cfg->number()][bb->number()]); 
	bool may, must;
	dom.contains(fb, &may, &must);
	
	if (must) {
	  ISP_CATEGORY(bb) = ISP_ALWAYS_HIT;
	} 
	else {
	  if (!may) {
	    ISP_CATEGORY(bb) = ISP_ALWAYS_MISS;
	  } 
	  else {
	    BasicBlock *pers_header = NULL;
	    BasicBlock *loop_header = ENCLOSING_LOOP_HEADER(bb);
 	    while (loop_header){
	      bool pers_entering, pers_back = true;
 	      for (BasicBlock::InIterator edge(loop_header) ; edge && pers_back; edge++){
		BasicBlock * source = edge->source();
		ISPProblem::Domain source_out(*listener.results_out[cfg->number()][source->number()]); 
		bool pers_may, pers_must;
		source_out.contains(fb, &pers_may, &pers_must);
 		if (!Dominance::isBackEdge(edge)){  // edge thats enters the loop
		  pers_entering = pers_must;
		}
		else { // backedge
		  if (!pers_must)
		    pers_back = false;
		}
	      }
	      if (pers_back){
		pers_header = loop_header;
		if (pers_entering)
		  loop_header = ENCLOSING_LOOP_HEADER(loop_header);
		else
		  loop_header = NULL;
	      }
	      else
		loop_header = NULL;
	    }
		  
	    if (pers_header){
	      ISP_CATEGORY(bb) = ISP_PERSISTENT; 
	      ISP_HEADER(bb) = pers_header;
	    }
	    else
	      ISP_CATEGORY(bb) = ISP_NOT_CLASSIFIED; 
	  }
	}
      }
    }
  }