Avoid handle-less fields in ClassLinker::InitializeClass()

There were some handle-less fields in a SafeMap across GC points.

Bug: 12687968
Change-Id: Ib8c6527d4e23031f1d0074fa11d8f85499b68340
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 8fc1d07..74c5c15 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -3843,7 +3843,7 @@
     const DexFile::ClassDef* dex_class_def = klass->GetClassDef();
     CHECK(dex_class_def != NULL);
     const DexFile& dex_file = klass->GetDexFile();
-    StackHandleScope<2> hs(self);
+    StackHandleScope<3> hs(self);
     Handle<mirror::ClassLoader> class_loader(hs.NewHandle(klass->GetClassLoader()));
     Handle<mirror::DexCache> dex_cache(hs.NewHandle(klass->GetDexCache()));
     EncodedStaticFieldValueIterator it(dex_file, &dex_cache, &class_loader,
@@ -3852,13 +3852,16 @@
       CHECK(can_init_statics);
       // We reordered the fields, so we need to be able to map the
       // field indexes to the right fields.
-      SafeMap<uint32_t, mirror::ArtField*> field_map;
-      ConstructFieldMap(dex_file, *dex_class_def, klass.Get(), field_map);
+      Handle<mirror::ObjectArray<mirror::ArtField>>
+          field_array(hs.NewHandle(AllocArtFieldArray(self, klass->NumStaticFields())));
+      ConstructFieldArray(dex_file, *dex_class_def, klass.Get(), field_array);
       for (size_t i = 0; it.HasNext(); i++, it.Next()) {
+        StackHandleScope<1> hs(self);
+        Handle<mirror::ArtField> field(hs.NewHandle(field_array->Get(i)));
         if (Runtime::Current()->IsActiveTransaction()) {
-          it.ReadValueToField<true>(field_map.Get(i));
+          it.ReadValueToField<true>(field);
         } else {
-          it.ReadValueToField<false>(field_map.Get(i));
+          it.ReadValueToField<false>(field);
         }
       }
     }
@@ -3997,17 +4000,20 @@
   return success;
 }
 
-void ClassLinker::ConstructFieldMap(const DexFile& dex_file, const DexFile::ClassDef& dex_class_def,
-                                    mirror::Class* c,
-                                    SafeMap<uint32_t, mirror::ArtField*>& field_map) {
+void ClassLinker::ConstructFieldArray(const DexFile& dex_file, const DexFile::ClassDef& dex_class_def,
+                                      mirror::Class* c,
+                                      Handle<mirror::ObjectArray<mirror::ArtField>> field_array) {
   const byte* class_data = dex_file.GetClassData(dex_class_def);
   ClassDataItemIterator it(dex_file, class_data);
   StackHandleScope<2> hs(Thread::Current());
   Handle<mirror::DexCache> dex_cache(hs.NewHandle(c->GetDexCache()));
   Handle<mirror::ClassLoader> class_loader(hs.NewHandle(c->GetClassLoader()));
-  CHECK(!kMovingFields);
   for (size_t i = 0; it.HasNextStaticField(); i++, it.Next()) {
-    field_map.Put(i, ResolveField(dex_file, it.GetMemberIndex(), dex_cache, class_loader, true));
+    if (Runtime::Current()->IsActiveTransaction()) {
+      field_array->Set<true>(i, ResolveField(dex_file, it.GetMemberIndex(), dex_cache, class_loader, true));
+    } else {
+      field_array->Set<false>(i, ResolveField(dex_file, it.GetMemberIndex(), dex_cache, class_loader, true));
+    }
   }
 }
 
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 5694149..edbf2b3 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -437,8 +437,8 @@
   void AppendToBootClassPath(const DexFile& dex_file, Handle<mirror::DexCache> dex_cache)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  void ConstructFieldMap(const DexFile& dex_file, const DexFile::ClassDef& dex_class_def,
-                         mirror::Class* c, SafeMap<uint32_t, mirror::ArtField*>& field_map)
+  void ConstructFieldArray(const DexFile& dex_file, const DexFile::ClassDef& dex_class_def,
+                           mirror::Class* c, Handle<mirror::ObjectArray<mirror::ArtField>> field_array)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Precomputes size needed for Class, in the case of a non-temporary class this size must be
diff --git a/runtime/dex_file.cc b/runtime/dex_file.cc
index ddc2147..db1a044 100644
--- a/runtime/dex_file.cc
+++ b/runtime/dex_file.cc
@@ -1200,7 +1200,7 @@
 }
 
 template<bool kTransactionActive>
-void EncodedStaticFieldValueIterator::ReadValueToField(mirror::ArtField* field) const {
+void EncodedStaticFieldValueIterator::ReadValueToField(Handle<mirror::ArtField> field) const {
   switch (type_) {
     case kBoolean: field->SetBoolean<kTransactionActive>(field->GetDeclaringClass(), jval_.z); break;
     case kByte:    field->SetByte<kTransactionActive>(field->GetDeclaringClass(), jval_.b); break;
@@ -1227,8 +1227,8 @@
     default: UNIMPLEMENTED(FATAL) << ": type " << type_;
   }
 }
-template void EncodedStaticFieldValueIterator::ReadValueToField<true>(mirror::ArtField* field) const;
-template void EncodedStaticFieldValueIterator::ReadValueToField<false>(mirror::ArtField* field) const;
+template void EncodedStaticFieldValueIterator::ReadValueToField<true>(Handle<mirror::ArtField> field) const;
+template void EncodedStaticFieldValueIterator::ReadValueToField<false>(Handle<mirror::ArtField> field) const;
 
 CatchHandlerIterator::CatchHandlerIterator(const DexFile::CodeItem& code_item, uint32_t address) {
   handler_.address_ = -1;
diff --git a/runtime/dex_file.h b/runtime/dex_file.h
index 2794af6..1e86bfc 100644
--- a/runtime/dex_file.h
+++ b/runtime/dex_file.h
@@ -1199,7 +1199,7 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   template<bool kTransactionActive>
-  void ReadValueToField(mirror::ArtField* field) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  void ReadValueToField(Handle<mirror::ArtField> field) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   bool HasNext() { return pos_ < array_size_; }