美文网首页
ART世界探险(16) - 快速编译器下的方法编译

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

作者: Jtag特工 | 来源:发表于2016-09-07 21:05 被阅读133次

    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的激动人心的过程中。
    先上一个预告图,顺便复习一下之前所学的流程:

    Paste_Image.png

    相关文章

      网友评论

          本文标题:ART世界探险(16) - 快速编译器下的方法编译

          本文链接:https://www.haomeiwen.com/subject/cpajettx.html