dex2oat将dex转换为oat的执行路径概览

dex2oat是一个可执行文件,在源码中通过编译文件art\dex2oat\Dex2oat.cc生成。


dex2oat的执行入口是:

int main(int argc, char** argv) {
  return art::dex2oat(argc, argv);
}

在函数dex2oat中调用了dex2oat->CreateOatFile函数,在CreateOatFile函数中执行了driver->CompileAll(class_loader, dex_files, timings);语句,这条语句将dex文件编译成了oat文件。

void CompilerDriver::CompileAll(jobject class_loader,
                                const std::vector& dex_files,
                                base::TimingLogger& timings) {
  DCHECK(!Runtime::Current()->IsStarted());
  UniquePtr thread_pool(new ThreadPool(thread_count_ - 1));
  PreCompile(class_loader, dex_files, *thread_pool.get(), timings);
  Compile(class_loader, dex_files, *thread_pool.get(), timings);
  if (dump_stats_) {
    stats_->Dump();
  }
}


Compile函数

void CompilerDriver::Compile(jobject class_loader, const std::vector& dex_files,
                       ThreadPool& thread_pool, base::TimingLogger& timings) {
  for (size_t i = 0; i != dex_files.size(); ++i) {
    const DexFile* dex_file = dex_files[i];
    CHECK(dex_file != NULL);
    CompileDexFile(class_loader, *dex_file, thread_pool, timings);
  }
}


CompileDexFile函数

void CompilerDriver::CompileDexFile(jobject class_loader, const DexFile& dex_file,
                                    ThreadPool& thread_pool, base::TimingLogger& timings) {
  // TODO: strdup memory leak.
  timings.NewSplit(strdup(("Compile " + dex_file.GetLocation()).c_str()));
  ParallelCompilationManager context(Runtime::Current()->GetClassLinker(), class_loader, this,
                                     &dex_file, thread_pool);
  context.ForAll(0, dex_file.NumClassDefs(), CompilerDriver::CompileClass, thread_count_);
}

context.ForAll(0, dex_file.NumClassDefs(), CompilerDriver::CompileClass, thread_count_);这条语句中重要的是CompilerDriver::CompileClass,CompilerDriver::CompileClass代表一个回调函数,这个回调函数将一个dex中的类进行编译。


CompileClass函数中调用了CompileMethod函数将一个方法进行编译,其中使用到了类的成员变量jni_compiler_和compiler_,这两个成员变量均在CompilerDriver类的构造函数中被赋值:

CompilerDriver::CompilerDriver(CompilerBackend compiler_backend, InstructionSet instruction_set,
                               bool image, DescriptorSet* image_classes, size_t thread_count,
                               bool dump_stats) ... {
...
  if (compiler_backend_ == kPortable) {
    // Initialize compiler_context_
    init_compiler_context = reinterpret_cast(ArtInitCompilerContext);
    compiler_ = reinterpret_cast(ArtCompileMethod);
  } else {
    init_compiler_context = reinterpret_cast(ArtInitQuickCompilerContext);
    compiler_ = reinterpret_cast(ArtQuickCompileMethod);
  }
...
  if (compiler_backend_ == kPortable) {
    jni_compiler_ = reinterpret_cast(ArtLLVMJniCompileMethod);
  } else {
    jni_compiler_ = reinterpret_cast(ArtQuickJniCompileMethod);
  }
...
}

这其中有这么几个函数值得关注:ArtCompileMethod、ArtQuickCompileMethod、ArtLLVMJniCompileMethod、ArtQuickJniCompileMethod。


查看其中ArtCompileMethod函数的代码:

extern "C" art::CompiledMethod* ArtCompileMethod(art::CompilerDriver& driver,
                                                 const art::DexFile::CodeItem* code_item,
                                                 uint32_t access_flags,
                                                 art::InvokeType invoke_type,
                                                 uint16_t class_def_idx,
                                                 uint32_t method_idx,
                                                 jobject class_loader,
                                                 const art::DexFile& dex_file) {
  UNUSED(class_def_idx);  // TODO: this is used with Compiler::RequiresConstructorBarrier.
  art::ClassLinker *class_linker = art::Runtime::Current()->GetClassLinker();

  art::DexCompilationUnit dex_compilation_unit(
    NULL, class_loader, class_linker, dex_file, code_item,
    class_def_idx, method_idx, access_flags);
  art::llvm::CompilerLLVM* compiler_llvm = ContextOf(driver);
  art::CompiledMethod* result = compiler_llvm->CompileDexMethod(&dex_compilation_unit, invoke_type);
  return result;
}

通过上面ArtCompileMethod函数的代码发现,使用类art::llvm::CompilerLLVM中的CompileDexMethod函数对dex中的方法进行了编译。


art::llvm::CompilerLLVM属于LLVM的范畴。以上就是dex2oat工具将dex转换为oat的执行路径概览,未涉及到具体细节。

你可能感兴趣的:(Android,Art研究)