Ejemplo n.º 1
0
void SimpleInlinePass::run_pass(DexClassesVector& dexen, ConfigFiles& cfg, PassManager& mgr) {
  const auto no_inline = no_inline_annos(m_no_inline_annos, cfg);

  auto scope = build_class_scope(dexen);
  // gather all inlinable candidates
  auto methods = gather_non_virtual_methods(scope, no_inline);
  select_single_called(scope, methods);

  auto resolver = [&](DexMethod* method, MethodSearch search) {
    return resolve_method(method, search, resolved_refs);
  };

  // inline candidates
  MultiMethodInliner inliner(
      scope, dexen[0], inlinable, resolver, m_inliner_config);
  inliner.inline_methods();

  // delete all methods that can be deleted
  auto inlined = inliner.get_inlined();
  size_t inlined_count = inlined.size();
  size_t deleted = delete_methods(scope, inlined, resolver);

  TRACE(SINL, 3, "recursive %ld\n", inliner.get_info().recursive);
  TRACE(SINL, 3, "blacklisted meths %ld\n", inliner.get_info().blacklisted);
  TRACE(SINL, 3, "more than 16 regs %ld\n",
      inliner.get_info().more_than_16regs);
  TRACE(SINL, 3, "try/catch in callee %ld\n",
      inliner.get_info().try_catch_block);
  TRACE(SINL, 3, "try/catch in caller %ld\n",
      inliner.get_info().caller_tries);
  TRACE(SINL, 3, "virtualizing methods %ld\n", inliner.get_info().need_vmethod);
  TRACE(SINL, 3, "invoke super %ld\n", inliner.get_info().invoke_super);
  TRACE(SINL, 3, "override inputs %ld\n", inliner.get_info().write_over_ins);
  TRACE(SINL, 3, "escaped virtual %ld\n", inliner.get_info().escaped_virtual);
  TRACE(SINL, 3, "known non public virtual %ld\n",
      inliner.get_info().non_pub_virtual);
  TRACE(SINL, 3, "non public ctor %ld\n", inliner.get_info().non_pub_ctor);
  TRACE(SINL, 3, "unknown field %ld\n", inliner.get_info().escaped_field);
  TRACE(SINL, 3, "non public field %ld\n", inliner.get_info().non_pub_field);
  TRACE(SINL, 3, "throws %ld\n", inliner.get_info().throws);
  TRACE(SINL, 3, "array data %ld\n", inliner.get_info().array_data);
  TRACE(SINL, 3, "multiple returns %ld\n", inliner.get_info().multi_ret);
  TRACE(SINL, 3, "reference outside of primary %ld\n",
      inliner.get_info().not_in_primary);
  TRACE(SINL, 3, "not found %ld\n", inliner.get_info().not_found);
  TRACE(SINL, 1,
      "%ld inlined calls over %ld methods and %ld methods removed\n",
      inliner.get_info().calls_inlined, inlined_count, deleted);
}
Ejemplo n.º 2
0
// Replace function calls with body
void Inliner::VisitCallExpr(CallExpr *node) {
    FunctionDecl * calee_ptr = node->getDirectCallee();
    if (!calee_ptr || !calee_ptr->hasBody()) {
        return;
    }

    // Visit the body and prefix all DeclRefs and Labels
    //string prefixed_body = PrefixFunc(fd);

    // Replace returns with goto + assignment

    // replace the prototype with locals and connect to the call arguments
    //if (functions_.count(calee_ptr) == 0) {
    Inliner inliner(rewriter_,source_manager_,contex_);
    inliner.VisitFunctionDecl(calee_ptr);
    //}


    stringstream ss;
    string calee_name = calee_ptr->getNameAsString();
    // add a start label (just for readability)
    ss << "{\n/*" << Defines::kLabelStart << calee_name << replacements_ << ":*/\n";
    // put in the arguments, start with RetVal and Ret
    string result_type = calee_ptr->getResultType().getAsString();
    if (result_type != "void") 
        ss << result_type << " " << Defines::kRetVal << "_" << calee_name << replacements_ << ";\n";
    ss << Defines::kGuardType << " " << Defines::kRetGuard << "_" << calee_name << replacements_ << " = 0;\n";
    // use temporary variables to transfer arguments to avoid this: 
    //  double foo(int x) { // foo body } main() { y = foo(x); }
    // turning into this:
    //  main () {
    //      {
    //          int tmp_x = x;
    //          double retval;
    //          {
    //              int x = tmp_x;
    //              // foo body
    //          }
    //          y = retval;
    //      }
    //  }
    stringstream temps, params;
    for (size_t i = 0; i < calee_ptr->getNumParams() ; ++i) {
        ParmVarDecl * param_ptr = calee_ptr->getParamDecl(i);
        string decl = Utils::PrintDecl(param_ptr,contex_);
        string name = param_ptr->getNameAsString();
        string type = decl.substr(0,decl.find_last_of(name) - name.size() + 1);
        temps << type << Defines::kTempPrefix << calee_name << "_" << name << replacements_<< " = " << Utils::PrintStmt(node->getArg(i),contex_) << ";\n";
        params << decl << " = " << Defines::kTempPrefix << calee_name << "_" << name << replacements_ << ";\n";
    }
    ss << temps.str() << "{\n" << params.str();
    // put in the inlined body
    ss << inliner.body_;
    ss << "\n}\n";
    // add the end label (just for readability)
    ss << "/*" << Defines::kLabelEnd << calee_name << replacements_ << ":*/\n";
    // connect the return value
    if (!return_vars_.empty()) {
        ss << return_vars_.back() << " = " << Defines::kRetVal << "_" << calee_name << replacements_;
    }
    ss << ";\n";
    ss << "}\n";

    SourceLocation start = node->getSourceRange().getBegin();
    Rewriter &rw = (current_func_->isMain()) ? main_rewriter_ : rewriter_;
    rw.ReplaceText(start, Utils::GetStmtLength(node),ss.str());
}