Merge "ART: Add boot classpath check for initialization"
diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc
index f9173f5..bde00cf 100644
--- a/compiler/oat_writer.cc
+++ b/compiler/oat_writer.cc
@@ -260,16 +260,7 @@
   // Data to write to a separate section.
   dchecked_vector<uint32_t> class_offsets_;
 
-  void InitTypeLookupTable(const DexFile& dex_file, uint8_t* storage) const {
-    lookup_table_.reset(TypeLookupTable::Create(dex_file, storage));
-  }
-
-  TypeLookupTable* GetTypeLookupTable() const {
-    return lookup_table_.get();
-  }
-
  private:
-  mutable std::unique_ptr<TypeLookupTable> lookup_table_;
   size_t GetClassOffsetsRawSize() const {
     return class_offsets_.size() * sizeof(class_offsets_[0]);
   }
@@ -2481,8 +2472,15 @@
 
     // Create the lookup table. When `nullptr` is given as the storage buffer,
     // TypeLookupTable allocates its own and OatDexFile takes ownership.
-    oat_dex_file->InitTypeLookupTable(*opened_dex_files[i], /* storage */ nullptr);
-    TypeLookupTable* table = oat_dex_file->GetTypeLookupTable();
+    const DexFile& dex_file = *opened_dex_files[i];
+    {
+      std::unique_ptr<TypeLookupTable> type_lookup_table =
+          TypeLookupTable::Create(dex_file, /* storage */ nullptr);
+      type_lookup_table_oat_dex_files_.push_back(
+          std::make_unique<art::OatDexFile>(std::move(type_lookup_table)));
+      dex_file.SetOatDexFile(type_lookup_table_oat_dex_files_.back().get());
+    }
+    TypeLookupTable* const table = type_lookup_table_oat_dex_files_.back()->GetTypeLookupTable();
 
     // Type tables are required to be 4 byte aligned.
     size_t initial_offset = oat_size_;
diff --git a/compiler/oat_writer.h b/compiler/oat_writer.h
index 3d08ad3..b92ba76 100644
--- a/compiler/oat_writer.h
+++ b/compiler/oat_writer.h
@@ -363,6 +363,9 @@
   // Offset of the oat data from the start of the mmapped region of the elf file.
   size_t oat_data_offset_;
 
+  // Fake OatDexFiles to hold type lookup tables for the compiler.
+  std::vector<std::unique_ptr<art::OatDexFile>> type_lookup_table_oat_dex_files_;
+
   // data to write
   std::unique_ptr<OatHeader> oat_header_;
   dchecked_vector<OatDexFile> oat_dex_files_;
diff --git a/runtime/art_method.cc b/runtime/art_method.cc
index c550a1b..17c5959 100644
--- a/runtime/art_method.cc
+++ b/runtime/art_method.cc
@@ -476,7 +476,11 @@
     }
     // The table is in the .vdex file.
     const OatFile::OatDexFile* oat_dex_file = GetDexCache()->GetDexFile()->GetOatDexFile();
-    return oat_dex_file->GetOatFile()->DexBegin() + header->vmap_table_offset_;
+    const OatFile* oat_file = oat_dex_file->GetOatFile();
+    if (oat_file == nullptr) {
+      return nullptr;
+    }
+    return oat_file->DexBegin() + header->vmap_table_offset_;
   } else {
     return oat_method.GetVmapTable();
   }
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 311d7d7..1338cc9 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -4006,7 +4006,7 @@
 
   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) {
+  if (oat_dex_file == nullptr || oat_dex_file->GetOatFile() == nullptr) {
     return false;
   }
 
diff --git a/runtime/class_table.cc b/runtime/class_table.cc
index b44104e..0fcce6b 100644
--- a/runtime/class_table.cc
+++ b/runtime/class_table.cc
@@ -170,7 +170,7 @@
     const DexFile* dex_file = ObjPtr<mirror::DexCache>::DownCast(obj)->GetDexFile();
     if (dex_file != nullptr && dex_file->GetOatDexFile() != nullptr) {
       const OatFile* oat_file = dex_file->GetOatDexFile()->GetOatFile();
-      if (!oat_file->GetBssGcRoots().empty()) {
+      if (oat_file != nullptr && !oat_file->GetBssGcRoots().empty()) {
         InsertOatFileLocked(oat_file);  // Ignore return value.
       }
     }
diff --git a/runtime/dex_file.h b/runtime/dex_file.h
index da9fa50..bd236f6 100644
--- a/runtime/dex_file.h
+++ b/runtime/dex_file.h
@@ -1010,6 +1010,11 @@
     return oat_dex_file_;
   }
 
+  // Used by oat writer.
+  void SetOatDexFile(OatDexFile* oat_dex_file) const {
+    oat_dex_file_ = oat_dex_file;
+  }
+
   // Utility methods for reading integral values from a buffer.
   static int32_t ReadSignedInt(const uint8_t* ptr, int zwidth);
   static uint32_t ReadUnsignedInt(const uint8_t* ptr, int zwidth, bool fill_on_right);
@@ -1138,9 +1143,10 @@
   // 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_;
+  mutable const OatDexFile* oat_dex_file_;
 
   friend class DexFileVerifierTest;
+  friend class OatWriter;
   ART_FRIEND_TEST(ClassLinkerTest, RegisterDexFileName);  // for constructor
 };
 
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index c14b616..61979c7 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -1252,13 +1252,14 @@
     if (lookup_table_data_ + TypeLookupTable::RawDataLength(num_class_defs) > GetOatFile()->End()) {
       LOG(WARNING) << "found truncated lookup table in " << dex_file_location_;
     } else {
-      lookup_table_.reset(TypeLookupTable::Open(dex_file_pointer_,
-                                                lookup_table_data_,
-                                                num_class_defs));
+      lookup_table_ = TypeLookupTable::Open(dex_file_pointer_, lookup_table_data_, num_class_defs);
     }
   }
 }
 
+OatFile::OatDexFile::OatDexFile(std::unique_ptr<TypeLookupTable>&& lookup_table)
+    : lookup_table_(std::move(lookup_table)) {}
+
 OatFile::OatDexFile::~OatDexFile() {}
 
 size_t OatFile::OatDexFile::FileSize() const {
@@ -1540,7 +1541,7 @@
                                         bool* found) {
   DCHECK_NE(class_def_idx, DexFile::kDexNoIndex16);
   const OatFile::OatDexFile* oat_dex_file = dex_file.GetOatDexFile();
-  if (oat_dex_file == nullptr) {
+  if (oat_dex_file == nullptr || oat_dex_file->GetOatFile() == nullptr) {
     *found = false;
     return OatFile::OatClass::Invalid();
   }
@@ -1548,4 +1549,8 @@
   return oat_dex_file->GetOatClass(class_def_idx);
 }
 
+void OatFile::OatDexFile::AssertAotCompiler() {
+  CHECK(Runtime::Current()->IsAotCompiler());
+}
+
 }  // namespace art
diff --git a/runtime/oat_file.h b/runtime/oat_file.h
index 63a0e14..29add5b 100644
--- a/runtime/oat_file.h
+++ b/runtime/oat_file.h
@@ -384,7 +384,13 @@
   // Opens the DexFile referred to by this OatDexFile from within the containing OatFile.
   std::unique_ptr<const DexFile> OpenDexFile(std::string* error_msg) const;
 
+  // May return null if the OatDexFile only contains a type lookup table. This case only happens
+  // for the compiler to speed up compilation.
   const OatFile* GetOatFile() const {
+    // Avoid pulling in runtime.h in the header file.
+    if (kIsDebugBuild && oat_file_ == nullptr) {
+      AssertAotCompiler();
+    }
     return oat_file_;
   }
 
@@ -436,6 +442,9 @@
 
   ~OatDexFile();
 
+  // Create only with a type lookup table, used by the compiler to speed up compilation.
+  explicit OatDexFile(std::unique_ptr<TypeLookupTable>&& lookup_table);
+
  private:
   OatDexFile(const OatFile* oat_file,
              const std::string& dex_file_location,
@@ -446,14 +455,16 @@
              const uint32_t* oat_class_offsets_pointer,
              uint8_t* dex_cache_arrays);
 
-  const OatFile* const oat_file_;
+  static void AssertAotCompiler();
+
+  const OatFile* const oat_file_ = nullptr;
   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 uint8_t* lookup_table_data_;
-  const uint32_t* const oat_class_offsets_pointer_;
-  uint8_t* const dex_cache_arrays_;
+  const uint32_t dex_file_location_checksum_ = 0u;
+  const uint8_t* const dex_file_pointer_ = nullptr;
+  const uint8_t* lookup_table_data_ = nullptr;
+  const uint32_t* const oat_class_offsets_pointer_ = 0u;
+  uint8_t* const dex_cache_arrays_ = nullptr;
   mutable std::unique_ptr<TypeLookupTable> lookup_table_;
 
   friend class OatFile;
diff --git a/runtime/type_lookup_table.cc b/runtime/type_lookup_table.cc
index 56e9262..16cd722 100644
--- a/runtime/type_lookup_table.cc
+++ b/runtime/type_lookup_table.cc
@@ -50,17 +50,19 @@
   return num_class_defs != 0u && num_class_defs <= std::numeric_limits<uint16_t>::max();
 }
 
-TypeLookupTable* TypeLookupTable::Create(const DexFile& dex_file, uint8_t* storage) {
+std::unique_ptr<TypeLookupTable> TypeLookupTable::Create(const DexFile& dex_file,
+                                                         uint8_t* storage) {
   const uint32_t num_class_defs = dex_file.NumClassDefs();
-  return SupportedSize(num_class_defs)
+  return std::unique_ptr<TypeLookupTable>(SupportedSize(num_class_defs)
       ? new TypeLookupTable(dex_file, storage)
-      : nullptr;
+      : nullptr);
 }
 
-TypeLookupTable* TypeLookupTable::Open(const uint8_t* dex_file_pointer,
-                                       const uint8_t* raw_data,
-                                       uint32_t num_class_defs) {
-  return new TypeLookupTable(dex_file_pointer, raw_data, num_class_defs);
+std::unique_ptr<TypeLookupTable> TypeLookupTable::Open(const uint8_t* dex_file_pointer,
+                                                       const uint8_t* raw_data,
+                                                       uint32_t num_class_defs) {
+  return std::unique_ptr<TypeLookupTable>(
+      new TypeLookupTable(dex_file_pointer, raw_data, num_class_defs));
 }
 
 TypeLookupTable::TypeLookupTable(const DexFile& dex_file, uint8_t* storage)
diff --git a/runtime/type_lookup_table.h b/runtime/type_lookup_table.h
index 9595743..3f6f76f 100644
--- a/runtime/type_lookup_table.h
+++ b/runtime/type_lookup_table.h
@@ -60,13 +60,14 @@
   }
 
   // Method creates lookup table for dex file
-  static TypeLookupTable* Create(const DexFile& dex_file, uint8_t* storage = nullptr);
+  static std::unique_ptr<TypeLookupTable> Create(const DexFile& dex_file,
+                                                 uint8_t* storage = nullptr);
 
   // Method opens lookup table from binary data. Lookups will traverse strings and other
   // data contained in dex_file as well.  Lookup table does not own raw_data or dex_file.
-  static TypeLookupTable* Open(const uint8_t* dex_file_pointer,
-                               const uint8_t* raw_data,
-                               uint32_t num_class_defs);
+  static std::unique_ptr<TypeLookupTable> Open(const uint8_t* dex_file_pointer,
+                                               const uint8_t* raw_data,
+                                               uint32_t num_class_defs);
 
   // Method returns pointer to binary data of lookup table. Used by the oat writer.
   const uint8_t* RawData() const {