Simplify command line arguments

Change-Id: I9d6902b0c447fd8fbe5600fd36139791b2ceefb7
diff --git a/src/class_linker.cc b/src/class_linker.cc
index b4e332d..d3a6ed0 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -16,10 +16,12 @@
 #include "intern_table.h"
 #include "logging.h"
 #include "monitor.h"
+#include "oat_file.h"
 #include "object.h"
 #include "runtime.h"
 #include "ScopedLocalRef.h"
 #include "space.h"
+#include "stl_util.h"
 #include "thread.h"
 #include "UniquePtr.h"
 #include "utils.h"
@@ -177,17 +179,17 @@
   DISALLOW_COPY_AND_ASSIGN(ObjectLock);
 };
 
-ClassLinker* ClassLinker::Create(const std::vector<const DexFile*>& boot_class_path,
-                                 const std::vector<const DexFile*>& class_path,
-                                 InternTable* intern_table, bool image) {
+ClassLinker* ClassLinker::Create(const std::string& boot_class_path,
+                                 InternTable* intern_table) {
   CHECK_NE(boot_class_path.size(), 0U);
   UniquePtr<ClassLinker> class_linker(new ClassLinker(intern_table));
-  if (image) {
-    class_linker->InitFromImage(boot_class_path, class_path);
-  } else {
-    class_linker->Init(boot_class_path, class_path);
-  }
-  // TODO: check for failure during initialization
+  class_linker->Init(boot_class_path);
+  return class_linker.release();
+}
+
+ClassLinker* ClassLinker::Create(InternTable* intern_table) {
+  UniquePtr<ClassLinker> class_linker(new ClassLinker(intern_table));
+  class_linker->InitFromImage();
   return class_linker.release();
 }
 
@@ -201,8 +203,19 @@
   CHECK_EQ(arraysize(class_roots_descriptors_), size_t(kClassRootsMax));
 }
 
-void ClassLinker::Init(const std::vector<const DexFile*>& boot_class_path,
-                       const std::vector<const DexFile*>& class_path) {
+void CreateClassPath(const std::string& class_path,
+                     std::vector<const DexFile*>& class_path_vector) {
+  std::vector<std::string> parsed;
+  Split(class_path, ':', parsed);
+  for (size_t i = 0; i < parsed.size(); ++i) {
+    const DexFile* dex_file = DexFile::Open(parsed[i], Runtime::Current()->GetHostPrefix());
+    if (dex_file != NULL) {
+      class_path_vector.push_back(dex_file);
+    }
+  }
+}
+
+void ClassLinker::Init(const std::string& boot_class_path) {
   const Runtime* runtime = Runtime::Current();
   if (runtime->IsVerboseStartup()) {
     LOG(INFO) << "ClassLinker::InitFrom entering";
@@ -290,16 +303,13 @@
 
   // setup boot_class_path_ and register class_path now that we can
   // use AllocObjectArray to create DexCache instances
-  for (size_t i = 0; i != boot_class_path.size(); ++i) {
-    const DexFile* dex_file = boot_class_path[i];
+  std::vector<const DexFile*> boot_class_path_vector;
+  CreateClassPath(boot_class_path, boot_class_path_vector);
+  for (size_t i = 0; i != boot_class_path_vector.size(); ++i) {
+    const DexFile* dex_file = boot_class_path_vector[i];
     CHECK(dex_file != NULL);
     AppendToBootClassPath(*dex_file);
   }
-  for (size_t i = 0; i != class_path.size(); ++i) {
-    const DexFile* dex_file = class_path[i];
-    CHECK(dex_file != NULL);
-    RegisterDexFile(*dex_file);
-  }
 
   // Constructor, Field, and Method are necessary so that FindClass can link members
   Class* java_lang_reflect_Constructor = AllocClass(java_lang_Class, sizeof(MethodClass));
@@ -523,6 +533,36 @@
   }
 }
 
+OatFile* ClassLinker::OpenOat(const Space* space) {
+  const Runtime* runtime = Runtime::Current();
+  if (runtime->IsVerboseStartup()) {
+    LOG(INFO) << "ClassLinker::OpenOat entering";
+  }
+  const ImageHeader& image_header = space->GetImageHeader();
+  String* oat_location = image_header.GetImageRoot(ImageHeader::kOatLocation)->AsString();
+  std::string oat_filename;
+  oat_filename += runtime->GetHostPrefix();
+  oat_filename += oat_location->ToModifiedUtf8();
+  OatFile* oat_file = OatFile::Open(std::string(oat_filename), "", image_header.GetOatBaseAddr());
+  if (oat_file == NULL) {
+    LOG(ERROR) << "Failed to open oat file " << oat_filename << " referenced from image";
+    return NULL;
+  }
+  uint32_t oat_checksum = oat_file->GetOatHeader().GetChecksum();
+  uint32_t image_oat_checksum = image_header.GetOatChecksum();
+  if (oat_checksum != image_oat_checksum) {
+    LOG(ERROR) << "Failed to match oat filechecksum " << std::hex << oat_checksum
+               << " to expected oat checksum " << std::hex << oat_checksum
+               << " in image";
+    return NULL;
+  }
+  oat_files_.push_back(oat_file);
+  if (runtime->IsVerboseStartup()) {
+    LOG(INFO) << "ClassLinker::OpenOat exiting";
+  }
+  return oat_file;
+}
+
 struct ClassLinker::InitFromImageCallbackState {
   ClassLinker* class_linker;
 
@@ -530,19 +570,47 @@
 
   typedef std::tr1::unordered_map<std::string, ClassRoot> Table;
   Table descriptor_to_class_root;
-
-  typedef std::tr1::unordered_set<DexCache*, DexCacheHash> Set;
-  Set dex_caches;
 };
 
-void ClassLinker::InitFromImage(const std::vector<const DexFile*>& boot_class_path,
-                                const std::vector<const DexFile*>& class_path) {
+void ClassLinker::InitFromImage() {
   const Runtime* runtime = Runtime::Current();
   if (runtime->IsVerboseStartup()) {
     LOG(INFO) << "ClassLinker::InitFromImage entering";
   }
   CHECK(!init_done_);
 
+  const std::vector<Space*>& spaces = Heap::GetSpaces();
+  for (size_t i = 0; i < spaces.size(); i++) {
+    Space* space = spaces[i] ;
+    if (space->IsImageSpace()) {
+      OatFile* oat_file = OpenOat(space);
+      CHECK(oat_file != NULL) << "Failed to open oat file for image";
+      Object* dex_caches_object = space->GetImageHeader().GetImageRoot(ImageHeader::kDexCaches);
+      ObjectArray<DexCache>* dex_caches = dex_caches_object->AsObjectArray<DexCache>();
+
+      CHECK_EQ(oat_file->GetOatHeader().GetDexFileCount(),
+               static_cast<uint32_t>(dex_caches->GetLength()));
+      for (int i = 0; i < dex_caches->GetLength(); i++) {
+        DexCache* dex_cache = dex_caches->Get(i);
+        const std::string& dex_file_location = dex_cache->GetLocation()->ToModifiedUtf8();
+
+        std::string dex_filename;
+        dex_filename += runtime->GetHostPrefix();
+        dex_filename += dex_file_location;
+        const DexFile* dex_file = DexFile::Open(dex_filename, runtime->GetHostPrefix());
+        if (dex_file == NULL) {
+          LOG(FATAL) << "Failed to open dex file " << dex_filename
+                     << " referenced from oat file as " << dex_file_location;
+        }
+
+        const OatFile::OatDexFile& oat_dex_file = oat_file->GetOatDexFile(dex_file_location);
+        CHECK_EQ(dex_file->GetHeader().checksum_, oat_dex_file.GetDexFileChecksum());
+
+        RegisterDexFile(*dex_file, dex_cache);
+      }
+    }
+  }
+
   HeapBitmap* heap_bitmap = Heap::GetLiveBits();
   DCHECK(heap_bitmap != NULL);
 
@@ -568,36 +636,6 @@
   array_interfaces_ = GetClassRoot(kObjectArrayClass)->GetInterfaces();
   DCHECK(array_interfaces_ == GetClassRoot(kBooleanArrayClass)->GetInterfaces());
 
-  // build a map from location to DexCache to match up with DexFile::GetLocation
-  std::tr1::unordered_map<std::string, DexCache*> location_to_dex_cache;
-  typedef InitFromImageCallbackState::Set::const_iterator It;  // TODO: C++0x auto
-  for (It it = state.dex_caches.begin(), end = state.dex_caches.end(); it != end; ++it) {
-    DexCache* dex_cache = *it;
-    std::string location = dex_cache->GetLocation()->ToModifiedUtf8();
-    location_to_dex_cache[location] = dex_cache;
-  }
-  CHECK(boot_class_path.size() + class_path.size() == location_to_dex_cache.size())
-      << "(" << boot_class_path.size() << " + " << class_path.size()
-      << " != " << location_to_dex_cache.size() << ")";
-
-  // reinit boot_class_path with DexFile arguments and found DexCaches
-  for (size_t i = 0; i != boot_class_path.size(); ++i) {
-    const DexFile* dex_file = boot_class_path[i];
-    CHECK(dex_file != NULL);
-    DexCache* dex_cache = location_to_dex_cache[dex_file->GetLocation()];
-    CHECK(dex_cache != NULL) << dex_file->GetLocation();
-    AppendToBootClassPath(*dex_file, dex_cache);
-  }
-
-  // register class_path with DexFile arguments and found DexCaches
-  for (size_t i = 0; i != class_path.size(); ++i) {
-    const DexFile* dex_file = class_path[i];
-    CHECK(dex_file != NULL);
-    DexCache* dex_cache = location_to_dex_cache[dex_file->GetLocation()];
-    CHECK(dex_cache != NULL) << dex_file->GetLocation();
-    RegisterDexFile(*dex_file, dex_cache);
-  }
-
   String::SetClass(GetClassRoot(kJavaLangString));
   Field::SetClass(GetClassRoot(kJavaLangReflectField));
   Method::SetClasses(GetClassRoot(kJavaLangReflectConstructor), GetClassRoot(kJavaLangReflectMethod));
@@ -644,14 +682,6 @@
   // restore class to ClassLinker::classes_ table
   state->class_linker->InsertClass(descriptor, klass);
 
-  // note DexCache to match with DexFile later
-  DexCache* dex_cache = klass->GetDexCache();
-  if (dex_cache != NULL) {
-    state->dex_caches.insert(dex_cache);
-  } else {
-    DCHECK(klass->IsArrayClass() || klass->IsPrimitive());
-  }
-
   // check if this is a root, if so, register it
   typedef InitFromImageCallbackState::Table::const_iterator It;  // TODO: C++0x auto
   It it = state->descriptor_to_class_root.find(descriptor);
@@ -696,6 +726,8 @@
   ShortArray::ResetArrayClass();
   PathClassLoader::ResetClass();
   StackTraceElement::ResetClass();
+  STLDeleteElements(&boot_class_path_);
+  STLDeleteElements(&oat_files_);
 }
 
 DexCache* ClassLinker::AllocDexCache(const DexFile& dex_file) {