Android 4.4のARTのソース解析メモ

チラシの裏に書いておく。

gitのタグはandroid-4.4_r1
android-4.4_r1.2でもartに関しては差分なし。

バックエンドの選択

compiler-backendはビルド時に選択する。QuickとPortableの2種類。デフォルトではQuick。
Portableを選択する方法はbuild/Android.common.mk参照
http://tools.oesf.biz/android-4.4.0_r1.0/xref/art/build/Android.common.mk#71

  • ART_USE_PORTABLE_COMPILER


art/compiler/driver/compiler_driver.cc

 if (compiler_backend_ == kPortable) {
     // Initialize compiler_context_
     init_compiler_context = reinterpret_cast<void (*)(CompilerDriver&)>(ArtInitCompilerContext);
     compiler_ = reinterpret_cast<CompilerFn>(ArtCompileMethod);
 } else {
     init_compiler_context = reinterpret_cast<void (*)(CompilerDriver&)>(ArtInitQuickCompilerContext);
     compiler_ = reinterpret_cast<CompilerFn>(ArtQuickCompileMethod);
 }

変数compiler_ はvoid CompilerDriver::CompileMethod( ... )で使用される。

gitのログを拾い読みすると、将来的には整理して両方のバックエンドを搭載し、実行時に選択できるようにしたいようだ。

現状ではPortableを選択してビルドするとビルドエラーになる。MCLinkerのAPI変更に追従できていないようだ。MCLinkerはRenderScriptで使用しているので、frameworks/compile/mclinker/ にある。

Quickのバックエンドのコード生成

MIR -> LIR -> アセンブラコード
MIRはDEXコードそのもの。
LIRはアセンブラ命令と同等の粒度。
Quickのバックエンドでのコード生成は外部のライブラリを使用せず、自前で行っている。

DEXコードからLIRを生成するのはCompileDalvikInstruction

http://tools.oesf.biz/android-4.4.0_r1.0/xref/art/compiler/dex/quick/mir_to_lir.cc#29

LIRをアセンブルするのは各アーキごとのAssembleInstructions ARMの場合は以下。

http://tools.oesf.biz/android-4.4.0_r1.0/xref/art/compiler/dex/quick/arm/assemble_arm.cc#1005

Portableのバックエンドのコード生成

LLVMのModule, Functionを使うのはcompiler/llvm/llvm_compilation_unit.{cc,h}
http://tools.oesf.biz/android-4.4.0_r1.0/xref/art/compiler/llvm/llvm_compilation_unit.h

DEXファイルをコンパイルするときにクラスごとに並列でコンパイルされる

http://tools.oesf.biz/android-4.4.0_r1.0/xref/art/compiler/driver/compiler_driver.cc#2266
スレッドの個数は、sysconf(_SC_NPROCESSORS_CONF) で求めたコアの個数。

その他のビルド時のオプション

以下の項目もビルド時に選択できる。

  • ART_SMALL_MODE

サイズを小さく保つためコンパイルするメソッドの数を制限する

  • ART_SEA_IR_MODE

(未調査)