Use the method descriptor for prototype and return type comparisons.
Change-Id: If2623b53e069d6f51c08849ac2798f792d465234
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 0d7c1dc..1bfa009 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -961,44 +961,6 @@
return true;
}
-bool ClassLinker::HasSameArgumentTypes(const Method* m1, const Method* m2) const {
- const DexFile& dex1 = FindDexFile(m1->GetClass()->GetDexCache());
- const DexFile& dex2 = FindDexFile(m2->GetClass()->GetDexCache());
- const DexFile::ProtoId& proto1 = dex1.GetProtoId(m1->proto_idx_);
- const DexFile::ProtoId& proto2 = dex2.GetProtoId(m2->proto_idx_);
-
- // TODO: compare ProtoId objects for equality and exit early
- const DexFile::TypeList* type_list1 = dex1.GetProtoParameters(proto1);
- const DexFile::TypeList* type_list2 = dex2.GetProtoParameters(proto2);
- size_t arity1 = (type_list1 == NULL) ? 0 : type_list1->Size();
- size_t arity2 = (type_list2 == NULL) ? 0 : type_list2->Size();
- if (arity1 != arity2) {
- return false;
- }
-
- for (size_t i = 0; i < arity1; ++i) {
- uint32_t type_idx1 = type_list1->GetTypeItem(i).type_idx_;
- uint32_t type_idx2 = type_list2->GetTypeItem(i).type_idx_;
- const char* type1 = dex1.dexStringByTypeIdx(type_idx1);
- const char* type2 = dex2.dexStringByTypeIdx(type_idx2);
- if (strcmp(type1, type2) != 0) {
- return false;
- }
- }
-
- return true;
-}
-
-bool ClassLinker::HasSameReturnType(const Method* m1, const Method* m2) const {
- const DexFile& dex1 = FindDexFile(m1->GetClass()->GetDexCache());
- const DexFile& dex2 = FindDexFile(m2->GetClass()->GetDexCache());
- const DexFile::ProtoId& proto1 = dex1.GetProtoId(m1->proto_idx_);
- const DexFile::ProtoId& proto2 = dex2.GetProtoId(m2->proto_idx_);
- const char* type1 = dex1.dexStringByTypeIdx(proto1.return_type_idx_);
- const char* type2 = dex2.dexStringByTypeIdx(proto2.return_type_idx_);
- return (strcmp(type1, type2) == 0);
-}
-
bool ClassLinker::InitializeSuperClass(Class* klass) {
CHECK(klass != NULL);
// TODO: assert klass lock is acquired
@@ -1195,7 +1157,7 @@
size_t j = 0;
for (; j < actual_count; ++j) {
Method* super_method = klass->vtable_->Get(j);
- if (HasSameNameAndPrototype(local_method, super_method)) {
+ if (local_method->HasSameNameAndDescriptor(super_method)) {
// Verify
if (super_method->IsFinal()) {
LG << "Method overrides final method"; // TODO: VirtualMachineError
@@ -1303,8 +1265,9 @@
Method* interface_method = interface->GetVirtualMethod(j);
int k; // must be signed
for (k = klass->vtable_->GetLength() - 1; k >= 0; --k) {
- if (HasSameNameAndPrototype(interface_method, klass->vtable_->Get(k))) {
- if (!klass->vtable_->Get(k)->IsPublic()) {
+ Method* vtable_method = klass->vtable_->Get(k);
+ if (interface_method->HasSameNameAndDescriptor(vtable_method)) {
+ if (!vtable_method->IsPublic()) {
LG << "Implementation not public";
return false;
}
@@ -1323,7 +1286,8 @@
}
int mir;
for (mir = 0; mir < miranda_count; mir++) {
- if (HasSameNameAndPrototype(miranda_list[mir], interface_method)) {
+ Method* miranda_method = miranda_list[mir];
+ if (miranda_method->HasSameNameAndDescriptor(interface_method)) {
break;
}
}
diff --git a/src/class_linker.h b/src/class_linker.h
index 013196b..70d268d 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -122,22 +122,6 @@
const Class* klass1,
const Class* klass2);
- bool HasSameNameAndPrototype(const Method* m1, const Method* m2) const {
- return HasSameName(m1, m2) && HasSamePrototype(m1, m2);
- }
-
- bool HasSameName(const Method* m1, const Method* m2) const {
- return String::Equals(m1->GetName(), m2->GetName());
- }
-
- bool HasSamePrototype(const Method* m1, const Method* m2) const {
- return HasSameReturnType(m1, m2) && HasSameArgumentTypes(m1, m2);
- }
-
- bool HasSameReturnType(const Method* m1, const Method* m2) const;
-
- bool HasSameArgumentTypes(const Method* m1, const Method* m2) const;
-
bool LinkClass(Class* klass, const DexFile& dex_file);
bool LinkSuperClass(Class* klass);
@@ -211,8 +195,6 @@
bool init_done_;
friend class RuntimeTest;
- FRIEND_TEST(ClassLinkerTest, ProtoCompare);
- FRIEND_TEST(ClassLinkerTest, ProtoCompare2);
FRIEND_TEST(DexCacheTest, Open);
friend class ObjectTest;
FRIEND_TEST(ObjectTest, AllocObjectArray);
diff --git a/src/class_linker_test.cc b/src/class_linker_test.cc
index d521183..a9c3e50 100644
--- a/src/class_linker_test.cc
+++ b/src/class_linker_test.cc
@@ -103,7 +103,7 @@
if (klass->IsInterface()) {
EXPECT_TRUE(klass->IsAbstract());
if (klass->NumDirectMethods() == 1) {
- EXPECT_PRED2(String::EqualsUtf8, klass->GetDirectMethod(0)->GetName(), "<clinit>");
+ EXPECT_TRUE(klass->GetDirectMethod(0)->GetName()->Equals("<clinit>"));
} else {
EXPECT_EQ(0U, klass->NumDirectMethods());
}
@@ -298,104 +298,6 @@
AssertNonExistantClass("[[[[LNonExistantClass;");
}
-TEST_F(ClassLinkerTest, ProtoCompare) {
- ClassLinker* linker = class_linker_;
-
- scoped_ptr<DexFile> dex(OpenDexFileBase64(kProtoCompareDex));
- PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
-
- Class* klass = linker->FindClass("LProtoCompare;", class_loader);
- ASSERT_TRUE(klass != NULL);
-
- ASSERT_EQ(4U, klass->NumVirtualMethods());
-
- Method* m1 = klass->GetVirtualMethod(0);
- EXPECT_PRED2(String::EqualsUtf8, m1->GetName(), "m1");
-
- Method* m2 = klass->GetVirtualMethod(1);
- EXPECT_PRED2(String::EqualsUtf8, m2->GetName(), "m2");
-
- Method* m3 = klass->GetVirtualMethod(2);
- EXPECT_PRED2(String::EqualsUtf8, m3->GetName(), "m3");
-
- Method* m4 = klass->GetVirtualMethod(3);
- EXPECT_PRED2(String::EqualsUtf8, m4->GetName(), "m4");
-
- EXPECT_TRUE(linker->HasSameReturnType(m1, m2));
- EXPECT_TRUE(linker->HasSameReturnType(m2, m1));
-
- EXPECT_TRUE(linker->HasSameReturnType(m1, m2));
- EXPECT_TRUE(linker->HasSameReturnType(m2, m1));
-
- EXPECT_FALSE(linker->HasSameReturnType(m1, m4));
- EXPECT_FALSE(linker->HasSameReturnType(m4, m1));
-
- EXPECT_TRUE(linker->HasSameArgumentTypes(m1, m2));
- EXPECT_TRUE(linker->HasSameArgumentTypes(m2, m1));
-
- EXPECT_FALSE(linker->HasSameArgumentTypes(m1, m3));
- EXPECT_FALSE(linker->HasSameArgumentTypes(m3, m1));
-
- EXPECT_FALSE(linker->HasSameArgumentTypes(m1, m4));
- EXPECT_FALSE(linker->HasSameArgumentTypes(m4, m1));
-
- EXPECT_TRUE(linker->HasSamePrototype(m1, m2));
- EXPECT_TRUE(linker->HasSamePrototype(m2, m1));
-
- EXPECT_FALSE(linker->HasSamePrototype(m1, m3));
- EXPECT_FALSE(linker->HasSamePrototype(m3, m1));
-
- EXPECT_FALSE(linker->HasSamePrototype(m3, m4));
- EXPECT_FALSE(linker->HasSamePrototype(m4, m3));
-
- EXPECT_FALSE(linker->HasSameName(m1, m2));
- EXPECT_FALSE(linker->HasSameNameAndPrototype(m1, m2));
-}
-
-TEST_F(ClassLinkerTest, ProtoCompare2) {
- ClassLinker* linker = class_linker_;
-
- scoped_ptr<DexFile> proto1_dex_file(OpenDexFileBase64(kProtoCompareDex));
- PathClassLoader* class_loader_1 = AllocPathClassLoader(proto1_dex_file.get());
- scoped_ptr<DexFile> proto2_dex_file(OpenDexFileBase64(kProtoCompare2Dex));
- PathClassLoader* class_loader_2 = AllocPathClassLoader(proto2_dex_file.get());
-
- Class* klass1 = linker->FindClass("LProtoCompare;", class_loader_1);
- ASSERT_TRUE(klass1 != NULL);
- Class* klass2 = linker->FindClass("LProtoCompare2;", class_loader_2);
- ASSERT_TRUE(klass2 != NULL);
-
- Method* m1_1 = klass1->GetVirtualMethod(0);
- EXPECT_PRED2(String::EqualsUtf8, m1_1->GetName(), "m1");
- Method* m2_1 = klass1->GetVirtualMethod(1);
- EXPECT_PRED2(String::EqualsUtf8, m2_1->GetName(), "m2");
- Method* m3_1 = klass1->GetVirtualMethod(2);
- EXPECT_PRED2(String::EqualsUtf8, m3_1->GetName(), "m3");
- Method* m4_1 = klass1->GetVirtualMethod(3);
- EXPECT_PRED2(String::EqualsUtf8, m4_1->GetName(), "m4");
-
- Method* m1_2 = klass2->GetVirtualMethod(0);
- EXPECT_PRED2(String::EqualsUtf8, m1_2->GetName(), "m1");
- Method* m2_2 = klass2->GetVirtualMethod(1);
- EXPECT_PRED2(String::EqualsUtf8, m2_2->GetName(), "m2");
- Method* m3_2 = klass2->GetVirtualMethod(2);
- EXPECT_PRED2(String::EqualsUtf8, m3_2->GetName(), "m3");
- Method* m4_2 = klass2->GetVirtualMethod(3);
- EXPECT_PRED2(String::EqualsUtf8, m4_2->GetName(), "m4");
-
- EXPECT_TRUE(linker->HasSameNameAndPrototype(m1_1, m1_2));
- EXPECT_TRUE(linker->HasSameNameAndPrototype(m1_2, m1_1));
-
- EXPECT_TRUE(linker->HasSameNameAndPrototype(m2_1, m2_2));
- EXPECT_TRUE(linker->HasSameNameAndPrototype(m2_2, m2_1));
-
- EXPECT_TRUE(linker->HasSameNameAndPrototype(m3_1, m3_2));
- EXPECT_TRUE(linker->HasSameNameAndPrototype(m3_2, m3_1));
-
- EXPECT_TRUE(linker->HasSameNameAndPrototype(m4_1, m4_2));
- EXPECT_TRUE(linker->HasSameNameAndPrototype(m4_2, m4_1));
-}
-
TEST_F(ClassLinkerTest, LibCore) {
UseLibCoreDex();
scoped_ptr<DexFile> libcore_dex_file(GetLibCoreDex());
@@ -410,47 +312,47 @@
UseLibCoreDex();
Class* string = class_linker_->FindSystemClass( "Ljava/lang/String;");
ASSERT_EQ(4U, string->NumInstanceFields());
- EXPECT_PRED2(String::EqualsUtf8, string->GetInstanceField(0)->GetName(), "value");
- EXPECT_PRED2(String::EqualsUtf8, string->GetInstanceField(1)->GetName(), "hashCode");
- EXPECT_PRED2(String::EqualsUtf8, string->GetInstanceField(2)->GetName(), "offset");
- EXPECT_PRED2(String::EqualsUtf8, string->GetInstanceField(3)->GetName(), "count");
+ EXPECT_TRUE(string->GetInstanceField(0)->GetName()->Equals("value"));
+ EXPECT_TRUE(string->GetInstanceField(1)->GetName()->Equals("hashCode"));
+ EXPECT_TRUE(string->GetInstanceField(2)->GetName()->Equals("offset"));
+ EXPECT_TRUE(string->GetInstanceField(3)->GetName()->Equals("count"));
Class* accessible_object = class_linker_->FindSystemClass("Ljava/lang/reflect/AccessibleObject;");
ASSERT_EQ(1U, accessible_object->NumInstanceFields());
- EXPECT_PRED2(String::EqualsUtf8, accessible_object->GetInstanceField(0)->GetName(), "flag");
+ EXPECT_TRUE(accessible_object->GetInstanceField(0)->GetName()->Equals("flag"));
Class* field = class_linker_->FindSystemClass("Ljava/lang/reflect/Field;");
ASSERT_EQ(6U, field->NumInstanceFields());
- EXPECT_PRED2(String::EqualsUtf8, field->GetInstanceField(0)->GetName(), "declaringClass");
- EXPECT_PRED2(String::EqualsUtf8, field->GetInstanceField(1)->GetName(), "genericType");
- EXPECT_PRED2(String::EqualsUtf8, field->GetInstanceField(2)->GetName(), "type");
- EXPECT_PRED2(String::EqualsUtf8, field->GetInstanceField(3)->GetName(), "name");
- EXPECT_PRED2(String::EqualsUtf8, field->GetInstanceField(4)->GetName(), "slot");
- EXPECT_PRED2(String::EqualsUtf8, field->GetInstanceField(5)->GetName(), "genericTypesAreInitialized");
+ EXPECT_TRUE(field->GetInstanceField(0)->GetName()->Equals("declaringClass"));
+ EXPECT_TRUE(field->GetInstanceField(1)->GetName()->Equals("genericType"));
+ EXPECT_TRUE(field->GetInstanceField(2)->GetName()->Equals("type"));
+ EXPECT_TRUE(field->GetInstanceField(3)->GetName()->Equals("name"));
+ EXPECT_TRUE(field->GetInstanceField(4)->GetName()->Equals("slot"));
+ EXPECT_TRUE(field->GetInstanceField(5)->GetName()->Equals("genericTypesAreInitialized"));
Class* method = class_linker_->FindSystemClass("Ljava/lang/reflect/Method;");
ASSERT_EQ(11U, method->NumInstanceFields());
- EXPECT_PRED2(String::EqualsUtf8, method->GetInstanceField( 0)->GetName(), "declaringClass");
- EXPECT_PRED2(String::EqualsUtf8, method->GetInstanceField( 1)->GetName(), "exceptionTypes");
- EXPECT_PRED2(String::EqualsUtf8, method->GetInstanceField( 2)->GetName(), "formalTypeParameters");
- EXPECT_PRED2(String::EqualsUtf8, method->GetInstanceField( 3)->GetName(), "genericExceptionTypes");
- EXPECT_PRED2(String::EqualsUtf8, method->GetInstanceField( 4)->GetName(), "genericParameterTypes");
- EXPECT_PRED2(String::EqualsUtf8, method->GetInstanceField( 5)->GetName(), "genericReturnType");
- EXPECT_PRED2(String::EqualsUtf8, method->GetInstanceField( 6)->GetName(), "returnType");
- EXPECT_PRED2(String::EqualsUtf8, method->GetInstanceField( 7)->GetName(), "name");
- EXPECT_PRED2(String::EqualsUtf8, method->GetInstanceField( 8)->GetName(), "parameterTypes");
- EXPECT_PRED2(String::EqualsUtf8, method->GetInstanceField( 9)->GetName(), "genericTypesAreInitialized");
- EXPECT_PRED2(String::EqualsUtf8, method->GetInstanceField(10)->GetName(), "slot");
+ EXPECT_TRUE(method->GetInstanceField( 0)->GetName()->Equals("declaringClass"));
+ EXPECT_TRUE(method->GetInstanceField( 1)->GetName()->Equals("exceptionTypes"));
+ EXPECT_TRUE(method->GetInstanceField( 2)->GetName()->Equals("formalTypeParameters"));
+ EXPECT_TRUE(method->GetInstanceField( 3)->GetName()->Equals("genericExceptionTypes"));
+ EXPECT_TRUE(method->GetInstanceField( 4)->GetName()->Equals("genericParameterTypes"));
+ EXPECT_TRUE(method->GetInstanceField( 5)->GetName()->Equals("genericReturnType"));
+ EXPECT_TRUE(method->GetInstanceField( 6)->GetName()->Equals("returnType"));
+ EXPECT_TRUE(method->GetInstanceField( 7)->GetName()->Equals("name"));
+ EXPECT_TRUE(method->GetInstanceField( 8)->GetName()->Equals("parameterTypes"));
+ EXPECT_TRUE(method->GetInstanceField( 9)->GetName()->Equals("genericTypesAreInitialized"));
+ EXPECT_TRUE(method->GetInstanceField(10)->GetName()->Equals("slot"));
Class* class_loader = class_linker_->FindSystemClass("Ljava/lang/ClassLoader;");
ASSERT_EQ(2U, class_loader->NumInstanceFields());
- EXPECT_PRED2(String::EqualsUtf8, class_loader->GetInstanceField(0)->GetName(), "packages");
- EXPECT_PRED2(String::EqualsUtf8, class_loader->GetInstanceField(1)->GetName(), "parent");
+ EXPECT_TRUE(class_loader->GetInstanceField(0)->GetName()->Equals("packages"));
+ EXPECT_TRUE(class_loader->GetInstanceField(1)->GetName()->Equals("parent"));
Class* dex_base_class_loader = class_linker_->FindSystemClass("Ldalvik/system/BaseDexClassLoader;");
ASSERT_EQ(2U, dex_base_class_loader->NumInstanceFields());
- EXPECT_PRED2(String::EqualsUtf8, dex_base_class_loader->GetInstanceField(0)->GetName(), "originalPath");
- EXPECT_PRED2(String::EqualsUtf8, dex_base_class_loader->GetInstanceField(1)->GetName(), "pathList");
+ EXPECT_TRUE(dex_base_class_loader->GetInstanceField(0)->GetName()->Equals("originalPath"));
+ EXPECT_TRUE(dex_base_class_loader->GetInstanceField(1)->GetName()->Equals("pathList"));
}
TEST_F(ClassLinkerTest, TwoClassLoadersOneClass) {
diff --git a/src/jni_compiler_test.cc b/src/jni_compiler_test.cc
index 79806f6..7677a7a 100644
--- a/src/jni_compiler_test.cc
+++ b/src/jni_compiler_test.cc
@@ -508,7 +508,7 @@
int gSuspendCounterHandler_calls;
void SuspendCountHandler(Method** frame) {
- EXPECT_PRED2(String::EqualsUtf8, (*frame)->GetName(), "fooI");
+ EXPECT_TRUE((*frame)->GetName()->Equals("fooI"));
gSuspendCounterHandler_calls++;
Thread::Current()->DecrementSuspendCount();
}
@@ -553,7 +553,7 @@
int gExceptionHandler_calls;
void ExceptionHandler(Method** frame) {
- EXPECT_PRED2(String::EqualsUtf8, (*frame)->GetName(), "foo");
+ EXPECT_TRUE((*frame)->GetName()->Equals("foo"));
gExceptionHandler_calls++;
Thread::Current()->ClearException();
}
diff --git a/src/object.cc b/src/object.cc
index 98b6e43..2369954 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -157,12 +157,17 @@
return ShortyCharToSize(shorty_[0]);
}
+bool Method::HasSameNameAndDescriptor(const Method* that) const {
+ return (this->GetName()->Equals(that->GetName()) &&
+ this->GetDescriptor()->Equals(that->GetDescriptor()));
+}
+
Method* Class::FindDeclaredDirectMethod(const StringPiece& name,
const StringPiece& descriptor) {
for (size_t i = 0; i < NumDirectMethods(); ++i) {
Method* method = GetDirectMethod(i);
- if (String::EqualsUtf8(method->GetName(), name.data()) &&
- String::EqualsUtf8(method->GetDescriptor(), descriptor.data())) {
+ if (method->GetName()->Equals(name) &&
+ method->GetDescriptor()->Equals(descriptor)) {
return method;
}
}
@@ -184,8 +189,8 @@
const StringPiece& descriptor) {
for (size_t i = 0; i < NumVirtualMethods(); ++i) {
Method* method = GetVirtualMethod(i);
- if (String::EqualsUtf8(method->GetName(), name.data()) &&
- String::EqualsUtf8(method->GetDescriptor(), descriptor.data())) {
+ if (method->GetName()->Equals(name) &&
+ method->GetDescriptor()->Equals(descriptor)) {
return method;
}
}
diff --git a/src/object.h b/src/object.h
index d0f4a63..0e0728d 100644
--- a/src/object.h
+++ b/src/object.h
@@ -395,11 +395,6 @@
return MemberOffset(OFFSETOF_MEMBER(Method, klass_));
}
- // const char* GetReturnTypeDescriptor() const {
- // return FindDexFile(declaring_class_->GetDexCache()
- // ->dexStringByTypeIdx(proto_id_.return_type_id_);
- // }
-
// Returns true if the method is declared public.
bool IsPublic() const {
return (access_flags_ & kAccPublic) != 0;
@@ -525,6 +520,8 @@
return MemberOffset(OFFSETOF_MEMBER(Method, native_method_));
}
+ bool HasSameNameAndDescriptor(const Method* that) const;
+
public: // TODO: private/const
// the class we are a part of
Class* declaring_class_;
@@ -1110,6 +1107,26 @@
class String : public Object {
public:
+ const CharArray* GetCharArray() const {
+ return array_;
+ }
+
+ uint32_t GetHashCode() const {
+ return hash_code_;
+ }
+
+ uint32_t GetOffset() const {
+ return offset_;
+ }
+
+ uint32_t GetLength() const {
+ return count_;
+ }
+
+ uint16_t CharAt(uint32_t index) const {
+ return GetCharArray()->GetChar(index + GetOffset());
+ }
+
static String* AllocFromUtf16(Class* java_lang_String,
Class* char_array,
int32_t utf16_length,
@@ -1151,16 +1168,6 @@
return AllocFromModifiedUtf8(java_lang_String_, char_array_, utf16_length, utf8_data_in);
}
- public: // TODO: private
- // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
- CharArray* array_;
-
- int32_t hash_code_;
-
- int32_t offset_;
-
- int32_t count_;
-
static void InitClasses(Class* java_lang_String, Class* char_array);
static String* Alloc(Class* java_lang_String,
@@ -1251,29 +1258,27 @@
return hash;
}
- static bool EqualsUtf8(const String* string, const char* other) {
- uint16_t* chars = string->array_->GetChars();
- for (int32_t i = 0; i < string->count_; i++) {
- uint16_t c = GetUtf16FromUtf8(&other);
- if (c == '\0' || c != chars[string->offset_ + i]) {
+ bool Equals(const char* modified_utf8) const {
+ for (size_t i = 0; i < GetLength(); ++i) {
+ uint16_t ch = GetUtf16FromUtf8(&modified_utf8);
+ if (ch == '\0' || ch != CharAt(i)) {
return false;
}
}
- return *other == '\0';
+ return *modified_utf8 == '\0';
}
- static bool Equals(const String* a, const String* b) {
- // TODO short circuit on hash_code_
- int32_t a_count = a->count_;
- if (a_count != b->count_) {
+ bool Equals(const StringPiece& modified_utf8) const {
+ // TODO: do not assume C-string representation.
+ return Equals(modified_utf8.data());
+ }
+
+ bool Equals(const String* that) const {
+ if (this->GetLength() != that->GetLength()) {
return false;
}
- int32_t a_offset = a->offset_;
- int32_t b_offset = b->offset_;
- uint16_t* a_chars = a->array_->GetChars();
- uint16_t* b_chars = b->array_->GetChars();
- for (int32_t i = 0; i < a_count; i++) {
- if (a_chars[a_offset + i] != b_chars[b_offset + i]) {
+ for (size_t i = 0; i < that->GetLength(); ++i) {
+ if (this->CharAt(i) != that->CharAt(i)) {
return false;
}
}
@@ -1281,10 +1286,19 @@
}
private:
- String();
+ // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
+ CharArray* array_;
+
+ uint32_t hash_code_;
+
+ uint32_t offset_;
+
+ uint32_t count_;
static Class* java_lang_String_;
static Class* char_array_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(String);
};
class InterfaceEntry {
diff --git a/src/object_test.cc b/src/object_test.cc
index d240d0c..18e8e77 100644
--- a/src/object_test.cc
+++ b/src/object_test.cc
@@ -19,7 +19,7 @@
void AssertString(size_t length,
const char* utf8_in,
const char* utf16_expected_le,
- int32_t hash_expected) {
+ uint32_t hash_expected) {
uint16_t utf16_expected[length];
for (size_t i = 0; i < length; i++) {
uint16_t ch = (((utf16_expected_le[i*2 + 0] & 0xff) << 8) |
@@ -28,15 +28,15 @@
}
String* string = String::AllocFromModifiedUtf8(length, utf8_in);
- ASSERT_EQ(length, static_cast<size_t>(string->count_));
- ASSERT_TRUE(string->array_ != NULL);
- ASSERT_TRUE(string->array_->GetChars() != NULL);
+ ASSERT_EQ(length, string->GetLength());
+ ASSERT_TRUE(string->GetCharArray() != NULL);
+ ASSERT_TRUE(string->GetCharArray()->GetChars() != NULL);
// strlen is necessary because the 1-character string "\0" is interpreted as ""
- ASSERT_TRUE(String::EqualsUtf8(string, utf8_in) || length != strlen(utf8_in));
+ ASSERT_TRUE(string->Equals(utf8_in) || length != strlen(utf8_in));
for (size_t i = 0; i < length; i++) {
- EXPECT_EQ(utf16_expected[i], string->array_->GetChar(i));
+ EXPECT_EQ(utf16_expected[i], string->GetCharArray()->GetChar(i));
}
- EXPECT_EQ(hash_expected, string->hash_code_);
+ EXPECT_EQ(hash_expected, string->GetHashCode());
}
};
@@ -90,40 +90,76 @@
AssertString(3, "h\xe1\x88\xb4i", "\x00\x68\x12\x34\x00\x69", (31 * ((31 * 0x68) + 0x1234)) + 0x69);
}
-static bool StringNotEqualsUtf8(const String* a, const char* b) {
- return !String::EqualsUtf8(a, b);
-}
-
TEST_F(ObjectTest, StringEqualsUtf8) {
String* string = String::AllocFromAscii("android");
- EXPECT_PRED2(String::EqualsUtf8, string, "android");
- EXPECT_PRED2(StringNotEqualsUtf8, string, "Android");
- EXPECT_PRED2(StringNotEqualsUtf8, string, "ANDROID");
- EXPECT_PRED2(StringNotEqualsUtf8, string, "");
- EXPECT_PRED2(StringNotEqualsUtf8, string, "and");
- EXPECT_PRED2(StringNotEqualsUtf8, string, "androids");
+ EXPECT_TRUE(string->Equals("android"));
+ EXPECT_FALSE(string->Equals("Android"));
+ EXPECT_FALSE(string->Equals("ANDROID"));
+ EXPECT_FALSE(string->Equals(""));
+ EXPECT_FALSE(string->Equals("and"));
+ EXPECT_FALSE(string->Equals("androids"));
String* empty = String::AllocFromAscii("");
- EXPECT_PRED2(String::EqualsUtf8, empty, "");
- EXPECT_PRED2(StringNotEqualsUtf8, empty, "a");
-}
-
-static bool StringNotEquals(const String* a, const String* b) {
- return !String::Equals(a, b);
+ EXPECT_TRUE(empty->Equals(""));
+ EXPECT_FALSE(empty->Equals("a"));
}
TEST_F(ObjectTest, StringEquals) {
String* string = String::AllocFromAscii("android");
- EXPECT_PRED2(String::Equals, string, String::AllocFromAscii("android"));
- EXPECT_PRED2(StringNotEquals, string, String::AllocFromAscii("Android"));
- EXPECT_PRED2(StringNotEquals, string, String::AllocFromAscii("ANDROID"));
- EXPECT_PRED2(StringNotEquals, string, String::AllocFromAscii(""));
- EXPECT_PRED2(StringNotEquals, string, String::AllocFromAscii("and"));
- EXPECT_PRED2(StringNotEquals, string, String::AllocFromAscii("androids"));
+ EXPECT_TRUE(string->Equals(String::AllocFromAscii("android")));
+ EXPECT_FALSE(string->Equals("Android"));
+ EXPECT_FALSE(string->Equals("ANDROID"));
+ EXPECT_FALSE(string->Equals(""));
+ EXPECT_FALSE(string->Equals("and"));
+ EXPECT_FALSE(string->Equals("androids"));
String* empty = String::AllocFromAscii("");
- EXPECT_PRED2(String::Equals, empty, String::AllocFromAscii(""));
- EXPECT_PRED2(StringNotEquals, empty, String::AllocFromAscii("a"));
+ EXPECT_TRUE(empty->Equals(""));
+ EXPECT_FALSE(empty->Equals("a"));
+}
+
+TEST_F(ObjectTest, DescriptorCompare) {
+ ClassLinker* linker = class_linker_;
+
+ scoped_ptr<DexFile> proto1_dex_file(OpenDexFileBase64(kProtoCompareDex));
+ PathClassLoader* class_loader_1 = AllocPathClassLoader(proto1_dex_file.get());
+ scoped_ptr<DexFile> proto2_dex_file(OpenDexFileBase64(kProtoCompare2Dex));
+ PathClassLoader* class_loader_2 = AllocPathClassLoader(proto2_dex_file.get());
+
+ Class* klass1 = linker->FindClass("LProtoCompare;", class_loader_1);
+ ASSERT_TRUE(klass1 != NULL);
+ Class* klass2 = linker->FindClass("LProtoCompare2;", class_loader_2);
+ ASSERT_TRUE(klass2 != NULL);
+
+ Method* m1_1 = klass1->GetVirtualMethod(0);
+ EXPECT_TRUE(m1_1->GetName()->Equals("m1"));
+ Method* m2_1 = klass1->GetVirtualMethod(1);
+ EXPECT_TRUE(m2_1->GetName()->Equals("m2"));
+ Method* m3_1 = klass1->GetVirtualMethod(2);
+ EXPECT_TRUE(m3_1->GetName()->Equals("m3"));
+ Method* m4_1 = klass1->GetVirtualMethod(3);
+ EXPECT_TRUE(m4_1->GetName()->Equals("m4"));
+
+ Method* m1_2 = klass2->GetVirtualMethod(0);
+ EXPECT_TRUE(m1_2->GetName()->Equals("m1"));
+ Method* m2_2 = klass2->GetVirtualMethod(1);
+ EXPECT_TRUE(m2_2->GetName()->Equals("m2"));
+ Method* m3_2 = klass2->GetVirtualMethod(2);
+ EXPECT_TRUE(m3_2->GetName()->Equals("m3"));
+ Method* m4_2 = klass2->GetVirtualMethod(3);
+ EXPECT_TRUE(m4_2->GetName()->Equals("m4"));
+
+ EXPECT_TRUE(m1_1->HasSameNameAndDescriptor(m1_2));
+ EXPECT_TRUE(m1_2->HasSameNameAndDescriptor(m1_1));
+
+ EXPECT_TRUE(m2_1->HasSameNameAndDescriptor(m2_2));
+ EXPECT_TRUE(m2_2->HasSameNameAndDescriptor(m2_1));
+
+ EXPECT_TRUE(m3_1->HasSameNameAndDescriptor(m3_2));
+ EXPECT_TRUE(m3_2->HasSameNameAndDescriptor(m3_1));
+
+ EXPECT_TRUE(m4_1->HasSameNameAndDescriptor(m4_2));
+ EXPECT_TRUE(m4_2->HasSameNameAndDescriptor(m4_1));
}
} // namespace art