Differences between dex2oat and native dex2oat in ARTist

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.

Posted by aloysiusf on Sat, 09 Feb 2019 10:45:17 -0800