ART世界探险(16) - 快速编译器下的方法编译

简介: ART快速编译器下的方法编译

ART世界探险(16) - 快速编译器下的方法编译

我们对三大组件有了了解之后,下面终于可以开始正餐,开始分析两种Compiler下的Compile函数。

我们先看一张图,对于整个流程有个整体的印象,然后我们再去看代码:

quick_compile

QuickCompiler的Compile

CompiledMethod* QuickCompiler::Compile(const DexFile::CodeItem* code_item,
                                       uint32_t access_flags,
                                       InvokeType invoke_type,
                                       uint16_t class_def_idx,
                                       uint32_t method_idx,
                                       jobject class_loader,
                                       const DexFile& dex_file) const {
...
CompilerDriver* driver = GetCompilerDriver();

上来就是老朋友,先获取CompilerDriver对象。前面我们介绍过,它是调用编译器的驱动接口,大杂烩类。
然后下面判断是不是病态情况,值不值得编译。是不是经过校验。是不是打开了编译开关。

...
  if (Compiler::IsPathologicalCase(*code_item, method_idx, dex_file)) {
    return nullptr;
  }

  if (driver->GetVerifiedMethod(&dex_file, method_idx)->HasRuntimeThrow()) {
    return nullptr;
  }

  DCHECK(driver->GetCompilerOptions().IsCompilationEnabled());

下面是Runtime和ClassLinker出场,三大组件齐了。
然后是大管家CompliationUnit开始工作。

  Runtime* const runtime = Runtime::Current();
  ClassLinker* const class_linker = runtime->GetClassLinker();
  InstructionSet instruction_set = driver->GetInstructionSet();
  if (instruction_set == kArm) {
    instruction_set = kThumb2;
  }
  CompilationUnit cu(runtime->GetArenaPool(), instruction_set, driver, class_linker);
  cu.dex_file = &dex_file;
  cu.class_def_idx = class_def_idx;
  cu.method_idx = method_idx;
  cu.access_flags = access_flags;
  cu.invoke_type = invoke_type;
  cu.shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx));

  CHECK((cu.instruction_set == kThumb2) ||
        (cu.instruction_set == kArm64) ||
        (cu.instruction_set == kX86) ||
        (cu.instruction_set == kX86_64) ||
        (cu.instruction_set == kMips) ||
        (cu.instruction_set == kMips64));

...
  InitCompilationUnit(cu);

上面都是在做CompilationUnit的初始化工作,例如这个InitCompilationUnit:

void QuickCompiler::InitCompilationUnit(CompilationUnit& cu) const {
  // Disable optimizations according to instruction set.
  cu.disable_opt |= kDisabledOptimizationsPerISA[cu.instruction_set];
  if (Runtime::Current()->UseJit()) {
    // Disable these optimizations for JIT until quickened byte codes are done being implemented.
    // TODO: Find a cleaner way to do this.
    cu.disable_opt |= 1u << kLocalValueNumbering;
  }
}

然后开始构建MIRGraph.

  cu.mir_graph.reset(new MIRGraph(&cu, &cu.arena));

  /*
   * After creation of the MIR graph, also create the code generator.
   * The reason we do this is that optimizations on the MIR graph may need to get information
   * that is only available if a CG exists.
   */
  cu.cg.reset(GetCodeGenerator(&cu, nullptr));

  /* Build the raw MIR graph */
  cu.mir_graph->InlineMethod(code_item, access_flags, invoke_type, class_def_idx, method_idx,
                             class_loader, dex_file);
...

下面创建Pass驱动,然后调用它来做优化。

  /* Create the pass driver and launch it */
  PassDriverMEOpts pass_driver(GetPreOptPassManager(), GetPostOptPassManager(), &cu);
  pass_driver.Launch();
...

寄存器重新映射

  /* Reassociate sreg names with original Dalvik vreg names. */
  cu.mir_graph->RemapRegLocations();

清理内存,以便下次复用

  /* Free Arenas from the cu.arena_stack for reuse by the cu.arena in the codegen. */
...
  cu.arena_stack.Reset();

  CompiledMethod* result = nullptr;
...

生成机器指令

  cu.cg->Materialize();
...

消除重复数据,并重复结果

  result = cu.cg->GetCompiledMethod();
...
  return result;
}

我们为下一章节做个小小的预告,下面我们将深入到MIRGraph,CodeGenerator,优化的Pass还有Mir2Lir的激动人心的过程中。
先上一个预告图,顺便复习一下之前所学的流程:

mir2lir

目录
相关文章
|
前端开发 C语言 iOS开发
基于LLVM的编译原理简明教程 (1) - 写编译器越来越容易了
跟学院派的厚书给大家的印象不同,其实用LLVM写个简单的编译器是件容易的事情,因为大部分事情LLVM都替我们做了。
8319 0
|
编译器 开发工具
音视频开发: VS2017编译器编译libVLC错误解决
音视频开发: VS2017编译器编译libVLC错误解决
294 0
音视频开发: VS2017编译器编译libVLC错误解决
《编译与反编译技术实战 》一1.5 编译器LLVM
LLVM是构架编译器的框架系统,由C++编写而成,用于优化以任意程序语言编写的程序的编译时间、链接时间、运行时间以及空闲时间,对开发者保持开放,并兼容已有脚本。LLVM计划启动于2000年,最初由伊利诺伊大学香槟分校的Chris Lattner主持开展。
1568 0
|
前端开发 程序员
《编译与反编译技术实战 》一2.2 编译器的结构
目前常用的程序设计语言都已经有很多优秀的编译器,比如C语言有GCC和ICC、C++有G++和I++、Java有JAVAC和GCJ。然而,即使这些常用的程序设计语言,其本身也一直在改变,即不断地完善。因而,实现这些程序设计语言的编译器也需要做出相应的改动。
1294 0