In order to better understand the working principle of ARTist, this paper analyses the special features of dex2oat in ARTist.
Refer to my previous article for the basic process of dex2oat: Analysis of dex2oat source code flow
First, look at the code flow of native dex2oat:
First, the first difference is in the Compile function:
void Compile() {
TimingLogger::ScopedTiming t("dex2oat Compile", timings_);
compiler_phases_timings_.reset(new CumulativeLogger("compilation times"));
// Handle and ClassLoader creation needs to come after Runtime::Create
jobject class_loader = nullptr;
Thread* self = Thread::Current();
if (!boot_image_option_.empty()) {
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
OpenClassPathFiles(runtime_->GetClassPathString(), dex_files_, &class_path_files_);
ScopedObjectAccess soa(self);
// Classpath: first the class-path given.
std::vector<const DexFile*> class_path_files;
for (auto& class_path_file : class_path_files_) {
class_path_files.push_back(class_path_file.get());
}
// Store the classpath we have right now.
key_value_store_->Put(OatHeader::kClassPathKey,
OatFile::EncodeDexFileDependencies(class_path_files));
// Then the dex files we'll compile. Thus we'll resolve the class-path first.
class_path_files.insert(class_path_files.end(), dex_files_.begin(), dex_files_.end());
class_loader = class_linker->CreatePathClassLoader(self, class_path_files);
-------------------------------------------------------------------------------------------------------------------
/* artist setup and module management */
ArtistLog::SetupArtistLogging();
VLOG(artist) << "START ARTIST SETUP (dex2oat)";
ModuleManager& module_manager = ModuleManager::getInstance();
// TODO eventually the modules should register themselves, e.g., from their own .so
module_manager.registerModule("trace", make_shared<TraceModule>());
module_manager.registerModule("logtimization", make_shared<LogtimizationModule>());
// initialize modules
module_manager.initializeModules(dex_files_, class_loader);
VLOG(artist) << "END ARTIST SETUP (dex2oat)";
-------------------------------------------------------------------------------------------------------------------
}
driver_ = new CompilerDriver(compiler_options_.get(),
verification_results_,
&method_inliner_map_,
compiler_kind_,
instruction_set_,
instruction_set_features_.get(),
image_,
image_classes_.release(),
compiled_classes_.release(),
nullptr,
thread_count_,
dump_stats_,
dump_passes_,
dump_cfg_file_name_,
compiler_phases_timings_.get(),
swap_fd_,
profile_file_);
driver_->CompileAll(class_loader, dex_files_, timings_);
}
ARTist has more than the middle part of the horizontal line than the native code. ModuleManager::getInstance() returns a ModuleManager handle, and module_manager.registerModule stores the Module in the map of _modules according to the key and value index. The module_manager.initializeModules code is as follows:
void ModuleManager::initializeModules(vector<const DexFile*> dex_files, jobject jclass_loader) {
VLOG(artistd) << "ModuleManager: initializing modules ";
if (init_flag.exchange(true)) { // atomic check and set
string msg = "ModuleManager: Attempting to initialize modules more than once.";
ErrorHandler::abortCompilation(msg);
}
_dex_file_env = make_shared<DexfileEnvironment>(dex_files);
for (auto it : _modules) {
auto id = it.first;
auto module = it.second;
auto codelib = module->createCodeLib();
// initialize environment for codelib if present
if (codelib != nullptr) {
VLOG(artistd) << "ModuleManager: initializing codelib environment for module " << id;
const MethodSignature signature = codelib->getCodeClass();
const DexFile* codelib_dexfile = nullptr;
for (auto && dexfile : dex_files) {
// check whether `dexfile` defines the code lib class (lookup by signature)
if (ArtUtils::FindClassDefIdxFromName(dexfile, signature)) {
codelib_dexfile = dexfile;
VLOG(artistd) << "ModuleManager: Found " << signature << " in dex file " << codelib_dexfile->GetLocation();
break;
}
}
if (codelib_dexfile == nullptr) {
auto msg = "Could not find dexfile defining codelib class " + signature
+ " (requires codelib). Deactivating module " + id + ".";
VLOG(artistd) << msg;
module->setEnabled(false);
} else {
_dex_file_env->declareCodelib(codelib_dexfile);
_environments[id] = make_shared<CodeLibEnvironment>(_dex_file_env, codelib_dexfile, codelib, jclass_loader);
}
}
}
VLOG(artistd) << "ModuleManager: initialized " << _environments.size() << " codelib environments (" << _modules.size() << " modules)";
init_flag = true;
}
First traverse the _modules, for each registered module, find its corresponding codelib, and then register and declare its codelib's DEX file with _dex_file_env-> declare Codelib.
Compiler Driver after compile basically did not modify, but added two header files, codelib_environment.h and artist_log.h.