Fix for test 044-proxy

Proxy implementation was incomplete following meta-data refactoring,
complete this change.

Change-Id: Ic0567bdef373dbae17031a30aabc779027173229
diff --git a/src/object_utils.h b/src/object_utils.h
index 0c93b43..42937cf 100644
--- a/src/object_utils.h
+++ b/src/object_utils.h
@@ -20,6 +20,7 @@
 #include "class_linker.h"
 #include "dex_cache.h"
 #include "dex_file.h"
+#include "intern_table.h"
 #include "object.h"
 #include "runtime.h"
 #include "UniquePtr.h"
@@ -90,8 +91,9 @@
       return 0;
     } else if (klass_->IsArrayClass()) {
       return 2;
+    } else if (klass_->IsProxyClass()) {
+      return klass_->GetIfTable()->GetLength();
     } else {
-      CHECK(!klass_->IsProxyClass());
       const DexFile::TypeList* interfaces = GetInterfaceTypeList();
       if (interfaces == NULL) {
         return 0;
@@ -116,6 +118,8 @@
         DCHECK_EQ(1U, idx);
         return GetClassLinker()->FindSystemClass("Ljava/io/Serializable;");
       }
+    } else if (klass_->IsProxyClass()) {
+      return klass_->GetIfTable()->Get(idx)->GetInterface();
     } else {
       uint16_t type_idx = GetInterfaceTypeIdx(idx);
       Class* interface = GetDexCache()->GetResolvedType(type_idx);
@@ -213,28 +217,60 @@
     field_ = new_f;
   }
   const char* GetName() {
-    const DexFile& dex_file = GetDexFile();
-    return dex_file.GetFieldName(dex_file.GetFieldId(field_->GetDexFieldIndex()));
+    uint32_t field_index = field_->GetDexFieldIndex();
+    if (field_index != DexFile::kDexNoIndex) {
+      const DexFile& dex_file = GetDexFile();
+      return dex_file.GetFieldName(dex_file.GetFieldId(field_index));
+    } else {
+      // Proxy classes have a single static field called "throws"
+      CHECK(field_->GetDeclaringClass()->IsProxyClass());
+      DCHECK(field_->IsStatic());
+      return "throws";
+    }
   }
   String* GetNameAsString() {
-    const DexFile& dex_file = GetDexFile();
-    const DexFile::FieldId& field_id = dex_file.GetFieldId(field_->GetDexFieldIndex());
-    return GetClassLinker()->ResolveString(dex_file, field_id.name_idx_, GetDexCache());
+    uint32_t field_index = field_->GetDexFieldIndex();
+    if (field_index != DexFile::kDexNoIndex) {
+      const DexFile& dex_file = GetDexFile();
+      const DexFile::FieldId& field_id = dex_file.GetFieldId(field_index);
+      return GetClassLinker()->ResolveString(dex_file, field_id.name_idx_, GetDexCache());
+    } else {
+      // Proxy classes have a single static field called "throws"
+      CHECK(field_->GetDeclaringClass()->IsProxyClass());
+      DCHECK(field_->IsStatic());
+      return Runtime::Current()->GetInternTable()->InternStrong("throws");
+    }
   }
   Class* GetType() {
-    const DexFile& dex_file = GetDexFile();
-    const DexFile::FieldId& field_id = dex_file.GetFieldId(field_->GetDexFieldIndex());
-    Class* type = GetDexCache()->GetResolvedType(field_id.type_idx_);
-    if (type == NULL) {
-      type = GetClassLinker()->ResolveType(field_id.type_idx_, field_);
-      CHECK(type != NULL || Thread::Current()->IsExceptionPending());
+    uint32_t field_index = field_->GetDexFieldIndex();
+    if (field_index != DexFile::kDexNoIndex) {
+      const DexFile& dex_file = GetDexFile();
+      const DexFile::FieldId& field_id = dex_file.GetFieldId(field_index);
+      Class* type = GetDexCache()->GetResolvedType(field_id.type_idx_);
+      if (type == NULL) {
+        type = GetClassLinker()->ResolveType(field_id.type_idx_, field_);
+        CHECK(type != NULL || Thread::Current()->IsExceptionPending());
+      }
+      return type;
+    } else {
+      // Proxy classes have a single static field called "throws" whose type is Class[][]
+      CHECK(field_->GetDeclaringClass()->IsProxyClass());
+      DCHECK(field_->IsStatic());
+      return GetClassLinker()->FindSystemClass("[[Ljava/lang/Class;");
     }
-    return type;
   }
   const char* GetTypeDescriptor() {
-    const DexFile& dex_file = GetDexFile();
-    const DexFile::FieldId& field_id = dex_file.GetFieldId(field_->GetDexFieldIndex());
-    return dex_file.GetFieldTypeDescriptor(field_id);
+    uint32_t field_index = field_->GetDexFieldIndex();
+    if (field_index != DexFile::kDexNoIndex) {
+      const DexFile& dex_file = GetDexFile();
+      const DexFile::FieldId& field_id = dex_file.GetFieldId(field_index);
+      return dex_file.GetFieldTypeDescriptor(field_id);
+    } else {
+      // Proxy classes have a single static field called "throws" whose type is Class[][]
+      CHECK(field_->GetDeclaringClass()->IsProxyClass());
+      DCHECK(field_->IsStatic());
+      return "[[Ljava/lang/Class;";
+    }
   }
   Primitive::Type GetTypeAsPrimitiveType() {
     return Primitive::GetType(GetTypeDescriptor()[0]);
@@ -247,10 +283,20 @@
     Primitive::Type type = GetTypeAsPrimitiveType();
     return Primitive::FieldSize(type);
   }
+
+  // The returned const char* is only guaranteed to be valid for the lifetime of the FieldHelper.
+  // If you need it longer, copy it into a std::string.
   const char* GetDeclaringClassDescriptor() {
     uint16_t type_idx = field_->GetDeclaringClass()->GetDexTypeIndex();
-    const DexFile& dex_file = GetDexFile();
-    return dex_file.GetTypeDescriptor(dex_file.GetTypeId(type_idx));
+    if (type_idx != DexFile::kDexNoIndex16) {
+      const DexFile& dex_file = GetDexFile();
+      return dex_file.GetTypeDescriptor(dex_file.GetTypeId(type_idx));
+    } else {
+      // Most likely a proxy class
+      ClassHelper kh(field_->GetDeclaringClass());
+      declaring_class_descriptor_ = kh.GetDescriptor();
+      return declaring_class_descriptor_.c_str();
+    }
   }
 
  private:
@@ -284,6 +330,7 @@
   DexCache* dex_cache_;
   const DexFile* dex_file_;
   const Field* field_;
+  std::string declaring_class_descriptor_;
 
   DISALLOW_COPY_AND_ASSIGN(FieldHelper);
 };
@@ -387,7 +434,7 @@
   }
   const char* GetDeclaringClassDescriptor() {
     Class* klass = method_->GetDeclaringClass();
-    CHECK(!klass->IsProxyClass());
+    DCHECK(!klass->IsProxyClass());
     uint16_t type_idx = klass->GetDexTypeIndex();
     const DexFile& dex_file = GetDexFile();
     return dex_file.GetTypeDescriptor(dex_file.GetTypeId(type_idx));