Make ResolveField not rely on Field::GetType resolution

Change-Id: I10f4a874809ac9db2cd54e200cf10eb7c8979fce
diff --git a/src/class_linker.cc b/src/class_linker.cc
index de35d33..afb6721 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -284,14 +284,14 @@
   SetClassRoot(kJavaLangString, java_lang_String.get());
 
   // Setup the primitive type classes.
-  SetClassRoot(kPrimitiveBoolean, CreatePrimitiveClass("Z", Class::kPrimBoolean));
-  SetClassRoot(kPrimitiveByte, CreatePrimitiveClass("B", Class::kPrimByte));
-  SetClassRoot(kPrimitiveShort, CreatePrimitiveClass("S", Class::kPrimShort));
-  SetClassRoot(kPrimitiveInt, CreatePrimitiveClass("I", Class::kPrimInt));
-  SetClassRoot(kPrimitiveLong, CreatePrimitiveClass("J", Class::kPrimLong));
-  SetClassRoot(kPrimitiveFloat, CreatePrimitiveClass("F", Class::kPrimFloat));
-  SetClassRoot(kPrimitiveDouble, CreatePrimitiveClass("D", Class::kPrimDouble));
-  SetClassRoot(kPrimitiveVoid, CreatePrimitiveClass("V", Class::kPrimVoid));
+  SetClassRoot(kPrimitiveBoolean, CreatePrimitiveClass("Z", Primitive::kPrimBoolean));
+  SetClassRoot(kPrimitiveByte, CreatePrimitiveClass("B", Primitive::kPrimByte));
+  SetClassRoot(kPrimitiveShort, CreatePrimitiveClass("S", Primitive::kPrimShort));
+  SetClassRoot(kPrimitiveInt, CreatePrimitiveClass("I", Primitive::kPrimInt));
+  SetClassRoot(kPrimitiveLong, CreatePrimitiveClass("J", Primitive::kPrimLong));
+  SetClassRoot(kPrimitiveFloat, CreatePrimitiveClass("F", Primitive::kPrimFloat));
+  SetClassRoot(kPrimitiveDouble, CreatePrimitiveClass("D", Primitive::kPrimDouble));
+  SetClassRoot(kPrimitiveVoid, CreatePrimitiveClass("V", Primitive::kPrimVoid));
 
   // Create array interface entries to populate once we can load system classes
   array_interfaces_ = AllocClassArray(2);
@@ -343,7 +343,7 @@
   // now we can use FindSystemClass
 
   // run char class through InitializePrimitiveClass to finish init
-  InitializePrimitiveClass(char_class.get(), "C", Class::kPrimChar);
+  InitializePrimitiveClass(char_class.get(), "C", Primitive::kPrimChar);
   SetClassRoot(kPrimitiveChar, char_class.get());  // needs descriptor
 
   // Object and String need to be rerun through FindSystemClass to finish init
@@ -875,7 +875,7 @@
 Class* ClassLinker::AllocClass(Class* java_lang_Class, size_t class_size) {
   DCHECK_GE(class_size, sizeof(Class));
   SirtRef<Class> klass(Heap::AllocObject(java_lang_Class, class_size)->AsClass());
-  klass->SetPrimitiveType(Class::kPrimNot);  // default to not being primitive
+  klass->SetPrimitiveType(Primitive::kPrimNot);  // default to not being primitive
   klass->SetClassSize(class_size);
   return klass.get();
 }
@@ -1062,7 +1062,7 @@
       DexFile::Field dex_field;
       dex_file.dexReadClassDataField(&class_data, &dex_field, &last_idx);
       const DexFile::FieldId& field_id = dex_file.GetFieldId(dex_field.field_idx_);
-      const char* descriptor = dex_file.dexStringByTypeIdx(field_id.type_idx_);
+      const char* descriptor = dex_file.GetFieldTypeDescriptor(field_id);
       char c = descriptor[0];
       if (c == 'L' || c == '[') {
         num_ref++;
@@ -1138,7 +1138,7 @@
   CHECK_EQ(access_flags & ~kAccJavaFlagsMask, 0U);
   klass->SetAccessFlags(access_flags);
   klass->SetClassLoader(class_loader);
-  DCHECK(klass->GetPrimitiveType() == Class::kPrimNot);
+  DCHECK(klass->GetPrimitiveType() == Primitive::kPrimNot);
   klass->SetStatus(Class::kStatusIdx);
 
   klass->SetSuperClassTypeIdx(dex_class_def.superclass_idx_);
@@ -1264,7 +1264,7 @@
 
   // In order to access primitive types using GetTypeDuringLinking we need to
   // ensure they are resolved into the dex cache
-  const char* descriptor = dex_file.dexStringByTypeIdx(field_id.type_idx_);
+  const char* descriptor = dex_file.GetFieldTypeDescriptor(field_id);
   if (descriptor[1] == '\0') {
     // only the descriptors of primitive types should be 1 character long
     Class* resolved = ResolveType(dex_file, field_id.type_idx_, klass.get());
@@ -1430,7 +1430,7 @@
 
 Class* ClassLinker::InitializePrimitiveClass(Class* primitive_class,
                                              const char* descriptor,
-                                             Class::PrimitiveType type) {
+                                             Primitive::Type type) {
   // TODO: deduce one argument from the other
   CHECK(primitive_class != NULL);
   primitive_class->SetAccessFlags(kAccPublic | kAccFinal | kAccAbstract);
@@ -1532,7 +1532,7 @@
   Class* java_lang_Object = GetClassRoot(kJavaLangObject);
   new_class->SetSuperClass(java_lang_Object);
   new_class->SetVTable(java_lang_Object->GetVTable());
-  new_class->SetPrimitiveType(Class::kPrimNot);
+  new_class->SetPrimitiveType(Primitive::kPrimNot);
   new_class->SetClassLoader(component_type->GetClassLoader());
   new_class->SetStatus(Class::kStatusInitialized);
   // don't need to set new_class->SetObjectSize(..)
@@ -1582,25 +1582,27 @@
 }
 
 Class* ClassLinker::FindPrimitiveClass(char type) {
-  switch (type) {
-    case 'B':
+  switch (Primitive::GetType(type)) {
+    case Primitive::kPrimByte:
       return GetClassRoot(kPrimitiveByte);
-    case 'C':
+    case Primitive::kPrimChar:
       return GetClassRoot(kPrimitiveChar);
-    case 'D':
+    case Primitive::kPrimDouble:
       return GetClassRoot(kPrimitiveDouble);
-    case 'F':
+    case Primitive::kPrimFloat:
       return GetClassRoot(kPrimitiveFloat);
-    case 'I':
+    case Primitive::kPrimInt:
       return GetClassRoot(kPrimitiveInt);
-    case 'J':
+    case Primitive::kPrimLong:
       return GetClassRoot(kPrimitiveLong);
-    case 'S':
+    case Primitive::kPrimShort:
       return GetClassRoot(kPrimitiveShort);
-    case 'Z':
+    case Primitive::kPrimBoolean:
       return GetClassRoot(kPrimitiveBoolean);
-    case 'V':
+    case Primitive::kPrimVoid:
       return GetClassRoot(kPrimitiveVoid);
+    case Primitive::kPrimNot:
+      break;
   }
   std::string printable_type(PrintableChar(type));
   ThrowNoClassDefFoundError("Not a primitive type: %s", printable_type.c_str());
@@ -2419,12 +2421,12 @@
 struct LinkFieldsComparator {
   bool operator()(const Field* field1, const Field* field2) {
     // First come reference fields, then 64-bit, and finally 32-bit
-    const Class* type1 = field1->GetTypeDuringLinking();
-    const Class* type2 = field2->GetTypeDuringLinking();
-    bool isPrimitive1 = type1 != NULL && type1->IsPrimitive();
-    bool isPrimitive2 = type2 != NULL && type2->IsPrimitive();
-    bool is64bit1 = isPrimitive1 && (type1->IsPrimitiveLong() || type1->IsPrimitiveDouble());
-    bool is64bit2 = isPrimitive2 && (type2->IsPrimitiveLong() || type2->IsPrimitiveDouble());
+    Primitive::Type type1 = field1->GetPrimitiveType();
+    Primitive::Type type2 = field2->GetPrimitiveType();
+    bool isPrimitive1 = type1 != Primitive::kPrimNot;
+    bool isPrimitive2 = type2 != Primitive::kPrimNot;
+    bool is64bit1 = isPrimitive1 && (type1 == Primitive::kPrimLong || type1 == Primitive::kPrimDouble);
+    bool is64bit2 = isPrimitive2 && (type2 == Primitive::kPrimLong || type2 == Primitive::kPrimDouble);
     int order1 = (!isPrimitive1 ? 0 : (is64bit1 ? 1 : 2));
     int order2 = (!isPrimitive2 ? 0 : (is64bit2 ? 1 : 2));
     if (order1 != order2) {
@@ -2477,9 +2479,8 @@
   size_t num_reference_fields = 0;
   for (; current_field < num_fields; current_field++) {
     Field* field = grouped_and_sorted_fields.front();
-    const Class* type = field->GetTypeDuringLinking();
-    // if a field's type at this point is NULL it isn't primitive
-    bool isPrimitive = type != NULL && type->IsPrimitive();
+    Primitive::Type type = field->GetPrimitiveType();
+    bool isPrimitive = type != Primitive::kPrimNot;
     if (isPrimitive) {
       break; // past last reference, move on to the next phase
     }
@@ -2496,10 +2497,9 @@
   if (current_field != num_fields && !IsAligned<8>(field_offset.Uint32Value())) {
     for (size_t i = 0; i < grouped_and_sorted_fields.size(); i++) {
       Field* field = grouped_and_sorted_fields[i];
-      const Class* type = field->GetTypeDuringLinking();
-      CHECK(type != NULL);  // should only be working on primitive types
-      DCHECK(type->IsPrimitive());
-      if (type->IsPrimitiveLong() || type->IsPrimitiveDouble()) {
+      Primitive::Type type = field->GetPrimitiveType();
+      CHECK(type != Primitive::kPrimNot);  // should only be working on primitive types
+      if (type == Primitive::kPrimLong || type == Primitive::kPrimDouble) {
         continue;
       }
       fields->Set(current_field++, field);
@@ -2518,13 +2518,12 @@
   while (!grouped_and_sorted_fields.empty()) {
     Field* field = grouped_and_sorted_fields.front();
     grouped_and_sorted_fields.pop_front();
-    const Class* type = field->GetTypeDuringLinking();
-    CHECK(type != NULL);  // should only be working on primitive types
-    DCHECK(type->IsPrimitive());
+    Primitive::Type type = field->GetPrimitiveType();
+    CHECK(type != Primitive::kPrimNot);  // should only be working on primitive types
     fields->Set(current_field, field);
     field->SetOffset(field_offset);
     field_offset = MemberOffset(field_offset.Uint32Value() +
-                                ((type->IsPrimitiveLong() || type->IsPrimitiveDouble())
+                                ((type == Primitive::kPrimLong || type == Primitive::kPrimDouble)
                                  ? sizeof(uint64_t)
                                  : sizeof(uint32_t)));
     current_field++;
@@ -2551,8 +2550,8 @@
                 << " field=" << PrettyField(field)
                 << " offset=" << field->GetField32(MemberOffset(Field::OffsetOffset()), false);
     }
-    const Class* type = field->GetTypeDuringLinking();
-    bool is_primitive = (type != NULL && type->IsPrimitive());
+    Primitive::Type type = field->GetPrimitiveType();
+    bool is_primitive = type != Primitive::kPrimNot;
     if (klass->GetDescriptor()->Equals("Ljava/lang/ref/Reference;") && field->GetName()->Equals("referent")) {
       is_primitive = true; // We lied above, so we have to expect a lie here.
     }
@@ -2727,23 +2726,18 @@
     return NULL;
   }
 
-  const char* name = dex_file.dexStringById(field_id.name_idx_);
-  Class* field_type = ResolveType(dex_file, field_id.type_idx_, dex_cache, class_loader);
-  if (field_type == NULL) {
-    // TODO: LinkageError?
-    UNIMPLEMENTED(WARNING) << "Failed to resolve type of field " << name
-                           << " in " << PrettyClass(klass);
-    return NULL;
-}
+  const char* name = dex_file.GetFieldName(field_id);
+  const char* type = dex_file.GetFieldTypeDescriptor(field_id);
   if (is_static) {
-    resolved = klass->FindStaticField(name, field_type);
+    resolved = klass->FindStaticField(name, type);
   } else {
-    resolved = klass->FindInstanceField(name, field_type);
+    resolved = klass->FindInstanceField(name, type);
   }
   if (resolved != NULL) {
     dex_cache->SetResolvedField(field_idx, resolved);
   } else {
-    DCHECK(Thread::Current()->IsExceptionPending());
+    DCHECK(Thread::Current()->IsExceptionPending())
+        << PrettyClass(klass) << " " << name << " " << type << " " << is_static;
   }
   return resolved;
 }