Make ResolveField not rely on Field::GetType resolution

Change-Id: I10f4a874809ac9db2cd54e200cf10eb7c8979fce
diff --git a/src/object.cc b/src/object.cc
index ab95885..91328aa 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -102,6 +102,31 @@
   return GetDeclaringClass()->GetDexCache()->GetResolvedType(GetTypeIdx());
 }
 
+bool Field::IsPrimitiveType() const {
+  Class* type = GetTypeDuringLinking();
+  return (type == NULL || type->IsPrimitive());
+}
+
+Primitive::Type Field::GetPrimitiveType() const {
+  Class* type = GetTypeDuringLinking();
+  if (type == NULL) {
+    return Primitive::kPrimNot;
+  }
+  return type->GetPrimitiveType();
+}
+
+size_t Field::PrimitiveSize() const {
+  return Primitive::FieldSize(GetPrimitiveType());
+}
+
+const char* Field::GetTypeDescriptor() const {
+  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+  const DexFile& dex_file = class_linker->FindDexFile(GetDeclaringClass()->GetDexCache());
+  const char* descriptor = dex_file.dexStringByTypeIdx(GetTypeIdx());
+  DCHECK(descriptor != NULL);
+  return descriptor;
+}
+
 Class* Field::GetType() const {
   if (type_ == NULL) {
     type_ = Runtime::Current()->GetClassLinker()->ResolveType(GetTypeIdx(), this);
@@ -120,11 +145,11 @@
 }
 
 void Field::InitJavaFieldsLocked() {
-  GetType(); // Sets type_ as a side-effect. May throw.
+  GetType(); // Resolves type as a side-effect. May throw.
 }
 
 uint32_t Field::Get32(const Object* object) const {
-  CHECK((object == NULL) == IsStatic());
+  CHECK((object == NULL) == IsStatic()) << PrettyField(this);
   if (IsStatic()) {
     object = declaring_class_;
   }
@@ -132,7 +157,7 @@
 }
 
 void Field::Set32(Object* object, uint32_t new_value) const {
-  CHECK((object == NULL) == IsStatic());
+  CHECK((object == NULL) == IsStatic()) << PrettyField(this);
   if (IsStatic()) {
     object = declaring_class_;
   }
@@ -140,7 +165,7 @@
 }
 
 uint64_t Field::Get64(const Object* object) const {
-  CHECK((object == NULL) == IsStatic());
+  CHECK((object == NULL) == IsStatic()) << PrettyField(this);
   if (IsStatic()) {
     object = declaring_class_;
   }
@@ -148,7 +173,7 @@
 }
 
 void Field::Set64(Object* object, uint64_t new_value) const {
-  CHECK((object == NULL) == IsStatic());
+  CHECK((object == NULL) == IsStatic()) << PrettyField(this);
   if (IsStatic()) {
     object = declaring_class_;
   }
@@ -156,7 +181,7 @@
 }
 
 Object* Field::GetObj(const Object* object) const {
-  CHECK((object == NULL) == IsStatic());
+  CHECK((object == NULL) == IsStatic()) << PrettyField(this);
   if (IsStatic()) {
     object = declaring_class_;
   }
@@ -164,7 +189,7 @@
 }
 
 void Field::SetObj(Object* object, const Object* new_value) const {
-  CHECK((object == NULL) == IsStatic());
+  CHECK((object == NULL) == IsStatic()) << PrettyField(this);
   if (IsStatic()) {
     object = declaring_class_;
   }
@@ -172,100 +197,100 @@
 }
 
 bool Field::GetBoolean(const Object* object) const {
-  DCHECK(GetType()->IsPrimitiveBoolean());
+  DCHECK(GetPrimitiveType() == Primitive::kPrimBoolean) << PrettyField(this);
   return Get32(object);
 }
 
 void Field::SetBoolean(Object* object, bool z) const {
-  DCHECK(GetType()->IsPrimitiveBoolean());
+  DCHECK(GetPrimitiveType() == Primitive::kPrimBoolean) << PrettyField(this);
   Set32(object, z);
 }
 
 int8_t Field::GetByte(const Object* object) const {
-  DCHECK(GetType()->IsPrimitiveByte());
+  DCHECK(GetPrimitiveType() == Primitive::kPrimByte) << PrettyField(this);
   return Get32(object);
 }
 
 void Field::SetByte(Object* object, int8_t b) const {
-  DCHECK(GetType()->IsPrimitiveByte());
+  DCHECK(GetPrimitiveType() == Primitive::kPrimByte) << PrettyField(this);
   Set32(object, b);
 }
 
 uint16_t Field::GetChar(const Object* object) const {
-  DCHECK(GetType()->IsPrimitiveChar());
+  DCHECK(GetPrimitiveType() == Primitive::kPrimChar) << PrettyField(this);
   return Get32(object);
 }
 
 void Field::SetChar(Object* object, uint16_t c) const {
-  DCHECK(GetType()->IsPrimitiveChar());
+  DCHECK(GetPrimitiveType() == Primitive::kPrimChar) << PrettyField(this);
   Set32(object, c);
 }
 
 int16_t Field::GetShort(const Object* object) const {
-  DCHECK(GetType()->IsPrimitiveShort());
+  DCHECK(GetPrimitiveType() == Primitive::kPrimShort) << PrettyField(this);
   return Get32(object);
 }
 
 void Field::SetShort(Object* object, int16_t s) const {
-  DCHECK(GetType()->IsPrimitiveShort());
+  DCHECK(GetPrimitiveType() == Primitive::kPrimShort) << PrettyField(this);
   Set32(object, s);
 }
 
 int32_t Field::GetInt(const Object* object) const {
-  DCHECK(GetType()->IsPrimitiveInt());
+  DCHECK(GetPrimitiveType() == Primitive::kPrimInt) << PrettyField(this);
   return Get32(object);
 }
 
 void Field::SetInt(Object* object, int32_t i) const {
-  DCHECK(GetType()->IsPrimitiveInt()) << PrettyField(this);
+  DCHECK(GetPrimitiveType() == Primitive::kPrimInt) << PrettyField(this);
   Set32(object, i);
 }
 
 int64_t Field::GetLong(const Object* object) const {
-  DCHECK(GetType()->IsPrimitiveLong());
+  DCHECK(GetPrimitiveType() == Primitive::kPrimLong) << PrettyField(this);
   return Get64(object);
 }
 
 void Field::SetLong(Object* object, int64_t j) const {
-  DCHECK(GetType()->IsPrimitiveLong());
+  DCHECK(GetPrimitiveType() == Primitive::kPrimLong) << PrettyField(this);
   Set64(object, j);
 }
 
 float Field::GetFloat(const Object* object) const {
-  DCHECK(GetType()->IsPrimitiveFloat());
+  DCHECK(GetPrimitiveType() == Primitive::kPrimFloat) << PrettyField(this);
   JValue float_bits;
   float_bits.i = Get32(object);
   return float_bits.f;
 }
 
 void Field::SetFloat(Object* object, float f) const {
-  DCHECK(GetType()->IsPrimitiveFloat());
+  DCHECK(GetPrimitiveType() == Primitive::kPrimFloat) << PrettyField(this);
   JValue float_bits;
   float_bits.f = f;
   Set32(object, float_bits.i);
 }
 
 double Field::GetDouble(const Object* object) const {
-  DCHECK(GetType()->IsPrimitiveDouble());
+  DCHECK(GetPrimitiveType() == Primitive::kPrimDouble) << PrettyField(this);
   JValue double_bits;
   double_bits.j = Get64(object);
   return double_bits.d;
 }
 
 void Field::SetDouble(Object* object, double d) const {
-  DCHECK(GetType()->IsPrimitiveDouble());
+  DCHECK(GetPrimitiveType() == Primitive::kPrimDouble) << PrettyField(this);
   JValue double_bits;
   double_bits.d = d;
   Set64(object, double_bits.j);
 }
 
 Object* Field::GetObject(const Object* object) const {
-  CHECK(!GetType()->IsPrimitive());
+  CHECK(GetPrimitiveType() == Primitive::kPrimNot) << PrettyField(this);
   return GetObj(object);
 }
 
 void Field::SetObject(Object* object, const Object* l) const {
-  CHECK(!GetType()->IsPrimitive());
+  CHECK(GetPrimitiveType() == Primitive::kPrimNot) << PrettyField(this);
   SetObj(object, l);
 }
 
@@ -828,44 +853,6 @@
              new_reference_offsets, false);
 }
 
-size_t Class::PrimitiveSize() const {
-  switch (GetPrimitiveType()) {
-    case kPrimBoolean:
-    case kPrimByte:    return 1;
-    case kPrimChar:
-    case kPrimShort:   return 2;
-    case kPrimInt:
-    case kPrimFloat:   return 4;
-    case kPrimLong:
-    case kPrimDouble:  return 8;
-    default:
-      LOG(FATAL) << "Primitive type size calculation on invalid type " << this;
-      return 0;
-  }
-}
-
-size_t Class::PrimitiveFieldSize() const {
-  return PrimitiveSize() <= 4 ? 4 : 8;
-}
-
-size_t Class::GetTypeSize(const String* descriptor) {
-  switch (descriptor->CharAt(0)) {
-  case 'B': return 1;  // byte
-  case 'C': return 2;  // char
-  case 'D': return 8;  // double
-  case 'F': return 4;  // float
-  case 'I': return 4;  // int
-  case 'J': return 8;  // long
-  case 'S': return 2;  // short
-  case 'Z': return 1;  // boolean
-  case 'L': return sizeof(Object*);
-  case '[': return sizeof(Array*);
-  default:
-    LOG(ERROR) << "Unknown type " << descriptor;
-    return 0;
-  }
-}
-
 bool Class::Implements(const Class* klass) const {
   DCHECK(klass != NULL);
   DCHECK(klass->IsInterface()) << PrettyClass(this);
@@ -1089,9 +1076,6 @@
     Method* method = GetVirtualMethod(i);
     if (method->GetName() == name && method->GetSignature() == signature) {
       return method;
-    } else {
-      LOG(INFO) << "Find (" << name->ToModifiedUtf8() << ", " << signature->ToModifiedUtf8()
-          << ") != " << PrettyMethod(method);
     }
   }
   return NULL;
@@ -1117,19 +1101,32 @@
   return NULL;
 }
 
-Field* Class::FindDeclaredInstanceField(const StringPiece& name, Class* type) {
+Field* Class::FindDeclaredInstanceField(const StringPiece& name, const StringPiece& type) {
   // Is the field in this class?
   // Interfaces are not relevant because they can't contain instance fields.
   for (size_t i = 0; i < NumInstanceFields(); ++i) {
     Field* f = GetInstanceField(i);
-    if (f->GetName()->Equals(name) && type == f->GetType()) {
+    if (f->GetName()->Equals(name) &&
+        StringPiece(f->GetTypeDescriptor()) == type) {
       return f;
     }
   }
   return NULL;
 }
 
-Field* Class::FindInstanceField(const StringPiece& name, Class* type) {
+Field* Class::FindDeclaredInstanceField(String* name, String* type) {
+  // Is the field in this class?
+  // Interfaces are not relevant because they can't contain instance fields.
+  for (size_t i = 0; i < NumInstanceFields(); ++i) {
+    Field* f = GetInstanceField(i);
+    if (f->GetName() == name && type->Equals(f->GetTypeDescriptor())) {
+      return f;
+    }
+  }
+  return NULL;
+}
+
+Field* Class::FindInstanceField(const StringPiece& name, const StringPiece& type) {
   // Is the field in this class, or any of its superclasses?
   // Interfaces are not relevant because they can't contain instance fields.
   for (Class* c = this; c != NULL; c = c->GetSuperClass()) {
@@ -1141,18 +1138,64 @@
   return NULL;
 }
 
-Field* Class::FindDeclaredStaticField(const StringPiece& name, Class* type) {
-  DCHECK(type != NULL);
-  for (size_t i = 0; i < NumStaticFields(); ++i) {
-    Field* f = GetStaticField(i);
-    if (f->GetName()->Equals(name) && f->GetType() == type) {
+Field* Class::FindInstanceField(String* name, String* type) {
+  // Is the field in this class, or any of its superclasses?
+  // Interfaces are not relevant because they can't contain instance fields.
+  for (Class* c = this; c != NULL; c = c->GetSuperClass()) {
+    Field* f = c->FindDeclaredInstanceField(name, type);
+    if (f != NULL) {
       return f;
     }
   }
   return NULL;
 }
 
-Field* Class::FindStaticField(const StringPiece& name, Class* type) {
+Field* Class::FindDeclaredStaticField(const StringPiece& name, const StringPiece& type) {
+  DCHECK(type != NULL);
+  for (size_t i = 0; i < NumStaticFields(); ++i) {
+    Field* f = GetStaticField(i);
+    if (f->GetName()->Equals(name) && StringPiece(f->GetTypeDescriptor()) == type) {
+      return f;
+    }
+  }
+  return NULL;
+}
+
+Field* Class::FindDeclaredStaticField(String* name, String* type) {
+  DCHECK(type != NULL);
+  for (size_t i = 0; i < NumStaticFields(); ++i) {
+    Field* f = GetStaticField(i);
+    if (f->GetName() == name && type->Equals(f->GetTypeDescriptor())) {
+      return f;
+    }
+  }
+  return NULL;
+}
+
+Field* Class::FindStaticField(const StringPiece& name, const StringPiece& type) {
+  // Is the field in this class (or its interfaces), or any of its
+  // superclasses (or their interfaces)?
+  for (Class* c = this; c != NULL; c = c->GetSuperClass()) {
+    // Is the field in this class?
+    Field* f = c->FindDeclaredStaticField(name, type);
+    if (f != NULL) {
+      return f;
+    }
+
+    // Is this field in any of this class' interfaces?
+    for (int32_t i = 0; i < c->GetIfTableCount(); ++i) {
+      InterfaceEntry* interface_entry = c->GetIfTable()->Get(i);
+      Class* interface = interface_entry->GetInterface();
+      f = interface->FindDeclaredStaticField(name, type);
+      if (f != NULL) {
+        return f;
+      }
+    }
+  }
+  return NULL;
+}
+
+Field* Class::FindStaticField(String* name, String* type) {
   // Is the field in this class (or its interfaces), or any of its
   // superclasses (or their interfaces)?
   for (Class* c = this; c != NULL; c = c->GetSuperClass()) {