Pass the classpath to dex2oat.

This makes it possible to run applications that have multiple
dex files on the classpath.

Change-Id: I15264a001a46ddb253e87f2739e6b9644348f1be
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 3341d88..505f86f 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -577,6 +577,8 @@
     execl(dex2oat.c_str(), dex2oat.c_str(),
           "--runtime-arg", "-Xms64m",
           "--runtime-arg", "-Xmx64m",
+          "--runtime-arg", "-classpath",
+          "--runtime-arg", Runtime::Current()->GetClassPath().c_str(),
           boot_image_option.c_str(),
           dex_file_option.c_str(),
           oat_file_option.c_str(),
@@ -2621,19 +2623,9 @@
     const char* descriptor = dex_file.StringByTypeIdx(type_idx);
     resolved = FindClass(descriptor, class_loader);
     if (resolved != NULL) {
-      Class* check = resolved;
-      while (check->IsArrayClass()) {
-        check = check->GetComponentType();
-      }
-      if (dex_cache != check->GetDexCache()) {
-        if (check->GetClassLoader() != NULL) {
-          Thread::Current()->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
-              "Class with type index %d resolved by unexpected .dex", type_idx);
-          resolved = NULL;
-        }
-      }
-    }
-    if (resolved != NULL) {
+      // TODO: we used to throw here if resolved's class loader was not the
+      //       boot class loader. This was to permit different classes with the
+      //       same name to be loaded simultaneously by different loaders
       dex_cache->SetResolvedType(type_idx, resolved);
     } else {
       DCHECK(Thread::Current()->IsExceptionPending());
diff --git a/src/compiler.cc b/src/compiler.cc
index 0a4117d..fabd8fd 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -82,13 +82,24 @@
   }
 }
 
-void Compiler::CompileAll(const ClassLoader* class_loader) {
+void Compiler::CompileAll(const ClassLoader* class_loader,
+    const std::vector<const DexFile*>& dex_files) {
   DCHECK(!Runtime::Current()->IsStarted());
-  Resolve(class_loader);
-  Verify(class_loader);
-  InitializeClassesWithoutClinit(class_loader);
-  Compile(class_loader);
-  SetCodeAndDirectMethods(class_loader);
+  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]);
+  }
 }
 
 void Compiler::CompileOne(const Method* method) {
diff --git a/src/compiler.h b/src/compiler.h
index c09e2c2..a8ea205 100644
--- a/src/compiler.h
+++ b/src/compiler.h
@@ -25,8 +25,8 @@
 
   ~Compiler();
 
-  // Compile all Methods of all the Classes of all the DexFiles that are part of a ClassLoader.
-  void CompileAll(const ClassLoader* class_loader);
+  void CompileAll(const ClassLoader* class_loader,
+                  const std::vector<const DexFile*>& class_path);
 
   // Compile a single Method
   void CompileOne(const Method* method);
diff --git a/src/compiler_test.cc b/src/compiler_test.cc
index d1b377a..823aa48 100644
--- a/src/compiler_test.cc
+++ b/src/compiler_test.cc
@@ -19,7 +19,7 @@
  protected:
 
   void CompileAll(const ClassLoader* class_loader) {
-    compiler_->CompileAll(class_loader);
+    compiler_->CompileAll(class_loader, ClassLoader::GetCompileTimeClassPath(class_loader));
     MakeAllExecutable(class_loader);
   }
 
diff --git a/src/dex2oat.cc b/src/dex2oat.cc
index 6cf6df6..231ca9c 100644
--- a/src/dex2oat.cc
+++ b/src/dex2oat.cc
@@ -94,6 +94,34 @@
   bool do_unlink_;
 };
 
+// Returns true if dex_files has a dex with the named location.
+bool DexFilesContains(const std::vector<const DexFile*>& dex_files, const std::string& location) {
+  for (size_t i = 0; i < dex_files.size(); ++i) {
+    if (dex_files[i]->GetLocation() == location) {
+      return true;
+    }
+  }
+  return false;
+}
+
+// Appends to dex_files any elements of class_path that it doesn't already
+// contain. This will open those dex files as necessary.
+void OpenClassPathFiles(const std::string& class_path, std::vector<const DexFile*>& dex_files) {
+  std::vector<std::string> parsed;
+  Split(class_path, ':', parsed);
+  for (size_t i = 0; i < parsed.size(); ++i) {
+    if (DexFilesContains(dex_files, parsed[i])) {
+      continue;
+    }
+    const DexFile* dex_file = DexFile::Open(parsed[i], Runtime::Current()->GetHostPrefix());
+    if (dex_file == NULL) {
+      LOG(WARNING) << "Failed to open dex file " << parsed[i];
+    } else {
+      dex_files.push_back(dex_file);
+    }
+  }
+}
+
 int dex2oat(int argc, char** argv) {
   // Skip over argv[0].
   argv++;
@@ -272,13 +300,17 @@
 
   // ClassLoader creation needs to come after Runtime::Create
   SirtRef<ClassLoader> class_loader(NULL);
+  std::vector<const DexFile*> dex_files;
   if (!boot_image_option.empty()) {
-    std::vector<const DexFile*> dex_files;
     DexFile::OpenDexFiles(dex_filenames, dex_files, host_prefix);
-    for (size_t i = 0; i < dex_files.size(); i++) {
-      class_linker->RegisterDexFile(*dex_files[i]);
+    std::vector<const DexFile*> class_path_files(dex_files);
+    OpenClassPathFiles(runtime->GetClassPath(), class_path_files);
+    for (size_t i = 0; i < class_path_files.size(); i++) {
+      class_linker->RegisterDexFile(*class_path_files[i]);
     }
-    class_loader.reset(PathClassLoader::AllocCompileTime(dex_files));
+    class_loader.reset(PathClassLoader::AllocCompileTime(class_path_files));
+  } else {
+    dex_files = runtime->GetClassLinker()->GetBootClassPath();
   }
 
   // if we loaded an existing image, we will reuse values from the image roots.
@@ -302,7 +334,7 @@
   }
   Compiler compiler(kThumb2, image_filename != NULL);
   if (method_names.empty()) {
-    compiler.CompileAll(class_loader.get());
+    compiler.CompileAll(class_loader.get(), dex_files);
   } else {
     for (size_t i = 0; i < method_names.size(); i++) {
       // names are actually class_descriptor + name + signature.
diff --git a/src/oat_test.cc b/src/oat_test.cc
index e3186de..17a00e4 100644
--- a/src/oat_test.cc
+++ b/src/oat_test.cc
@@ -11,11 +11,12 @@
 
 TEST_F(OatTest, WriteRead) {
   const bool compile = false;  // DISABLED_ due to the time to compile libcore
+  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
 
   SirtRef<ClassLoader> class_loader(NULL);
   if (compile) {
     compiler_.reset(new Compiler(kThumb2, false));
-    compiler_->CompileAll(class_loader.get());
+    compiler_->CompileAll(class_loader.get(), class_linker->GetBootClassPath());
   }
 
   ScratchFile tmp;
@@ -23,15 +24,13 @@
   ASSERT_TRUE(success);
 
   if (compile) {  // OatWriter strips the code, regenerate to compare
-    compiler_->CompileAll(class_loader.get());
+    compiler_->CompileAll(class_loader.get(), class_linker->GetBootClassPath());
   }
   UniquePtr<OatFile> oat_file(OatFile::Open(std::string(tmp.GetFilename()), "", NULL));
   ASSERT_TRUE(oat_file.get() != NULL);
   const OatHeader& oat_header = oat_file->GetOatHeader();
   ASSERT_EQ(1U, oat_header.GetDexFileCount());
 
-  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-
   const DexFile& dex_file = *java_lang_dex_file_.get();
   const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_file.GetLocation());
   for (size_t i = 0; i < dex_file.NumClassDefs(); i++) {