Add --image-classes to dex2oat

Change-Id: Ia88f9d302e0f9cd72be2199ee46d212d99864c67
diff --git a/src/compiler.cc b/src/compiler.cc
index a3655c6..fba767d 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -35,12 +35,18 @@
   ByteArray* CreateJniDlysmLookupStub();
 }
 
-Compiler::Compiler(InstructionSet instruction_set, bool image)
+Compiler::Compiler(InstructionSet instruction_set,
+                   bool image,
+                   const std::set<std::string>* image_classes)
     : instruction_set_(instruction_set),
       jni_compiler_(instruction_set),
       image_(image),
+      image_classes_(image_classes),
       verbose_(false) {
   CHECK(!Runtime::Current()->IsStarted());
+  if (!image_) {
+    CHECK(image_classes_ == NULL);
+  }
 }
 
 Compiler::~Compiler() {
@@ -83,50 +89,62 @@
 }
 
 void Compiler::CompileAll(const ClassLoader* class_loader,
-    const std::vector<const DexFile*>& dex_files) {
+                          const std::vector<const DexFile*>& dex_files) {
   DCHECK(!Runtime::Current()->IsStarted());
-  for (size_t i = 0; i != dex_files.size(); ++i) {
-    ResolveDexFile(class_loader, *dex_files[i]);
-  }
-  for (size_t i = 0; i != dex_files.size(); ++i) {
-    VerifyDexFile(class_loader, *dex_files[i]);
-  }
-  for (size_t i = 0; i != dex_files.size(); ++i) {
-    InitializeClassesWithoutClinit(class_loader, *dex_files[i]);
-  }
-  for (size_t i = 0; i != dex_files.size(); ++i) {
-    CompileDexFile(class_loader, *dex_files[i]);
-  }
-  for (size_t i = 0; i != dex_files.size(); ++i) {
-    SetCodeAndDirectMethodsDexFile(*dex_files[i]);
-  }
+
+  PreCompile(class_loader, dex_files);
+  Compile(class_loader, dex_files);
+  PostCompile(class_loader, dex_files);
 }
 
 void Compiler::CompileOne(const Method* method) {
   DCHECK(!Runtime::Current()->IsStarted());
+
   const ClassLoader* class_loader = method->GetDeclaringClass()->GetClassLoader();
-  Resolve(class_loader);
-  Verify(class_loader);
-  InitializeClassesWithoutClinit(class_loader);
+
   // Find the dex_file
   const DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
   const DexFile& dex_file = Runtime::Current()->GetClassLinker()->FindDexFile(dex_cache);
+  std::vector<const DexFile*> dex_files;
+  dex_files.push_back(&dex_file);
+
+  PreCompile(class_loader, dex_files);
+
   uint32_t method_idx = method->GetDexMethodIndex();
   const DexFile::CodeItem* code_item = dex_file.GetCodeItem(method->GetCodeItemOffset());
   CompileMethod(code_item, method->GetAccessFlags(), method_idx, class_loader, dex_file);
-  SetCodeAndDirectMethods(class_loader);
+
+  PostCompile(class_loader, dex_files);
 }
 
-void Compiler::Resolve(const ClassLoader* class_loader) {
-  const std::vector<const DexFile*>& class_path
-      = ClassLoader::GetCompileTimeClassPath(class_loader);
-  for (size_t i = 0; i != class_path.size(); ++i) {
-    const DexFile* dex_file = class_path[i];
+void Compiler::Resolve(const ClassLoader* class_loader,
+                       const std::vector<const DexFile*>& dex_files) {
+  for (size_t i = 0; i != dex_files.size(); ++i) {
+    const DexFile* dex_file = dex_files[i];
     CHECK(dex_file != NULL);
     ResolveDexFile(class_loader, *dex_file);
   }
 }
 
+void Compiler::PreCompile(const ClassLoader* class_loader,
+                          const std::vector<const DexFile*>& dex_files) {
+  Resolve(class_loader, dex_files);
+  Verify(class_loader, dex_files);
+  InitializeClassesWithoutClinit(class_loader, dex_files);
+}
+
+void Compiler::PostCompile(const ClassLoader* class_loader,
+                           const std::vector<const DexFile*>& dex_files) {
+  SetCodeAndDirectMethods(dex_files);
+}
+
+bool Compiler::IsImageClass(const std::string& descriptor) const {
+  if (image_classes_ == NULL) {
+    return true;
+  }
+  return image_classes_->find(descriptor) != image_classes_->end();
+}
+
 // Return true if the class should be skipped during compilation. We
 // never skip classes in the boot class loader. However, if we have a
 // non-boot class loader and we can resolve the class in the boot
@@ -157,8 +175,10 @@
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
   DexCache* dex_cache = class_linker->FindDexCache(dex_file);
 
-  // Strings are easy, they always are simply resolved to literals in the same file
-  if (IsImage()) {  // Only resolve when we'll have an image, so compiler won't choose fast path
+  // Strings are easy in that they always are simply resolved to literals in the same file
+  if (image_ && image_classes_ == NULL) {
+    // TODO: Add support for loading strings referenced by image_classes_
+    // See also Compiler::CanAssumeTypeIsPresentInDexCache.
     for (size_t string_idx = 0; string_idx < dex_cache->NumStrings(); string_idx++) {
       class_linker->ResolveString(dex_file, string_idx, dex_cache);
     }
@@ -235,11 +255,10 @@
   }
 }
 
-void Compiler::Verify(const ClassLoader* class_loader) {
-  const std::vector<const DexFile*>& class_path
-      = ClassLoader::GetCompileTimeClassPath(class_loader);
-  for (size_t i = 0; i != class_path.size(); ++i) {
-    const DexFile* dex_file = class_path[i];
+void Compiler::Verify(const ClassLoader* class_loader,
+                      const std::vector<const DexFile*>& dex_files) {
+  for (size_t i = 0; i != dex_files.size(); ++i) {
+    const DexFile* dex_file = dex_files[i];
     CHECK(dex_file != NULL);
     VerifyDexFile(class_loader, *dex_file);
   }
@@ -275,11 +294,10 @@
   dex_file.ChangePermissions(PROT_READ);
 }
 
-void Compiler::InitializeClassesWithoutClinit(const ClassLoader* class_loader) {
-  const std::vector<const DexFile*>& class_path
-      = ClassLoader::GetCompileTimeClassPath(class_loader);
-  for (size_t i = 0; i != class_path.size(); ++i) {
-    const DexFile* dex_file = class_path[i];
+void Compiler::InitializeClassesWithoutClinit(const ClassLoader* class_loader,
+                                              const std::vector<const DexFile*>& dex_files) {
+  for (size_t i = 0; i != dex_files.size(); ++i) {
+    const DexFile* dex_file = dex_files[i];
     CHECK(dex_file != NULL);
     InitializeClassesWithoutClinit(class_loader, *dex_file);
   }
@@ -309,11 +327,10 @@
   }
 }
 
-void Compiler::Compile(const ClassLoader* class_loader) {
-  const std::vector<const DexFile*>& class_path
-      = ClassLoader::GetCompileTimeClassPath(class_loader);
-  for (size_t i = 0; i != class_path.size(); ++i) {
-    const DexFile* dex_file = class_path[i];
+void Compiler::Compile(const ClassLoader* class_loader,
+                       const std::vector<const DexFile*>& dex_files) {
+  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);
   }
@@ -410,7 +427,7 @@
 }
 
 const CompiledInvokeStub* Compiler::FindInvokeStub(bool is_static, const char* shorty) const {
-  std::string key = MakeInvokeStubKey(is_static, shorty);
+  const std::string key = MakeInvokeStubKey(is_static, shorty);
   InvokeStubTable::const_iterator it = compiled_invoke_stubs_.find(key);
   if (it == compiled_invoke_stubs_.end()) {
     return NULL;
@@ -435,11 +452,9 @@
   return it->second;
 }
 
-void Compiler::SetCodeAndDirectMethods(const ClassLoader* class_loader) {
-  const std::vector<const DexFile*>& class_path
-      = ClassLoader::GetCompileTimeClassPath(class_loader);
-  for (size_t i = 0; i != class_path.size(); ++i) {
-    const DexFile* dex_file = class_path[i];
+void Compiler::SetCodeAndDirectMethods(const std::vector<const DexFile*>& dex_files) {
+  for (size_t i = 0; i != dex_files.size(); ++i) {
+    const DexFile* dex_file = dex_files[i];
     CHECK(dex_file != NULL);
     SetCodeAndDirectMethodsDexFile(*dex_file);
   }