ART世界探险(14) - 快速编译器和优化编译器

ART世界探险(14) - 快速编译器和优化编译器

ART的编译器为两种,一种是QuickCompiler,快速编译器;另一种是OptimizingCompiler,优化编译器。

编译器的基类 - Compiler类

Compiler类是真正实现Java方法和Jni方法编译的入口。
我们先通过一个思维导图来看一下它的结构:

art_Compiler

有了上面的结构图之后,我们再看下面的类结构就非常清晰了。

class Compiler {
 public:
  enum Kind {
    kQuick,
    kOptimizing
  };

Kind有两类,Quick和Optimizing。它的子类也有两个:QuickCompiler和OptimizingCompiler.

  static Compiler* Create(CompilerDriver* driver, Kind kind);

  virtual void Init() = 0;

  virtual void UnInit() const = 0;

  virtual bool CanCompileMethod(uint32_t method_idx, const DexFile& dex_file, CompilationUnit* cu)
      const = 0;

  virtual CompiledMethod* 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 = 0;

  virtual CompiledMethod* JniCompile(uint32_t access_flags,
                                     uint32_t method_idx,
                                     const DexFile& dex_file) const = 0;

  virtual uintptr_t GetEntryPointOf(ArtMethod* method) const
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;

  uint64_t GetMaximumCompilationTimeBeforeWarning() const {
    return maximum_compilation_time_before_warning_;
  }

  virtual void InitCompilationUnit(CompilationUnit& cu) const = 0;

  virtual ~Compiler() {}

  /*
   * @brief Generate and return Dwarf CFI initialization, if supported by the
   * backend.
   * @param driver CompilerDriver for this compile.
   * @returns nullptr if not supported by backend or a vector of bytes for CFI DWARF
   * information.
   * @note This is used for backtrace information in generated code.
   */
  virtual std::vector<uint8_t>* GetCallFrameInformationInitialization(const CompilerDriver& driver)
      const {
    UNUSED(driver);
    return nullptr;
  }

  // Returns whether the method to compile is such a pathological case that
  // it's not worth compiling.
  static bool IsPathologicalCase(const DexFile::CodeItem& code_item,
                                 uint32_t method_idx,
                                 const DexFile& dex_file);

 protected:
  explicit Compiler(CompilerDriver* driver, uint64_t warning) :
      driver_(driver), maximum_compilation_time_before_warning_(warning) {
  }

  CompilerDriver* GetCompilerDriver() const {
    return driver_;
  }

 private:
  CompilerDriver* const driver_;
  const uint64_t maximum_compilation_time_before_warning_;

  DISALLOW_COPY_AND_ASSIGN(Compiler);
};

快速编译器 - QuickCompiler

QuickerCompiler在实现了所有Compiler基类的方法之外,新增了两个PassManager,用来管理前优化的Pass和后优化的Pass.
我们来看下增加了QuickCompiler之后的Compiler思维导图:

art_Compiler_v2

class QuickCompiler : public Compiler {
 public:
  virtual ~QuickCompiler();

  void Init() OVERRIDE;

  void UnInit() const OVERRIDE;

  bool CanCompileMethod(uint32_t method_idx, const DexFile& dex_file, CompilationUnit* cu) const
      OVERRIDE;

  CompiledMethod* 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 OVERRIDE;

  CompiledMethod* JniCompile(uint32_t access_flags,
                             uint32_t method_idx,
                             const DexFile& dex_file) const OVERRIDE;

  uintptr_t GetEntryPointOf(ArtMethod* method) const OVERRIDE
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  static Mir2Lir* GetCodeGenerator(CompilationUnit* cu, void* compilation_unit);

  void InitCompilationUnit(CompilationUnit& cu) const OVERRIDE;

  static Compiler* Create(CompilerDriver* driver);

  const PassManager* GetPreOptPassManager() const {
    return pre_opt_pass_manager_.get();
  }
  const PassManager* GetPostOptPassManager() const {
    return post_opt_pass_manager_.get();
  }

 protected:
  explicit QuickCompiler(CompilerDriver* driver);

 private:
  std::unique_ptr<PassManager> pre_opt_pass_manager_;
  std::unique_ptr<PassManager> post_opt_pass_manager_;
  DISALLOW_COPY_AND_ASSIGN(QuickCompiler);
};

PassManager

我们顺藤摸瓜来看下PassManager的作用:

class PassManager {
 public:
  explicit PassManager(const PassManagerOptions& options);
  virtual ~PassManager();
  void CreateDefaultPassList();
  void AddPass(const Pass* pass) {
    passes_.push_back(pass);
  }
  /**
   * @brief Print the pass names of all the passes available.
   */
  void PrintPassNames() const;
  const std::vector<const Pass*>* GetDefaultPassList() const {
    return &default_pass_list_;
  }
  const PassManagerOptions& GetOptions() const {
    return options_;
  }

 private:
  /** @brief The set of possible passes.  */
  std::vector<const Pass*> passes_;

  /** @brief The default pass list is used to initialize pass_list_. */
  std::vector<const Pass*> default_pass_list_;

  /** @brief Pass manager options. */
  PassManagerOptions options_;

  DISALLOW_COPY_AND_ASSIGN(PassManager);
};

从上面的类中可以看出,PassManager主要就是Pass的一个列表容器。

Pass是什么?

上面是Pass的列表,那么Pass是什么呢?
Pass就是优化时,我们所要做的一些步骤。这次是我们第一次跟它打交道,后面我们要花一些时间在Pass上。
我们先看看,ART都提供了哪些Pass供我们选择:

Pass

Pass有两个重要的子类,一个是PassME,目前所有的其它子类都继承自PassME。另一个是PassME的子类PassMEMirSsaRep,是将MIR进行SSA表示的优化。

优化编译器OptimizingCompiler

优化编译器在Compiler的基础上增加了两个公开方法:
1. TryCompile
2. MaybeRecordStat

另外,在私有方法上,优化编译器区分了带有优化的编译CompileOptimized和不带优化的CompileBaseline.
我们再看下思维导图,加深一下印象:

Compiler_v3

下面是源代码,大家浏览过一下就好。

class OptimizingCompiler FINAL : public Compiler {
 public:
  explicit OptimizingCompiler(CompilerDriver* driver);
  ~OptimizingCompiler();

  bool CanCompileMethod(uint32_t method_idx, const DexFile& dex_file, CompilationUnit* cu) const
      OVERRIDE;

  CompiledMethod* 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 OVERRIDE;

  CompiledMethod* TryCompile(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;

  CompiledMethod* JniCompile(uint32_t access_flags,
                             uint32_t method_idx,
                             const DexFile& dex_file) const OVERRIDE {
    return ArtQuickJniCompileMethod(GetCompilerDriver(), access_flags, method_idx, dex_file);
  }

  uintptr_t GetEntryPointOf(ArtMethod* method) const OVERRIDE
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    return reinterpret_cast<uintptr_t>(method->GetEntryPointFromQuickCompiledCodePtrSize(
        InstructionSetPointerSize(GetCompilerDriver()->GetInstructionSet())));
  }

  void InitCompilationUnit(CompilationUnit& cu) const OVERRIDE;

  void Init() OVERRIDE;

  void UnInit() const OVERRIDE;

  void MaybeRecordStat(MethodCompilationStat compilation_stat) const {
    if (compilation_stats_.get() != nullptr) {
      compilation_stats_->RecordStat(compilation_stat);
    }
  }

 private:
  // Whether we should run any optimization or register allocation. If false, will
  // just run the code generation after the graph was built.
  const bool run_optimizations_;

  // Optimize and compile `graph`.
  CompiledMethod* CompileOptimized(HGraph* graph,
                                   CodeGenerator* codegen,
                                   CompilerDriver* driver,
                                   const DexFile& dex_file,
                                   const DexCompilationUnit& dex_compilation_unit,
                                   PassInfoPrinter* pass_info) const;

  // Just compile without doing optimizations.
  CompiledMethod* CompileBaseline(CodeGenerator* codegen,
                                  CompilerDriver* driver,
                                  const DexCompilationUnit& dex_compilation_unit) const;

  std::unique_ptr<OptimizingCompilerStats> compilation_stats_;

  std::unique_ptr<std::ostream> visualizer_output_;

  // Delegate to Quick in case the optimizing compiler cannot compile a method.
  std::unique_ptr<Compiler> delegate_;

  DISALLOW_COPY_AND_ASSIGN(OptimizingCompiler);
};

优化编译状态 - MethodComplicationStat

优化编译还是挺复杂的,有下面一堆状态:
后面用到的时候我们再详细解释,大家知道有一堆状态就好。

enum MethodCompilationStat {
  kAttemptCompilation = 0,
  kCompiledBaseline,
  kCompiledOptimized,
  kCompiledQuick,
  kInlinedInvoke,
  kInstructionSimplifications,
  kNotCompiledBranchOutsideMethodCode,
  kNotCompiledCannotBuildSSA,
  kNotCompiledCantAccesType,
  kNotCompiledClassNotVerified,
  kNotCompiledHugeMethod,
  kNotCompiledLargeMethodNoBranches,
  kNotCompiledMalformedOpcode,
  kNotCompiledNoCodegen,
  kNotCompiledNonSequentialRegPair,
  kNotCompiledPathological,
  kNotCompiledSpaceFilter,
  kNotCompiledUnhandledInstruction,
  kNotCompiledUnresolvedField,
  kNotCompiledUnresolvedMethod,
  kNotCompiledUnsupportedIsa,
  kNotCompiledVerifyAtRuntime,
  kNotOptimizedDisabled,
  kNotOptimizedRegisterAllocator,
  kNotOptimizedTryCatch,
  kRemovedCheckedCast,
  kRemovedDeadInstruction,
  kRemovedNullCheck,
  kLastStat
};

编译单元:CompilationUnit

我们先看下CompliationUnit的思维导图结构:

art_CompilationUnit

struct CompilationUnit {
  CompilationUnit(ArenaPool* pool, InstructionSet isa, CompilerDriver* driver, ClassLinker* linker);
  ~CompilationUnit();

  void StartTimingSplit(const char* label);
  void NewTimingSplit(const char* label);
  void EndTiming();

  /*
   * Fields needed/generated by common frontend and generally used throughout
   * the compiler.
  */
  CompilerDriver* const compiler_driver;
  ClassLinker* const class_linker;        // Linker to resolve fields and methods.
  const DexFile* dex_file;                // DexFile containing the method being compiled.
  jobject class_loader;                   // compiling method's class loader.
  uint16_t class_def_idx;                 // compiling method's defining class definition index.
  uint32_t method_idx;                    // compiling method's index into method_ids of DexFile.
  uint32_t access_flags;                  // compiling method's access flags.
  InvokeType invoke_type;                 // compiling method's invocation type.
  const char* shorty;                     // compiling method's shorty.
  uint32_t disable_opt;                   // opt_control_vector flags.
  uint32_t enable_debug;                  // debugControlVector flags.
  bool verbose;
  const InstructionSet instruction_set;
  const bool target64;

  // TODO: move memory management to mir_graph, or just switch to using standard containers.
  ArenaAllocator arena;
  ArenaStack arena_stack;  // Arenas for ScopedArenaAllocator.

  std::unique_ptr<MIRGraph> mir_graph;   // MIR container.
  std::unique_ptr<Mir2Lir> cg;           // Target-specific codegen.
  TimingLogger timings;
  bool print_pass;                 // Do we want to print a pass or not?

  /**
   * @brief Holds pass options for current pass being applied to compilation unit.
   * @details This is updated for every pass to contain the overridden pass options
   * that were specified by user. The pass itself will check this to see if the
   * default settings have been changed. The key is simply the option string without
   * the pass name.
   */
  SafeMap<const std::string, const OptionContent> overridden_pass_options;
};
### Android 14ART 虚拟机的工作原理与特性 #### 工作原理 ARTAndroid Runtime)作为现代 Android 设备的主要运行环境,其工作原理主要围绕 **AOT (Ahead-of-Time)** **JIT (Just-in-Time)** 编译技术展开。自 Android 7.0 开始,ART 引入了 JIT 编译器优化性能并减少存储空间占用[^3]。 在 Android 14 中,ART 继续改进编译策略,通过动态调整 AOT JIT 的平衡点来提升应用启动速度运行效率。具体而言: - **AOT 编译**:在安装阶段将字节码转换为本地机器码,从而显著提高首次加载的速度。 - **JIT 编译**:针对频繁执行的代码片段实时生成高效的机器指令,并将其缓存到设备上以便后续调用时重用。 此外,ART 使用分代垃圾回收机制(Generational Garbage Collection),能够更高效地管理内存资源。这种机制将堆分为年轻代(Young Generation)、老年代(Old Generation)等多个区域,分别采取不同的清理算法以降低停顿时间[^2]。 #### 主要特性 以下是 Android 14ART 虚拟机的关键特性增强功能: 1. **Profile-Guided Optimization (PGO)**: PGO 是一种基于实际使用情况的数据驱动方法,用于指导编译过程中的决策制定。通过对常用路径进行优先级排序,可以进一步缩短冷启动时间热路径延迟[^4]^。 2. **并发标记清除(Concurrent Mark-Sweep, CMS)GC 改进**: 新版 ART 提升了 CMS 垃圾收集器的表现力,减少了全局暂停的时间窗口长度以及频率。这使得用户体验更加流畅无卡顿现象发生[^5]^。 3. **内存分配优化**: ART 实现了一种新型的对象布局方案——Compact Object Layouts,它允许更好地利用 CPU 缓存行大小来进行连续数据访问操作,进而改善整体吞吐量表现[^6]^。 4. **安全性加强措施**: - 加密 Dex 文件传输流程防止中间人攻击; - 扩展验证链路至第三方库级别确保供应链安全; 5. **调试支持扩展**: 提供更为丰富的诊断工具集帮助开发者快速定位问题所在位置及其根本原因分析能力得到极大程度上的强化[^7]^。 ```python # 示例 Python 伪代码展示如何模拟简单的 GC 行为 class SimpleGarbageCollector: def __init__(self): self.objects = [] def add_object(self, obj): if not any(o is obj for o in self.objects): # 检查是否存在相同引用 self.objects.append(obj) def remove_unreferenced_objects(self): global_vars = globals().values() referenced_objs = set(global_vars).union(*(vars(x).values() for x in global_vars)) unreferenced = [o for o in self.objects if id(o) not in map(id, referenced_objs)] for u in unreferenced: del u gc_instance = SimpleGarbageCollector() def test(): a = {"key": "value"} gc_instance.add_object(a) test() print(len(gc_instance.objects)) # 输出应为 0,因为 'a' 在函数作用域结束后被销毁 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jtag特工

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值