Change Class::component_type_ and implement reflect.Array

Change-Id: I9e06f31577551c738eca2621146c8d2328119442
diff --git a/src/class_linker_test.cc b/src/class_linker_test.cc
index 32f2eec..5e605c4 100644
--- a/src/class_linker_test.cc
+++ b/src/class_linker_test.cc
@@ -43,7 +43,7 @@
     EXPECT_TRUE(primitive->IsResolved());
     EXPECT_FALSE(primitive->IsArrayInstance());
     EXPECT_FALSE(primitive->IsArrayClass());
-    EXPECT_EQ(0, primitive->GetArrayRank());
+    EXPECT_TRUE(primitive->GetComponentType() == NULL);
     EXPECT_FALSE(primitive->IsInterface());
     EXPECT_TRUE(primitive->IsPublic());
     EXPECT_TRUE(primitive->IsFinal());
@@ -60,11 +60,9 @@
   }
 
   void AssertArrayClass(const StringPiece& array_descriptor,
-                        int32_t array_rank,
                         const StringPiece& component_type,
                         const ClassLoader* class_loader) {
     Class* array = class_linker_->FindClass(array_descriptor, class_loader);
-    EXPECT_EQ(array_rank, array->GetArrayRank());
     EXPECT_TRUE(array->GetComponentType()->GetDescriptor()->Equals(component_type));
     EXPECT_EQ(class_loader, array->GetClassLoader());
     AssertArrayClass(array_descriptor, array);
@@ -87,7 +85,6 @@
     EXPECT_TRUE(array->IsResolved());
     EXPECT_FALSE(array->IsArrayInstance());
     EXPECT_TRUE(array->IsArrayClass());
-    EXPECT_LE(1, array->GetArrayRank());
     EXPECT_FALSE(array->IsInterface());
     EXPECT_EQ(array->GetComponentType()->IsPublic(), array->IsPublic());
     EXPECT_TRUE(array->IsFinal());
@@ -156,7 +153,7 @@
     EXPECT_TRUE(klass->IsResolved());
     EXPECT_TRUE(klass->IsLoaded());
     EXPECT_FALSE(klass->IsArrayClass());
-    EXPECT_EQ(0, klass->GetArrayRank());
+    EXPECT_TRUE(klass->GetComponentType() == NULL);
     EXPECT_TRUE(klass->IsInSamePackage(klass));
     EXPECT_TRUE(Class::IsInSamePackage(klass->GetDescriptor(), klass->GetDescriptor()));
     if (klass->IsInterface()) {
@@ -292,113 +289,6 @@
   }
 };
 
-TEST_F(ClassLinkerTest, FindClassNonexistent) {
-  AssertNonExistentClass("NoSuchClass;");
-  AssertNonExistentClass("LNoSuchClass;");
-}
-
-TEST_F(ClassLinkerTest, FindClassNested) {
-  const ClassLoader* class_loader = LoadDex("Nested");
-
-  Class* outer = class_linker_->FindClass("LNested;", class_loader);
-  ASSERT_TRUE(outer != NULL);
-  EXPECT_EQ(0U, outer->NumVirtualMethods());
-  EXPECT_EQ(1U, outer->NumDirectMethods());
-
-  Class* inner = class_linker_->FindClass("LNested$Inner;", class_loader);
-  ASSERT_TRUE(inner != NULL);
-  EXPECT_EQ(0U, inner->NumVirtualMethods());
-  EXPECT_EQ(1U, inner->NumDirectMethods());
-}
-
-TEST_F(ClassLinkerTest, FindClass_Primitives) {
-  StringPiece expected = "BCDFIJSZV";
-  for (int ch = 0; ch < 255; ch++) {
-    char* s = reinterpret_cast<char*>(&ch);
-    StringPiece descriptor(s, 1);
-    if (expected.find(ch) == StringPiece::npos) {
-      AssertNonExistentClass(descriptor);
-    } else {
-      AssertPrimitiveClass(descriptor);
-    }
-  }
-}
-
-TEST_F(ClassLinkerTest, FindClass) {
-  Class* JavaLangObject = class_linker_->FindSystemClass("Ljava/lang/Object;");
-  ASSERT_TRUE(JavaLangObject != NULL);
-  ASSERT_TRUE(JavaLangObject->GetClass() != NULL);
-  ASSERT_EQ(JavaLangObject->GetClass(), JavaLangObject->GetClass()->GetClass());
-  EXPECT_EQ(JavaLangObject, JavaLangObject->GetClass()->GetSuperClass());
-  ASSERT_TRUE(JavaLangObject->GetDescriptor()->Equals("Ljava/lang/Object;"));
-  EXPECT_TRUE(JavaLangObject->GetSuperClass() == NULL);
-  EXPECT_FALSE(JavaLangObject->HasSuperClass());
-  EXPECT_TRUE(JavaLangObject->GetClassLoader() == NULL);
-  EXPECT_FALSE(JavaLangObject->IsErroneous());
-  EXPECT_TRUE(JavaLangObject->IsVerified());
-  EXPECT_TRUE(JavaLangObject->IsResolved());
-  EXPECT_FALSE(JavaLangObject->IsArrayInstance());
-  EXPECT_FALSE(JavaLangObject->IsArrayClass());
-  EXPECT_EQ(0, JavaLangObject->GetArrayRank());
-  EXPECT_FALSE(JavaLangObject->IsInterface());
-  EXPECT_TRUE(JavaLangObject->IsPublic());
-  EXPECT_FALSE(JavaLangObject->IsFinal());
-  EXPECT_FALSE(JavaLangObject->IsPrimitive());
-  EXPECT_FALSE(JavaLangObject->IsSynthetic());
-  EXPECT_EQ(2U, JavaLangObject->NumDirectMethods());
-  EXPECT_EQ(11U, JavaLangObject->NumVirtualMethods());
-  EXPECT_EQ(2U, JavaLangObject->NumInstanceFields());
-  EXPECT_TRUE(JavaLangObject->GetInstanceField(0)->GetName()->Equals("shadow$_klass_"));
-  EXPECT_TRUE(JavaLangObject->GetInstanceField(1)->GetName()->Equals("shadow$_monitor_"));
-
-  EXPECT_EQ(0U, JavaLangObject->NumStaticFields());
-  EXPECT_EQ(0U, JavaLangObject->NumInterfaces());
-
-  const ClassLoader* class_loader = LoadDex("MyClass");
-  AssertNonExistentClass("LMyClass;");
-  Class* MyClass = class_linker_->FindClass("LMyClass;", class_loader);
-  ASSERT_TRUE(MyClass != NULL);
-  ASSERT_TRUE(MyClass->GetClass() != NULL);
-  ASSERT_EQ(MyClass->GetClass(), MyClass->GetClass()->GetClass());
-  EXPECT_EQ(JavaLangObject, MyClass->GetClass()->GetSuperClass());
-  ASSERT_TRUE(MyClass->GetDescriptor()->Equals("LMyClass;"));
-  EXPECT_TRUE(MyClass->GetSuperClass() == JavaLangObject);
-  EXPECT_TRUE(MyClass->HasSuperClass());
-  EXPECT_EQ(class_loader, MyClass->GetClassLoader());
-  EXPECT_TRUE(MyClass->GetStatus() == Class::kStatusResolved);
-  EXPECT_FALSE(MyClass->IsErroneous());
-  EXPECT_FALSE(MyClass->IsVerified());
-  EXPECT_TRUE(MyClass->IsResolved());
-  EXPECT_FALSE(MyClass->IsArrayInstance());
-  EXPECT_FALSE(MyClass->IsArrayClass());
-  EXPECT_EQ(0, JavaLangObject->GetArrayRank());
-  EXPECT_FALSE(MyClass->IsInterface());
-  EXPECT_FALSE(MyClass->IsPublic());
-  EXPECT_FALSE(MyClass->IsFinal());
-  EXPECT_FALSE(MyClass->IsPrimitive());
-  EXPECT_FALSE(MyClass->IsSynthetic());
-  EXPECT_EQ(1U, MyClass->NumDirectMethods());
-  EXPECT_EQ(0U, MyClass->NumVirtualMethods());
-  EXPECT_EQ(0U, MyClass->NumInstanceFields());
-  EXPECT_EQ(0U, MyClass->NumStaticFields());
-  EXPECT_EQ(0U, MyClass->NumInterfaces());
-
-  EXPECT_EQ(JavaLangObject->GetClass()->GetClass(), MyClass->GetClass()->GetClass());
-
-  // created by class_linker
-  AssertArrayClass("[C", 1, "C", NULL);
-  AssertArrayClass("[Ljava/lang/Object;", 1, "Ljava/lang/Object;", NULL);
-  // synthesized on the fly
-  AssertArrayClass("[[C", 2, "C", NULL);
-  AssertArrayClass("[[[LMyClass;", 3, "LMyClass;", class_loader);
-  // or not available at all
-  AssertNonExistentClass("[[[[LNonExistentClass;");
-}
-
-TEST_F(ClassLinkerTest, LibCore) {
-  AssertDexFile(java_lang_dex_file_.get(), NULL);
-}
-
 struct CheckOffset {
   size_t cpp_offset;
   const char* java_name;
@@ -480,6 +370,9 @@
   };
 };
 
+// Note that ClassLinkerTest.ValidateFieldOrderOfJavaCppUnionClasses
+// is first since if it is failing, others are unlikely to succeed.
+
 struct ObjectOffsets : public CheckOffsets {
   ObjectOffsets() {
     instance = true;
@@ -601,7 +494,6 @@
 
     // alphabetical 32-bit
     offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Class, access_flags_),                  "shadow$_access_flags_"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Class, array_rank_),                    "shadow$_array_rank_"));
     offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Class, class_size_),                    "shadow$_class_size_"));
     offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Class, clinit_thread_id_),              "shadow$_clinit_thread_id_"));
     offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Class, num_reference_instance_fields_), "shadow$_num_reference_instance_fields_"));
@@ -698,6 +590,10 @@
     size = sizeof(ClassClass);
     class_descriptor = "Ljava/lang/Class;";
 
+    // padding 32-bit
+    CHECK_EQ(OFFSETOF_MEMBER(ClassClass, padding_) + 4,
+             OFFSETOF_MEMBER(ClassClass, serialVersionUID_));
+
     // alphabetical 64-bit
     offsets.push_back(CheckOffset(OFFSETOF_MEMBER(ClassClass, serialVersionUID_), "serialVersionUID"));
   };
@@ -713,11 +609,11 @@
     offsets.push_back(CheckOffset(OFFSETOF_MEMBER(StringClass, ASCII_),                  "ASCII"));
     offsets.push_back(CheckOffset(OFFSETOF_MEMBER(StringClass, CASE_INSENSITIVE_ORDER_), "CASE_INSENSITIVE_ORDER"));
 
+    // padding 32-bit
+    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(StringClass, REPLACEMENT_CHAR_),       "REPLACEMENT_CHAR"));
+
     // alphabetical 64-bit
     offsets.push_back(CheckOffset(OFFSETOF_MEMBER(StringClass, serialVersionUID_),       "serialVersionUID"));
-
-    // alphabetical 32-bit
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(StringClass, REPLACEMENT_CHAR_),       "REPLACEMENT_CHAR"));
   };
 };
 
@@ -776,6 +672,113 @@
   EXPECT_TRUE(MethodClassOffsets().Check());
 }
 
+TEST_F(ClassLinkerTest, FindClassNonexistent) {
+  AssertNonExistentClass("NoSuchClass;");
+  AssertNonExistentClass("LNoSuchClass;");
+}
+
+TEST_F(ClassLinkerTest, FindClassNested) {
+  const ClassLoader* class_loader = LoadDex("Nested");
+
+  Class* outer = class_linker_->FindClass("LNested;", class_loader);
+  ASSERT_TRUE(outer != NULL);
+  EXPECT_EQ(0U, outer->NumVirtualMethods());
+  EXPECT_EQ(1U, outer->NumDirectMethods());
+
+  Class* inner = class_linker_->FindClass("LNested$Inner;", class_loader);
+  ASSERT_TRUE(inner != NULL);
+  EXPECT_EQ(0U, inner->NumVirtualMethods());
+  EXPECT_EQ(1U, inner->NumDirectMethods());
+}
+
+TEST_F(ClassLinkerTest, FindClass_Primitives) {
+  StringPiece expected = "BCDFIJSZV";
+  for (int ch = 0; ch < 255; ch++) {
+    char* s = reinterpret_cast<char*>(&ch);
+    StringPiece descriptor(s, 1);
+    if (expected.find(ch) == StringPiece::npos) {
+      AssertNonExistentClass(descriptor);
+    } else {
+      AssertPrimitiveClass(descriptor);
+    }
+  }
+}
+
+TEST_F(ClassLinkerTest, FindClass) {
+  Class* JavaLangObject = class_linker_->FindSystemClass("Ljava/lang/Object;");
+  ASSERT_TRUE(JavaLangObject != NULL);
+  ASSERT_TRUE(JavaLangObject->GetClass() != NULL);
+  ASSERT_EQ(JavaLangObject->GetClass(), JavaLangObject->GetClass()->GetClass());
+  EXPECT_EQ(JavaLangObject, JavaLangObject->GetClass()->GetSuperClass());
+  ASSERT_TRUE(JavaLangObject->GetDescriptor()->Equals("Ljava/lang/Object;"));
+  EXPECT_TRUE(JavaLangObject->GetSuperClass() == NULL);
+  EXPECT_FALSE(JavaLangObject->HasSuperClass());
+  EXPECT_TRUE(JavaLangObject->GetClassLoader() == NULL);
+  EXPECT_FALSE(JavaLangObject->IsErroneous());
+  EXPECT_TRUE(JavaLangObject->IsVerified());
+  EXPECT_TRUE(JavaLangObject->IsResolved());
+  EXPECT_FALSE(JavaLangObject->IsArrayInstance());
+  EXPECT_FALSE(JavaLangObject->IsArrayClass());
+  EXPECT_TRUE(JavaLangObject->GetComponentType() == NULL);
+  EXPECT_FALSE(JavaLangObject->IsInterface());
+  EXPECT_TRUE(JavaLangObject->IsPublic());
+  EXPECT_FALSE(JavaLangObject->IsFinal());
+  EXPECT_FALSE(JavaLangObject->IsPrimitive());
+  EXPECT_FALSE(JavaLangObject->IsSynthetic());
+  EXPECT_EQ(2U, JavaLangObject->NumDirectMethods());
+  EXPECT_EQ(11U, JavaLangObject->NumVirtualMethods());
+  EXPECT_EQ(2U, JavaLangObject->NumInstanceFields());
+  EXPECT_TRUE(JavaLangObject->GetInstanceField(0)->GetName()->Equals("shadow$_klass_"));
+  EXPECT_TRUE(JavaLangObject->GetInstanceField(1)->GetName()->Equals("shadow$_monitor_"));
+
+  EXPECT_EQ(0U, JavaLangObject->NumStaticFields());
+  EXPECT_EQ(0U, JavaLangObject->NumInterfaces());
+
+  const ClassLoader* class_loader = LoadDex("MyClass");
+  AssertNonExistentClass("LMyClass;");
+  Class* MyClass = class_linker_->FindClass("LMyClass;", class_loader);
+  ASSERT_TRUE(MyClass != NULL);
+  ASSERT_TRUE(MyClass->GetClass() != NULL);
+  ASSERT_EQ(MyClass->GetClass(), MyClass->GetClass()->GetClass());
+  EXPECT_EQ(JavaLangObject, MyClass->GetClass()->GetSuperClass());
+  ASSERT_TRUE(MyClass->GetDescriptor()->Equals("LMyClass;"));
+  EXPECT_TRUE(MyClass->GetSuperClass() == JavaLangObject);
+  EXPECT_TRUE(MyClass->HasSuperClass());
+  EXPECT_EQ(class_loader, MyClass->GetClassLoader());
+  EXPECT_TRUE(MyClass->GetStatus() == Class::kStatusResolved);
+  EXPECT_FALSE(MyClass->IsErroneous());
+  EXPECT_FALSE(MyClass->IsVerified());
+  EXPECT_TRUE(MyClass->IsResolved());
+  EXPECT_FALSE(MyClass->IsArrayInstance());
+  EXPECT_FALSE(MyClass->IsArrayClass());
+  EXPECT_TRUE(MyClass->GetComponentType() == NULL);
+  EXPECT_FALSE(MyClass->IsInterface());
+  EXPECT_FALSE(MyClass->IsPublic());
+  EXPECT_FALSE(MyClass->IsFinal());
+  EXPECT_FALSE(MyClass->IsPrimitive());
+  EXPECT_FALSE(MyClass->IsSynthetic());
+  EXPECT_EQ(1U, MyClass->NumDirectMethods());
+  EXPECT_EQ(0U, MyClass->NumVirtualMethods());
+  EXPECT_EQ(0U, MyClass->NumInstanceFields());
+  EXPECT_EQ(0U, MyClass->NumStaticFields());
+  EXPECT_EQ(0U, MyClass->NumInterfaces());
+
+  EXPECT_EQ(JavaLangObject->GetClass()->GetClass(), MyClass->GetClass()->GetClass());
+
+  // created by class_linker
+  AssertArrayClass("[C", "C", NULL);
+  AssertArrayClass("[Ljava/lang/Object;", "Ljava/lang/Object;", NULL);
+  // synthesized on the fly
+  AssertArrayClass("[[C", "[C", NULL);
+  AssertArrayClass("[[[LMyClass;", "[[LMyClass;", class_loader);
+  // or not available at all
+  AssertNonExistentClass("[[[[LNonExistentClass;");
+}
+
+TEST_F(ClassLinkerTest, LibCore) {
+  AssertDexFile(java_lang_dex_file_.get(), NULL);
+}
+
 // The first reference array element must be a multiple of 8 bytes from the
 // start of the object
 TEST_F(ClassLinkerTest, ValidateObjectArrayElementsOffset) {