ART: Clean up ClassLinker

Try to clean up and simplify ClassLinker.

Move dex_lock to Locks. Remove dead code. Move single-use
code to user. Hide implementation details from header.

Test: m test-art-host
Change-Id: I58150fa9c2a9524f8304370270c2197d655cb3a8
diff --git a/runtime/mirror/dex_cache.cc b/runtime/mirror/dex_cache.cc
index a32d51f..741cf3b 100644
--- a/runtime/mirror/dex_cache.cc
+++ b/runtime/mirror/dex_cache.cc
@@ -22,15 +22,123 @@
 #include "gc/accounting/card_table-inl.h"
 #include "gc/heap.h"
 #include "globals.h"
+#include "linear_alloc.h"
 #include "object.h"
 #include "object-inl.h"
 #include "object_array-inl.h"
 #include "runtime.h"
 #include "string.h"
+#include "thread.h"
+#include "utils/dex_cache_arrays_layout-inl.h"
 
 namespace art {
 namespace mirror {
 
+void DexCache::InitializeDexCache(Thread* self,
+                                  ObjPtr<mirror::DexCache> dex_cache,
+                                  ObjPtr<mirror::String> location,
+                                  const DexFile* dex_file,
+                                  LinearAlloc* linear_alloc,
+                                  PointerSize image_pointer_size) {
+  DCHECK(dex_file != nullptr);
+  ScopedAssertNoThreadSuspension sants(__FUNCTION__);
+  DexCacheArraysLayout layout(image_pointer_size, dex_file);
+  uint8_t* raw_arrays = nullptr;
+
+  const OatDexFile* const oat_dex = dex_file->GetOatDexFile();
+  if (oat_dex != nullptr && oat_dex->GetDexCacheArrays() != nullptr) {
+    raw_arrays = oat_dex->GetDexCacheArrays();
+  } else if (dex_file->NumStringIds() != 0u ||
+             dex_file->NumTypeIds() != 0u ||
+             dex_file->NumMethodIds() != 0u ||
+             dex_file->NumFieldIds() != 0u) {
+    // Zero-initialized.
+    raw_arrays = reinterpret_cast<uint8_t*>(linear_alloc->Alloc(self, layout.Size()));
+  }
+
+  mirror::StringDexCacheType* strings = (dex_file->NumStringIds() == 0u) ? nullptr :
+      reinterpret_cast<mirror::StringDexCacheType*>(raw_arrays + layout.StringsOffset());
+  GcRoot<mirror::Class>* types = (dex_file->NumTypeIds() == 0u) ? nullptr :
+      reinterpret_cast<GcRoot<mirror::Class>*>(raw_arrays + layout.TypesOffset());
+  ArtMethod** methods = (dex_file->NumMethodIds() == 0u) ? nullptr :
+      reinterpret_cast<ArtMethod**>(raw_arrays + layout.MethodsOffset());
+  ArtField** fields = (dex_file->NumFieldIds() == 0u) ? nullptr :
+      reinterpret_cast<ArtField**>(raw_arrays + layout.FieldsOffset());
+
+  size_t num_strings = mirror::DexCache::kDexCacheStringCacheSize;
+  if (dex_file->NumStringIds() < num_strings) {
+    num_strings = dex_file->NumStringIds();
+  }
+
+  // Note that we allocate the method type dex caches regardless of this flag,
+  // and we make sure here that they're not used by the runtime. This is in the
+  // interest of simplicity and to avoid extensive compiler and layout class changes.
+  //
+  // If this needs to be mitigated in a production system running this code,
+  // DexCache::kDexCacheMethodTypeCacheSize can be set to zero.
+  mirror::MethodTypeDexCacheType* method_types = nullptr;
+  size_t num_method_types = 0;
+
+  if (dex_file->NumProtoIds() < mirror::DexCache::kDexCacheMethodTypeCacheSize) {
+    num_method_types = dex_file->NumProtoIds();
+  } else {
+    num_method_types = mirror::DexCache::kDexCacheMethodTypeCacheSize;
+  }
+
+  if (num_method_types > 0) {
+    method_types = reinterpret_cast<mirror::MethodTypeDexCacheType*>(
+        raw_arrays + layout.MethodTypesOffset());
+  }
+
+  DCHECK_ALIGNED(raw_arrays, alignof(mirror::StringDexCacheType)) <<
+                 "Expected raw_arrays to align to StringDexCacheType.";
+  DCHECK_ALIGNED(layout.StringsOffset(), alignof(mirror::StringDexCacheType)) <<
+                 "Expected StringsOffset() to align to StringDexCacheType.";
+  DCHECK_ALIGNED(strings, alignof(mirror::StringDexCacheType)) <<
+                 "Expected strings to align to StringDexCacheType.";
+  static_assert(alignof(mirror::StringDexCacheType) == 8u,
+                "Expected StringDexCacheType to have align of 8.");
+  if (kIsDebugBuild) {
+    // Sanity check to make sure all the dex cache arrays are empty. b/28992179
+    for (size_t i = 0; i < num_strings; ++i) {
+      CHECK_EQ(strings[i].load(std::memory_order_relaxed).index, 0u);
+      CHECK(strings[i].load(std::memory_order_relaxed).object.IsNull());
+    }
+    for (size_t i = 0; i < dex_file->NumTypeIds(); ++i) {
+      CHECK(types[i].IsNull());
+    }
+    for (size_t i = 0; i < dex_file->NumMethodIds(); ++i) {
+      CHECK(mirror::DexCache::GetElementPtrSize(methods, i, image_pointer_size) == nullptr);
+    }
+    for (size_t i = 0; i < dex_file->NumFieldIds(); ++i) {
+      CHECK(mirror::DexCache::GetElementPtrSize(fields, i, image_pointer_size) == nullptr);
+    }
+    for (size_t i = 0; i < num_method_types; ++i) {
+      CHECK_EQ(method_types[i].load(std::memory_order_relaxed).index, 0u);
+      CHECK(method_types[i].load(std::memory_order_relaxed).object.IsNull());
+    }
+  }
+  if (strings != nullptr) {
+    mirror::StringDexCachePair::Initialize(strings);
+  }
+  if (method_types != nullptr) {
+    mirror::MethodTypeDexCachePair::Initialize(method_types);
+  }
+  dex_cache->Init(dex_file,
+                  location,
+                  strings,
+                  num_strings,
+                  types,
+                  dex_file->NumTypeIds(),
+                  methods,
+                  dex_file->NumMethodIds(),
+                  fields,
+                  dex_file->NumFieldIds(),
+                  method_types,
+                  num_method_types,
+                  image_pointer_size);
+}
+
 void DexCache::Init(const DexFile* dex_file,
                     ObjPtr<String> location,
                     StringDexCacheType* strings,
diff --git a/runtime/mirror/dex_cache.h b/runtime/mirror/dex_cache.h
index cc4d01a..ec265e5 100644
--- a/runtime/mirror/dex_cache.h
+++ b/runtime/mirror/dex_cache.h
@@ -31,6 +31,8 @@
 class DexFile;
 class ImageWriter;
 union JValue;
+class LinearAlloc;
+class Thread;
 
 namespace mirror {
 
@@ -137,19 +139,14 @@
     return sizeof(DexCache);
   }
 
-  void Init(const DexFile* dex_file,
-            ObjPtr<String> location,
-            StringDexCacheType* strings,
-            uint32_t num_strings,
-            GcRoot<Class>* resolved_types,
-            uint32_t num_resolved_types,
-            ArtMethod** resolved_methods,
-            uint32_t num_resolved_methods,
-            ArtField** resolved_fields,
-            uint32_t num_resolved_fields,
-            MethodTypeDexCacheType* resolved_methodtypes,
-            uint32_t num_resolved_methodtypes,
-            PointerSize pointer_size) REQUIRES_SHARED(Locks::mutator_lock_);
+  static void InitializeDexCache(Thread* self,
+                                 ObjPtr<mirror::DexCache> dex_cache,
+                                 ObjPtr<mirror::String> location,
+                                 const DexFile* dex_file,
+                                 LinearAlloc* linear_alloc,
+                                 PointerSize image_pointer_size)
+      REQUIRES_SHARED(Locks::mutator_lock_)
+      REQUIRES(Locks::dex_lock_);
 
   void Fixup(ArtMethod* trampoline, PointerSize pointer_size)
       REQUIRES_SHARED(Locks::mutator_lock_);
@@ -339,6 +336,21 @@
   static void SetElementPtrSize(PtrType* ptr_array, size_t idx, PtrType ptr, PointerSize ptr_size);
 
  private:
+  void Init(const DexFile* dex_file,
+            ObjPtr<String> location,
+            StringDexCacheType* strings,
+            uint32_t num_strings,
+            GcRoot<Class>* resolved_types,
+            uint32_t num_resolved_types,
+            ArtMethod** resolved_methods,
+            uint32_t num_resolved_methods,
+            ArtField** resolved_fields,
+            uint32_t num_resolved_fields,
+            MethodTypeDexCacheType* resolved_methodtypes,
+            uint32_t num_resolved_methodtypes,
+            PointerSize pointer_size)
+      REQUIRES_SHARED(Locks::mutator_lock_);
+
   // Visit instance fields of the dex cache as well as its associated arrays.
   template <bool kVisitNativeRoots,
             VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,