UsedVarsFixpointIterator::UsedVarsFixpointIterator( const local_pointers::FixpointIterator& pointers_fp_iter, const EffectSummaryMap& effect_summaries, const std::unordered_set<const DexMethod*>& non_overridden_virtuals, const cfg::ControlFlowGraph& cfg) : MonotonicFixpointIterator(cfg, cfg.blocks().size()), m_insn_env_map(gen_instruction_environment_map(cfg, pointers_fp_iter)), m_effect_summaries(effect_summaries), m_non_overridden_virtuals(non_overridden_virtuals) {}
/* * Record the environment before the execution of every instruction. We need * this data during the backwards used vars analysis. */ static std::unordered_map<const IRInstruction*, ptrs::Environment> gen_instruction_environment_map(const cfg::ControlFlowGraph& cfg, const ptrs::FixpointIterator& fp_iter) { std::unordered_map<const IRInstruction*, ptrs::Environment> result; for (auto* block : cfg.blocks()) { auto env = fp_iter.get_entry_state_at(block); for (auto& mie : InstructionIterable(block)) { auto* insn = mie.insn; result.emplace(insn, env); fp_iter.analyze_instruction(insn, &env); } } return result; }
std::string show(const cfg::ControlFlowGraph& cfg) { const auto& blocks = cfg.blocks(); std::ostringstream ss; ss << "CFG:\n"; for (const auto& b : blocks) { ss << " Block B" << b->id() << ":\n"; ss << " preds:"; for (const auto& p : b->preds()) { ss << " (" << *p << " B" << p->src()->id() << ")"; } ss << "\n"; ss << show(b); ss << " succs:"; for (auto& s : b->succs()) { ss << " (" << *s << " B" << s->target()->id() << ")"; } ss << "\n"; } return ss.str(); }