Store OatDexFile instead of OatFile in DexFile.

This requires moving OatDexFile out of the OatFile class so that
a forward class declaration can be used for OatDexFile.

Bug: 19071355
Change-Id: Ibda85b78d0577e9e81073090616fc0f2fa526be3
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index a89196d..a02d1ad 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -693,35 +693,6 @@
   return *oat_file;
 }
 
-const OatFile::OatDexFile* ClassLinker::FindOpenedOatDexFileForDexFile(const DexFile& dex_file) {
-  const char* dex_location = dex_file.GetLocation().c_str();
-  uint32_t dex_location_checksum = dex_file.GetLocationChecksum();
-  return FindOpenedOatDexFile(nullptr, dex_location, &dex_location_checksum);
-}
-
-const OatFile::OatDexFile* ClassLinker::FindOpenedOatDexFile(const char* oat_location,
-                                                             const char* dex_location,
-                                                             const uint32_t* dex_location_checksum) {
-  ReaderMutexLock mu(Thread::Current(), dex_lock_);
-  for (const OatFile* oat_file : oat_files_) {
-    DCHECK(oat_file != nullptr);
-
-    if (oat_location != nullptr) {
-      if (oat_file->GetLocation() != oat_location) {
-        continue;
-      }
-    }
-
-    const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_location,
-                                                                      dex_location_checksum,
-                                                                      false);
-    if (oat_dex_file != nullptr) {
-      return oat_dex_file;
-    }
-  }
-  return nullptr;
-}
-
 std::vector<std::unique_ptr<const DexFile>> ClassLinker::OpenDexFilesFromOat(
     const char* dex_location, const char* oat_location,
     std::vector<std::string>* error_msgs) {
@@ -1600,7 +1571,7 @@
 OatFile::OatClass ClassLinker::FindOatClass(const DexFile& dex_file, uint16_t class_def_idx,
                                             bool* found) {
   DCHECK_NE(class_def_idx, DexFile::kDexNoIndex16);
-  const OatFile::OatDexFile* oat_dex_file = FindOpenedOatDexFileForDexFile(dex_file);
+  const OatFile::OatDexFile* oat_dex_file = dex_file.GetOatDexFile();
   if (oat_dex_file == nullptr) {
     *found = false;
     return OatFile::OatClass::Invalid();
@@ -2813,7 +2784,7 @@
     }
   }
 
-  const OatFile::OatDexFile* oat_dex_file = FindOpenedOatDexFileForDexFile(dex_file);
+  const OatFile::OatDexFile* oat_dex_file = dex_file.GetOatDexFile();
   // In case we run without an image there won't be a backing oat file.
   if (oat_dex_file == nullptr) {
     return false;
@@ -3845,9 +3816,19 @@
     // Now comes the expensive part: things can be broken if (a) the klass' dex file has a
     // definition for the super-class, and (b) the files are in separate oat files. The oat files
     // are referenced from the dex file, so do (b) first. Only relevant if we have oat files.
-    const OatFile* class_oat_file = dex_file.GetOatFile();
+    const OatDexFile* class_oat_dex_file = dex_file.GetOatDexFile();
+    const OatFile* class_oat_file = nullptr;
+    if (class_oat_dex_file != nullptr) {
+      class_oat_file = class_oat_dex_file->GetOatFile();
+    }
+
     if (class_oat_file != nullptr) {
-      const OatFile* loaded_super_oat_file = super_class->GetDexFile().GetOatFile();
+      const OatDexFile* loaded_super_oat_dex_file = super_class->GetDexFile().GetOatDexFile();
+      const OatFile* loaded_super_oat_file = nullptr;
+      if (loaded_super_oat_dex_file != nullptr) {
+        loaded_super_oat_file = loaded_super_oat_dex_file->GetOatFile();
+      }
+
       if (loaded_super_oat_file != nullptr && class_oat_file != loaded_super_oat_file) {
         // Now check (a).
         const DexFile::ClassDef* super_class_def = dex_file.FindClassDef(class_def.superclass_idx_);
@@ -5293,9 +5274,8 @@
   if (m->IsPrivate()) {
     // The method can only be called inside its own oat file. Therefore it won't be called using
     // its direct code if the oat file has been compiled in PIC mode.
-    ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
     const DexFile& dex_file = m->GetDeclaringClass()->GetDexFile();
-    const OatFile::OatDexFile* oat_dex_file = class_linker->FindOpenedOatDexFileForDexFile(dex_file);
+    const OatFile::OatDexFile* oat_dex_file = dex_file.GetOatDexFile();
     if (oat_dex_file == nullptr) {
       // No oat file: the method has not been compiled.
       return false;
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index ec984cb..69a5337 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -600,17 +600,6 @@
   }
   mirror::DexCache* GetDexCache(size_t idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_, dex_lock_);
 
-  const OatFile::OatDexFile* FindOpenedOatDexFileForDexFile(const DexFile& dex_file)
-      LOCKS_EXCLUDED(dex_lock_)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
-  // Find an opened oat dex file that contains dex_location. If oat_location is not nullptr,
-  // the file must have that location, else any oat location is accepted.
-  const OatFile::OatDexFile* FindOpenedOatDexFile(const char* oat_location,
-                                                  const char* dex_location,
-                                                  const uint32_t* dex_location_checksum)
-      LOCKS_EXCLUDED(dex_lock_);
-
   const OatFile* FindOpenedOatFileFromOatLocation(const std::string& oat_location)
       LOCKS_EXCLUDED(dex_lock_);
 
@@ -739,8 +728,6 @@
   friend class ImageWriter;  // for GetClassRoots
   friend class ImageDumper;  // for FindOpenedOatFileFromOatLocation
   friend class JniCompilerTest;  // for GetRuntimeQuickGenericJniStub
-  friend class NoDex2OatTest;  // for FindOpenedOatFileForDexFile
-  friend class NoPatchoatTest;  // for FindOpenedOatFileForDexFile
   ART_FRIEND_TEST(mirror::DexCacheTest, Open);  // for AllocDexCache
 
   DISALLOW_COPY_AND_ASSIGN(ClassLinker);
diff --git a/runtime/dex_file.cc b/runtime/dex_file.cc
index edd8bfe..8685d8e 100644
--- a/runtime/dex_file.cc
+++ b/runtime/dex_file.cc
@@ -340,11 +340,11 @@
                                                    const std::string& location,
                                                    uint32_t location_checksum,
                                                    MemMap* mem_map,
-                                                   const OatFile* oat_file,
+                                                   const OatDexFile* oat_dex_file,
                                                    std::string* error_msg) {
   CHECK_ALIGNED(base, 4);  // various dex file structures must be word aligned
   std::unique_ptr<DexFile> dex_file(
-      new DexFile(base, size, location, location_checksum, mem_map, oat_file));
+      new DexFile(base, size, location, location_checksum, mem_map, oat_dex_file));
   if (!dex_file->Init(error_msg)) {
     dex_file.reset();
   }
@@ -355,7 +355,7 @@
                  const std::string& location,
                  uint32_t location_checksum,
                  MemMap* mem_map,
-                 const OatFile* oat_file)
+                 const OatDexFile* oat_dex_file)
     : begin_(base),
       size_(size),
       location_(location),
@@ -370,7 +370,7 @@
       class_defs_(reinterpret_cast<const ClassDef*>(base + header_->class_defs_off_)),
       find_class_def_misses_(0),
       class_def_index_(nullptr),
-      oat_file_(oat_file) {
+      oat_dex_file_(oat_dex_file) {
   CHECK(begin_ != NULL) << GetLocation();
   CHECK_GT(size_, 0U) << GetLocation();
 }
diff --git a/runtime/dex_file.h b/runtime/dex_file.h
index da39573..8e2d6c2 100644
--- a/runtime/dex_file.h
+++ b/runtime/dex_file.h
@@ -44,7 +44,7 @@
 }  // namespace mirror
 class ClassLinker;
 class MemMap;
-class OatFile;
+class OatDexFile;
 class Signature;
 template<class T> class Handle;
 class StringPiece;
@@ -392,9 +392,9 @@
   static std::unique_ptr<const DexFile> Open(const uint8_t* base, size_t size,
                                              const std::string& location,
                                              uint32_t location_checksum,
-                                             const OatFile* oat_file,
+                                             const OatDexFile* oat_dex_file,
                                              std::string* error_msg) {
-    return OpenMemory(base, size, location, location_checksum, NULL, oat_file, error_msg);
+    return OpenMemory(base, size, location, location_checksum, NULL, oat_dex_file, error_msg);
   }
 
   // Open all classesXXX.dex files from a zip archive.
@@ -904,8 +904,8 @@
   //     the dex_location where it's file name part has been made canonical.
   static std::string GetDexCanonicalLocation(const char* dex_location);
 
-  const OatFile* GetOatFile() const {
-    return oat_file_;
+  const OatDexFile* GetOatDexFile() const {
+    return oat_dex_file_;
   }
 
  private:
@@ -944,14 +944,14 @@
                                                    const std::string& location,
                                                    uint32_t location_checksum,
                                                    MemMap* mem_map,
-                                                   const OatFile* oat_file,
+                                                   const OatDexFile* oat_dex_file,
                                                    std::string* error_msg);
 
   DexFile(const uint8_t* base, size_t size,
           const std::string& location,
           uint32_t location_checksum,
           MemMap* mem_map,
-          const OatFile* oat_file);
+          const OatDexFile* oat_dex_file);
 
   // Top-level initializer that calls other Init methods.
   bool Init(std::string* error_msg);
@@ -1035,9 +1035,10 @@
   typedef HashMap<const char*, const ClassDef*, UTF16EmptyFn, UTF16HashCmp, UTF16HashCmp> Index;
   mutable Atomic<Index*> class_def_index_;
 
-  // The oat file this dex file was loaded from. May be null in case the dex file is not coming
-  // from an oat file, e.g., directly from an apk.
-  const OatFile* oat_file_;
+  // If this dex file was loaded from an oat file, oat_dex_file_ contains a
+  // pointer to the OatDexFile it was loaded from. Otherwise oat_dex_file_ is
+  // null.
+  const OatDexFile* oat_dex_file_;
 };
 
 struct DexFileReference {
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index 69cb22d..81703b1 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -453,7 +453,7 @@
 
 std::unique_ptr<const DexFile> OatFile::OatDexFile::OpenDexFile(std::string* error_msg) const {
   return DexFile::Open(dex_file_pointer_, FileSize(), dex_file_location_,
-                       dex_file_location_checksum_, GetOatFile(), error_msg);
+                       dex_file_location_checksum_, this, error_msg);
 }
 
 uint32_t OatFile::OatDexFile::GetOatClassOffset(uint16_t class_def_index) const {
@@ -495,12 +495,12 @@
     CHECK_LE(methods_pointer, oat_file_->End()) << oat_file_->GetLocation();
   }
 
-  return OatClass(oat_file_,
-                  status,
-                  type,
-                  bitmap_size,
-                  reinterpret_cast<const uint32_t*>(bitmap_pointer),
-                  reinterpret_cast<const OatMethodOffsets*>(methods_pointer));
+  return OatFile::OatClass(oat_file_,
+                           status,
+                           type,
+                           bitmap_size,
+                           reinterpret_cast<const uint32_t*>(bitmap_pointer),
+                           reinterpret_cast<const OatMethodOffsets*>(methods_pointer));
 }
 
 OatFile::OatClass::OatClass(const OatFile* oat_file,
diff --git a/runtime/oat_file.h b/runtime/oat_file.h
index 51952f3..2b9ef9d 100644
--- a/runtime/oat_file.h
+++ b/runtime/oat_file.h
@@ -37,9 +37,12 @@
 class MemMap;
 class OatMethodOffsets;
 class OatHeader;
+class OatDexFile;
 
-class OatFile {
+class OatFile FINAL {
  public:
+  typedef art::OatDexFile OatDexFile;
+
   // Opens an oat file contained within the given elf file. This is always opened as
   // non-executable at the moment.
   static OatFile* OpenWithElfFile(ElfFile* elf_file, const std::string& location,
@@ -90,9 +93,7 @@
 
   const OatHeader& GetOatHeader() const;
 
-  class OatDexFile;
-
-  class OatMethod {
+  class OatMethod FINAL {
    public:
     void LinkMethod(mirror::ArtMethod* method) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
@@ -156,7 +157,7 @@
     friend class OatClass;
   };
 
-  class OatClass {
+  class OatClass FINAL {
    public:
     mirror::Class::Status GetStatus() const {
       return status_;
@@ -207,63 +208,8 @@
 
     const OatMethodOffsets* const methods_pointer_;
 
-    friend class OatDexFile;
+    friend class art::OatDexFile;
   };
-
-  class OatDexFile {
-   public:
-    // Opens the DexFile referred to by this OatDexFile from within the containing OatFile.
-    std::unique_ptr<const DexFile> OpenDexFile(std::string* error_msg) const;
-
-    const OatFile* GetOatFile() const {
-      return oat_file_;
-    }
-
-    // Returns the size of the DexFile refered to by this OatDexFile.
-    size_t FileSize() const;
-
-    // Returns original path of DexFile that was the source of this OatDexFile.
-    const std::string& GetDexFileLocation() const {
-      return dex_file_location_;
-    }
-
-    // Returns the canonical location of DexFile that was the source of this OatDexFile.
-    const std::string& GetCanonicalDexFileLocation() const {
-      return canonical_dex_file_location_;
-    }
-
-    // Returns checksum of original DexFile that was the source of this OatDexFile;
-    uint32_t GetDexFileLocationChecksum() const {
-      return dex_file_location_checksum_;
-    }
-
-    // Returns the OatClass for the class specified by the given DexFile class_def_index.
-    OatClass GetOatClass(uint16_t class_def_index) const;
-
-    // Returns the offset to the OatClass information. Most callers should use GetOatClass.
-    uint32_t GetOatClassOffset(uint16_t class_def_index) const;
-
-    ~OatDexFile();
-
-   private:
-    OatDexFile(const OatFile* oat_file,
-               const std::string& dex_file_location,
-               const std::string& canonical_dex_file_location,
-               uint32_t dex_file_checksum,
-               const uint8_t* dex_file_pointer,
-               const uint32_t* oat_class_offsets_pointer);
-
-    const OatFile* const oat_file_;
-    const std::string dex_file_location_;
-    const std::string canonical_dex_file_location_;
-    const uint32_t dex_file_location_checksum_;
-    const uint8_t* const dex_file_pointer_;
-    const uint32_t* const oat_class_offsets_pointer_;
-
-    friend class OatFile;
-    DISALLOW_COPY_AND_ASSIGN(OatDexFile);
-  };
-
   const OatDexFile* GetOatDexFile(const char* dex_location,
                                   const uint32_t* const dex_location_checksum,
                                   bool exception_if_not_found = true) const
@@ -382,11 +328,69 @@
   mutable std::list<std::string> string_cache_ GUARDED_BY(secondary_lookup_lock_);
 
   friend class OatClass;
-  friend class OatDexFile;
+  friend class art::OatDexFile;
   friend class OatDumper;  // For GetBase and GetLimit
   DISALLOW_COPY_AND_ASSIGN(OatFile);
 };
 
+// OatDexFile should be an inner class of OatFile. Unfortunately, C++ doesn't
+// support forward declarations of inner classes, and we want to
+// forward-declare OatDexFile so that we can store an opaque pointer to an
+// OatDexFile in DexFile.
+class OatDexFile FINAL {
+ public:
+  // Opens the DexFile referred to by this OatDexFile from within the containing OatFile.
+  std::unique_ptr<const DexFile> OpenDexFile(std::string* error_msg) const;
+
+  const OatFile* GetOatFile() const {
+    return oat_file_;
+  }
+
+  // Returns the size of the DexFile refered to by this OatDexFile.
+  size_t FileSize() const;
+
+  // Returns original path of DexFile that was the source of this OatDexFile.
+  const std::string& GetDexFileLocation() const {
+    return dex_file_location_;
+  }
+
+  // Returns the canonical location of DexFile that was the source of this OatDexFile.
+  const std::string& GetCanonicalDexFileLocation() const {
+    return canonical_dex_file_location_;
+  }
+
+  // Returns checksum of original DexFile that was the source of this OatDexFile;
+  uint32_t GetDexFileLocationChecksum() const {
+    return dex_file_location_checksum_;
+  }
+
+  // Returns the OatClass for the class specified by the given DexFile class_def_index.
+  OatFile::OatClass GetOatClass(uint16_t class_def_index) const;
+
+  // Returns the offset to the OatClass information. Most callers should use GetOatClass.
+  uint32_t GetOatClassOffset(uint16_t class_def_index) const;
+
+  ~OatDexFile();
+
+ private:
+  OatDexFile(const OatFile* oat_file,
+             const std::string& dex_file_location,
+             const std::string& canonical_dex_file_location,
+             uint32_t dex_file_checksum,
+             const uint8_t* dex_file_pointer,
+             const uint32_t* oat_class_offsets_pointer);
+
+  const OatFile* const oat_file_;
+  const std::string dex_file_location_;
+  const std::string canonical_dex_file_location_;
+  const uint32_t dex_file_location_checksum_;
+  const uint8_t* const dex_file_pointer_;
+  const uint32_t* const oat_class_offsets_pointer_;
+
+  friend class OatFile;
+  DISALLOW_COPY_AND_ASSIGN(OatDexFile);
+};
+
 }  // namespace art
 
 #endif  // ART_RUNTIME_OAT_FILE_H_
diff --git a/runtime/oat_file_assistant_test.cc b/runtime/oat_file_assistant_test.cc
index a8b0876..a198824 100644
--- a/runtime/oat_file_assistant_test.cc
+++ b/runtime/oat_file_assistant_test.cc
@@ -787,7 +787,8 @@
     std::vector<std::string> error_msgs;
     dex_files = linker->OpenDexFilesFromOat(dex_location_.c_str(), oat_location_.c_str(), &error_msgs);
     CHECK(!dex_files.empty()) << Join(error_msgs, '\n');
-    loaded_oat_file_ = dex_files[0]->GetOatFile();
+    CHECK(dex_files[0]->GetOatDexFile() != nullptr) << dex_files[0]->GetLocation();
+    loaded_oat_file_ = dex_files[0]->GetOatDexFile()->GetOatFile();
   }
 
   const OatFile* GetLoadedOatFile() const {
diff --git a/test/116-nodex2oat/nodex2oat.cc b/test/116-nodex2oat/nodex2oat.cc
index 564d58d2..131af31 100644
--- a/test/116-nodex2oat/nodex2oat.cc
+++ b/test/116-nodex2oat/nodex2oat.cc
@@ -28,8 +28,7 @@
     ScopedObjectAccess soa(Thread::Current());
     mirror::Class* klass = soa.Decode<mirror::Class*>(cls);
     const DexFile& dex_file = klass->GetDexFile();
-    const OatFile::OatDexFile* oat_dex_file =
-        Runtime::Current()->GetClassLinker()->FindOpenedOatDexFileForDexFile(dex_file);
+    const OatFile::OatDexFile* oat_dex_file = dex_file.GetOatDexFile();
     return oat_dex_file != nullptr;
   }
 };
diff --git a/test/117-nopatchoat/nopatchoat.cc b/test/117-nopatchoat/nopatchoat.cc
index da276f2..7eac412 100644
--- a/test/117-nopatchoat/nopatchoat.cc
+++ b/test/117-nopatchoat/nopatchoat.cc
@@ -28,11 +28,7 @@
     ScopedObjectAccess soa(Thread::Current());
     mirror::Class* klass = soa.Decode<mirror::Class*>(cls);
     const DexFile& dex_file = klass->GetDexFile();
-
-    const OatFile::OatDexFile* oat_dex_file =
-        Runtime::Current()->GetClassLinker()->FindOpenedOatDexFileForDexFile(dex_file);
-
-    return oat_dex_file;
+    return dex_file.GetOatDexFile();
   }
 
   static bool hasExecutableOat(jclass cls) {
diff --git a/test/118-noimage-dex2oat/noimage-dex2oat.cc b/test/118-noimage-dex2oat/noimage-dex2oat.cc
index c49a13e..aacf00f 100644
--- a/test/118-noimage-dex2oat/noimage-dex2oat.cc
+++ b/test/118-noimage-dex2oat/noimage-dex2oat.cc
@@ -28,8 +28,7 @@
     ScopedObjectAccess soa(Thread::Current());
     mirror::Class* klass = soa.Decode<mirror::Class*>(cls);
     const DexFile& dex_file = klass->GetDexFile();
-    const OatFile::OatDexFile* oat_dex_file =
-        Runtime::Current()->GetClassLinker()->FindOpenedOatDexFileForDexFile(dex_file);
+    const OatFile::OatDexFile* oat_dex_file = dex_file.GetOatDexFile();
     return oat_dex_file != nullptr;
   }
 };