Exemple #1
0
bool relocate_method_if_no_changes(DexMethod* method, DexType* to_type) {
  if (!gather_invoked_methods_that_prevent_relocation(method)) {
    return false;
  }

  set_public(method);
  relocate_method(method, to_type);
  change_visibility(method);

  return true;
}
Exemple #2
0
void MultiMethodInliner::inline_callees(
    InlineContext& inline_context, std::vector<DexMethod*>& callees) {
  size_t found = 0;
  auto caller = inline_context.caller;
  auto insns = caller->get_code()->get_instructions();

  // walk the caller opcodes collecting all candidates to inline
  // Build a callee to opcode map
  std::vector<std::pair<DexMethod*, DexOpcodeMethod*>> inlinables;
  for (auto insn = insns.begin(); insn != insns.end(); ++insn) {
    if (!is_invoke((*insn)->opcode())) continue;
    auto mop = static_cast<DexOpcodeMethod*>(*insn);
    auto callee = resolver(mop->get_method(), opcode_to_search(*insn));
    if (callee == nullptr) continue;
    if (std::find(callees.begin(), callees.end(), callee) == callees.end()) {
      continue;
    }
    always_assert(callee->is_concrete());
    found++;
    inlinables.push_back(std::make_pair(callee, mop));
    if (found == callees.size()) break;
  }
  if (found != callees.size()) {
    always_assert(found <= callees.size());
    info.not_found += callees.size() - found;
  }

  // attempt to inline all inlinable candidates
  for (auto inlinable : inlinables) {
    auto callee = inlinable.first;
    auto mop = inlinable.second;

    if (!is_inlinable(callee, caller)) continue;

    auto op = mop->opcode();
    if (is_invoke_range(op)) {
      info.invoke_range++;
      continue;
    }

    TRACE(MMINL, 4, "inline %s (%d) in %s (%d)\n",
        SHOW(callee), caller->get_code()->get_registers_size(),
        SHOW(caller),
        callee->get_code()->get_registers_size() -
        callee->get_code()->get_ins_size());
    change_visibility(callee);
    MethodTransform::inline_16regs(inline_context, callee, mop);
    info.calls_inlined++;
    inlined.insert(callee);
  }
}