diff options
Diffstat (limited to 'runtime')
-rw-r--r-- | runtime/class_linker.cc | 51 | ||||
-rw-r--r-- | runtime/class_linker.h | 2 | ||||
-rw-r--r-- | runtime/class_linker_test.cc | 138 | ||||
-rw-r--r-- | runtime/image.cc | 2 | ||||
-rw-r--r-- | runtime/mirror/class.cc | 7 | ||||
-rw-r--r-- | runtime/mirror/class.h | 40 | ||||
-rw-r--r-- | runtime/mirror/object-inl.h | 20 | ||||
-rw-r--r-- | runtime/mirror/object.h | 4 | ||||
-rw-r--r-- | runtime/mirror/object_test.cc | 3 |
9 files changed, 122 insertions, 145 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 6ed27bb945..c3290f2688 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -5191,36 +5191,31 @@ bool ClassLinker::LinkFields(Thread* self, Handle<mirror::Class> klass, bool is_ void ClassLinker::CreateReferenceInstanceOffsets(Handle<mirror::Class> klass) { uint32_t reference_offsets = 0; mirror::Class* super_class = klass->GetSuperClass(); + // Leave the reference offsets as 0 for mirror::Object (the class field is handled specially). if (super_class != nullptr) { reference_offsets = super_class->GetReferenceInstanceOffsets(); - // If our superclass overflowed, we don't stand a chance. - if (reference_offsets == CLASS_WALK_SUPER) { - klass->SetReferenceInstanceOffsets(reference_offsets); - return; - } - } - CreateReferenceOffsets(klass, reference_offsets); -} - -void ClassLinker::CreateReferenceOffsets(Handle<mirror::Class> klass, - uint32_t reference_offsets) { - size_t num_reference_fields = klass->NumReferenceInstanceFieldsDuringLinking(); - mirror::ObjectArray<mirror::ArtField>* fields = klass->GetIFields(); - // All of the fields that contain object references are guaranteed - // to be at the beginning of the fields list. - for (size_t i = 0; i < num_reference_fields; ++i) { - // Note that byte_offset is the offset from the beginning of - // object, not the offset into instance data - mirror::ArtField* field = fields->Get(i); - MemberOffset byte_offset = field->GetOffsetDuringLinking(); - CHECK_EQ(byte_offset.Uint32Value() & (CLASS_OFFSET_ALIGNMENT - 1), 0U); - if (CLASS_CAN_ENCODE_OFFSET(byte_offset.Uint32Value())) { - uint32_t new_bit = CLASS_BIT_FROM_OFFSET(byte_offset.Uint32Value()); - CHECK_NE(new_bit, 0U); - reference_offsets |= new_bit; - } else { - reference_offsets = CLASS_WALK_SUPER; - break; + // Compute reference offsets unless our superclass overflowed. + if (reference_offsets != mirror::Class::kClassWalkSuper) { + size_t num_reference_fields = klass->NumReferenceInstanceFieldsDuringLinking(); + mirror::ObjectArray<mirror::ArtField>* fields = klass->GetIFields(); + // All of the fields that contain object references are guaranteed + // to be at the beginning of the fields list. + for (size_t i = 0; i < num_reference_fields; ++i) { + // Note that byte_offset is the offset from the beginning of + // object, not the offset into instance data + mirror::ArtField* field = fields->Get(i); + MemberOffset byte_offset = field->GetOffsetDuringLinking(); + uint32_t displaced_bitmap_position = + (byte_offset.Uint32Value() - mirror::kObjectHeaderSize) / + sizeof(mirror::HeapReference<mirror::Object>); + if (displaced_bitmap_position >= 32) { + // Can't encode offset so fall back on slow-path. + reference_offsets = mirror::Class::kClassWalkSuper; + break; + } else { + reference_offsets |= (1 << displaced_bitmap_position); + } + } } } klass->SetReferenceInstanceOffsets(reference_offsets); diff --git a/runtime/class_linker.h b/runtime/class_linker.h index 111dd6369e..cc75530cc8 100644 --- a/runtime/class_linker.h +++ b/runtime/class_linker.h @@ -539,8 +539,6 @@ class ClassLinker { SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void CreateReferenceInstanceOffsets(Handle<mirror::Class> klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void CreateReferenceOffsets(Handle<mirror::Class> klass, uint32_t reference_offsets) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // For use by ImageWriter to find DexCaches for its roots ReaderWriterMutex* DexLock() diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc index 613ac66843..e990181aa8 100644 --- a/runtime/class_linker_test.cc +++ b/runtime/class_linker_test.cc @@ -47,9 +47,9 @@ class ClassLinkerTest : public CommonRuntimeTest { void AssertNonExistentClass(const std::string& descriptor) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { Thread* self = Thread::Current(); - EXPECT_TRUE(class_linker_->FindSystemClass(self, descriptor.c_str()) == NULL); + EXPECT_TRUE(class_linker_->FindSystemClass(self, descriptor.c_str()) == nullptr); EXPECT_TRUE(self->IsExceptionPending()); - mirror::Object* exception = self->GetException(NULL); + mirror::Object* exception = self->GetException(nullptr); self->ClearException(); mirror::Class* exception_class = class_linker_->FindSystemClass(self, "Ljava/lang/NoClassDefFoundError;"); @@ -64,15 +64,15 @@ class ClassLinkerTest : public CommonRuntimeTest { void AssertPrimitiveClass(const std::string& descriptor, mirror::Class* primitive) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - ASSERT_TRUE(primitive != NULL); - ASSERT_TRUE(primitive->GetClass() != NULL); + ASSERT_TRUE(primitive != nullptr); + ASSERT_TRUE(primitive->GetClass() != nullptr); ASSERT_EQ(primitive->GetClass(), primitive->GetClass()->GetClass()); - EXPECT_TRUE(primitive->GetClass()->GetSuperClass() != NULL); + EXPECT_TRUE(primitive->GetClass()->GetSuperClass() != nullptr); std::string temp; ASSERT_STREQ(descriptor.c_str(), primitive->GetDescriptor(&temp)); - EXPECT_TRUE(primitive->GetSuperClass() == NULL); + EXPECT_TRUE(primitive->GetSuperClass() == nullptr); EXPECT_FALSE(primitive->HasSuperClass()); - EXPECT_TRUE(primitive->GetClassLoader() == NULL); + EXPECT_TRUE(primitive->GetClassLoader() == nullptr); EXPECT_EQ(mirror::Class::kStatusInitialized, primitive->GetStatus()); EXPECT_FALSE(primitive->IsErroneous()); EXPECT_TRUE(primitive->IsLoaded()); @@ -81,7 +81,7 @@ class ClassLinkerTest : public CommonRuntimeTest { EXPECT_TRUE(primitive->IsInitialized()); EXPECT_FALSE(primitive->IsArrayInstance()); EXPECT_FALSE(primitive->IsArrayClass()); - EXPECT_TRUE(primitive->GetComponentType() == NULL); + EXPECT_TRUE(primitive->GetComponentType() == nullptr); EXPECT_FALSE(primitive->IsInterface()); EXPECT_TRUE(primitive->IsPublic()); EXPECT_TRUE(primitive->IsFinal()); @@ -94,7 +94,7 @@ class ClassLinkerTest : public CommonRuntimeTest { EXPECT_EQ(0U, primitive->NumDirectInterfaces()); EXPECT_FALSE(primitive->HasVTable()); EXPECT_EQ(0, primitive->GetIfTableCount()); - EXPECT_TRUE(primitive->GetIfTable() == NULL); + EXPECT_TRUE(primitive->GetIfTable() == nullptr); EXPECT_EQ(kAccPublic | kAccFinal | kAccAbstract, primitive->GetAccessFlags()); } @@ -116,17 +116,17 @@ class ClassLinkerTest : public CommonRuntimeTest { void AssertArrayClass(const std::string& array_descriptor, Handle<mirror::Class> array) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - ASSERT_TRUE(array.Get() != NULL); - ASSERT_TRUE(array->GetClass() != NULL); + ASSERT_TRUE(array.Get() != nullptr); + ASSERT_TRUE(array->GetClass() != nullptr); ASSERT_EQ(array->GetClass(), array->GetClass()->GetClass()); - EXPECT_TRUE(array->GetClass()->GetSuperClass() != NULL); + EXPECT_TRUE(array->GetClass()->GetSuperClass() != nullptr); std::string temp; ASSERT_STREQ(array_descriptor.c_str(), array->GetDescriptor(&temp)); - EXPECT_TRUE(array->GetSuperClass() != NULL); + EXPECT_TRUE(array->GetSuperClass() != nullptr); Thread* self = Thread::Current(); EXPECT_EQ(class_linker_->FindSystemClass(self, "Ljava/lang/Object;"), array->GetSuperClass()); EXPECT_TRUE(array->HasSuperClass()); - ASSERT_TRUE(array->GetComponentType() != NULL); + ASSERT_TRUE(array->GetComponentType() != nullptr); ASSERT_GT(strlen(array->GetComponentType()->GetDescriptor(&temp)), 0U); EXPECT_EQ(mirror::Class::kStatusInitialized, array->GetStatus()); EXPECT_FALSE(array->IsErroneous()); @@ -148,7 +148,7 @@ class ClassLinkerTest : public CommonRuntimeTest { EXPECT_EQ(2U, array->NumDirectInterfaces()); EXPECT_TRUE(array->ShouldHaveEmbeddedImtAndVTable()); EXPECT_EQ(2, array->GetIfTableCount()); - ASSERT_TRUE(array->GetIfTable() != NULL); + ASSERT_TRUE(array->GetIfTable() != nullptr); mirror::Class* direct_interface0 = mirror::Class::GetDirectInterface(self, array, 0); EXPECT_TRUE(direct_interface0 != nullptr); EXPECT_STREQ(direct_interface0->GetDescriptor(&temp), "Ljava/lang/Cloneable;"); @@ -177,13 +177,13 @@ class ClassLinkerTest : public CommonRuntimeTest { void AssertField(mirror::Class* klass, mirror::ArtField* field) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - EXPECT_TRUE(field != NULL); - EXPECT_TRUE(field->GetClass() != NULL); + EXPECT_TRUE(field != nullptr); + EXPECT_TRUE(field->GetClass() != nullptr); EXPECT_EQ(klass, field->GetDeclaringClass()); - EXPECT_TRUE(field->GetName() != NULL); + EXPECT_TRUE(field->GetName() != nullptr); StackHandleScope<1> hs(Thread::Current()); FieldHelper fh(hs.NewHandle(field)); - EXPECT_TRUE(fh.GetType() != NULL); + EXPECT_TRUE(fh.GetType() != nullptr); } void AssertClass(const std::string& descriptor, Handle<mirror::Class> klass) @@ -194,16 +194,16 @@ class ClassLinkerTest : public CommonRuntimeTest { EXPECT_FALSE(klass->HasSuperClass()); } else { EXPECT_TRUE(klass->HasSuperClass()); - EXPECT_TRUE(klass->GetSuperClass() != NULL); + EXPECT_TRUE(klass->GetSuperClass() != nullptr); } - EXPECT_TRUE(klass->GetClass() != NULL); + EXPECT_TRUE(klass->GetClass() != nullptr); EXPECT_EQ(klass->GetClass(), klass->GetClass()->GetClass()); - EXPECT_TRUE(klass->GetDexCache() != NULL); + EXPECT_TRUE(klass->GetDexCache() != nullptr); EXPECT_TRUE(klass->IsLoaded()); EXPECT_TRUE(klass->IsResolved()); EXPECT_FALSE(klass->IsErroneous()); EXPECT_FALSE(klass->IsArrayClass()); - EXPECT_TRUE(klass->GetComponentType() == NULL); + EXPECT_TRUE(klass->GetComponentType() == nullptr); EXPECT_TRUE(klass->IsInSamePackage(klass.Get())); std::string temp2; EXPECT_TRUE(mirror::Class::IsInSamePackage(klass->GetDescriptor(&temp), @@ -225,7 +225,7 @@ class ClassLinkerTest : public CommonRuntimeTest { mirror::IfTable* iftable = klass->GetIfTable(); for (int i = 0; i < klass->GetIfTableCount(); i++) { mirror::Class* interface = iftable->GetInterface(i); - ASSERT_TRUE(interface != NULL); + ASSERT_TRUE(interface != nullptr); if (klass->IsInterface()) { EXPECT_EQ(0U, iftable->GetMethodArrayCount(i)); } else { @@ -285,7 +285,7 @@ class ClassLinkerTest : public CommonRuntimeTest { FieldHelper fh(fhandle); ASSERT_TRUE(!field->IsPrimitiveType()); mirror::Class* field_type = fh.GetType(); - ASSERT_TRUE(field_type != NULL); + ASSERT_TRUE(field_type != nullptr); ASSERT_TRUE(!field_type->IsPrimitive()); } for (size_t i = klass->NumReferenceInstanceFields(); i < klass->NumInstanceFields(); i++) { @@ -293,7 +293,7 @@ class ClassLinkerTest : public CommonRuntimeTest { fhandle.Assign(field); FieldHelper fh(fhandle); mirror::Class* field_type = fh.GetType(); - ASSERT_TRUE(field_type != NULL); + ASSERT_TRUE(field_type != nullptr); if (!fh.GetField()->IsPrimitiveType() || !field_type->IsPrimitive()) { // While Reference.referent is not primitive, the ClassLinker // treats it as such so that the garbage collector won't scan it. @@ -301,18 +301,24 @@ class ClassLinkerTest : public CommonRuntimeTest { } } - size_t total_num_reference_instance_fields = 0; + uint32_t total_num_reference_instance_fields = 0; mirror::Class* k = klass.Get(); - while (k != NULL) { + while (k != nullptr) { total_num_reference_instance_fields += k->NumReferenceInstanceFields(); k = k->GetSuperClass(); } - EXPECT_EQ(klass->GetReferenceInstanceOffsets() == 0, total_num_reference_instance_fields == 0); + EXPECT_GE(total_num_reference_instance_fields, 1U); // Should always have Object's class. + if (klass->GetReferenceInstanceOffsets() != mirror::Class::kClassWalkSuper) { + // The reference instance offsets have a bit set for each reference offset. + // +1 for Object's class. + EXPECT_EQ(static_cast<uint32_t>(POPCOUNT(klass->GetReferenceInstanceOffsets())) + 1, + total_num_reference_instance_fields); + } } void AssertDexFileClass(mirror::ClassLoader* class_loader, const std::string& descriptor) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - ASSERT_TRUE(descriptor != NULL); + ASSERT_TRUE(descriptor != nullptr); Thread* self = Thread::Current(); StackHandleScope<1> hs(self); Handle<mirror::Class> klass( @@ -332,7 +338,7 @@ class ClassLinkerTest : public CommonRuntimeTest { void AssertDexFile(const DexFile* dex, mirror::ClassLoader* class_loader) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - ASSERT_TRUE(dex != NULL); + ASSERT_TRUE(dex != nullptr); // Verify all the classes defined in this file for (size_t i = 0; i < dex->NumClassDefs(); i++) { @@ -346,17 +352,17 @@ class ClassLinkerTest : public CommonRuntimeTest { const char* descriptor = dex->GetTypeDescriptor(type_id); AssertDexFileClass(class_loader, descriptor); } - class_linker_->VisitRoots(TestRootVisitor, NULL, kVisitRootFlagAllRoots); + class_linker_->VisitRoots(TestRootVisitor, nullptr, kVisitRootFlagAllRoots); // Verify the dex cache has resolution methods in all resolved method slots mirror::DexCache* dex_cache = class_linker_->FindDexCache(*dex); mirror::ObjectArray<mirror::ArtMethod>* resolved_methods = dex_cache->GetResolvedMethods(); for (size_t i = 0; i < static_cast<size_t>(resolved_methods->GetLength()); i++) { - EXPECT_TRUE(resolved_methods->Get(i) != NULL) << dex->GetLocation() << " i=" << i; + EXPECT_TRUE(resolved_methods->Get(i) != nullptr) << dex->GetLocation() << " i=" << i; } } static void TestRootVisitor(mirror::Object** root, void*, uint32_t, RootType) { - EXPECT_TRUE(*root != NULL); + EXPECT_TRUE(*root != nullptr); } }; @@ -378,7 +384,7 @@ struct CheckOffsets { Thread* self = Thread::Current(); mirror::Class* klass = Runtime::Current()->GetClassLinker()->FindSystemClass(self, class_descriptor.c_str()); - CHECK(klass != NULL) << class_descriptor; + CHECK(klass != nullptr) << class_descriptor; bool error = false; @@ -647,12 +653,12 @@ TEST_F(ClassLinkerTest, FindClassNested) { hs.NewHandle(soa.Decode<mirror::ClassLoader*>(LoadDex("Nested")))); mirror::Class* outer = class_linker_->FindClass(soa.Self(), "LNested;", class_loader); - ASSERT_TRUE(outer != NULL); + ASSERT_TRUE(outer != nullptr); EXPECT_EQ(0U, outer->NumVirtualMethods()); EXPECT_EQ(1U, outer->NumDirectMethods()); mirror::Class* inner = class_linker_->FindClass(soa.Self(), "LNested$Inner;", class_loader); - ASSERT_TRUE(inner != NULL); + ASSERT_TRUE(inner != nullptr); EXPECT_EQ(0U, inner->NumVirtualMethods()); EXPECT_EQ(1U, inner->NumDirectMethods()); } @@ -674,15 +680,15 @@ TEST_F(ClassLinkerTest, FindClass_Primitives) { TEST_F(ClassLinkerTest, FindClass) { ScopedObjectAccess soa(Thread::Current()); mirror::Class* JavaLangObject = class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;"); - ASSERT_TRUE(JavaLangObject != NULL); - ASSERT_TRUE(JavaLangObject->GetClass() != NULL); + ASSERT_TRUE(JavaLangObject != nullptr); + ASSERT_TRUE(JavaLangObject->GetClass() != nullptr); ASSERT_EQ(JavaLangObject->GetClass(), JavaLangObject->GetClass()->GetClass()); EXPECT_EQ(JavaLangObject, JavaLangObject->GetClass()->GetSuperClass()); std::string temp; ASSERT_STREQ(JavaLangObject->GetDescriptor(&temp), "Ljava/lang/Object;"); - EXPECT_TRUE(JavaLangObject->GetSuperClass() == NULL); + EXPECT_TRUE(JavaLangObject->GetSuperClass() == nullptr); EXPECT_FALSE(JavaLangObject->HasSuperClass()); - EXPECT_TRUE(JavaLangObject->GetClassLoader() == NULL); + EXPECT_TRUE(JavaLangObject->GetClassLoader() == nullptr); EXPECT_EQ(mirror::Class::kStatusInitialized, JavaLangObject->GetStatus()); EXPECT_FALSE(JavaLangObject->IsErroneous()); EXPECT_TRUE(JavaLangObject->IsLoaded()); @@ -691,7 +697,7 @@ TEST_F(ClassLinkerTest, FindClass) { EXPECT_TRUE(JavaLangObject->IsInitialized()); EXPECT_FALSE(JavaLangObject->IsArrayInstance()); EXPECT_FALSE(JavaLangObject->IsArrayClass()); - EXPECT_TRUE(JavaLangObject->GetComponentType() == NULL); + EXPECT_TRUE(JavaLangObject->GetComponentType() == nullptr); EXPECT_FALSE(JavaLangObject->IsInterface()); EXPECT_TRUE(JavaLangObject->IsPublic()); EXPECT_FALSE(JavaLangObject->IsFinal()); @@ -719,8 +725,8 @@ TEST_F(ClassLinkerTest, FindClass) { hs.NewHandle(soa.Decode<mirror::ClassLoader*>(LoadDex("MyClass")))); AssertNonExistentClass("LMyClass;"); mirror::Class* MyClass = class_linker_->FindClass(soa.Self(), "LMyClass;", class_loader); - ASSERT_TRUE(MyClass != NULL); - ASSERT_TRUE(MyClass->GetClass() != NULL); + ASSERT_TRUE(MyClass != nullptr); + ASSERT_TRUE(MyClass->GetClass() != nullptr); ASSERT_EQ(MyClass->GetClass(), MyClass->GetClass()->GetClass()); EXPECT_EQ(JavaLangObject, MyClass->GetClass()->GetSuperClass()); ASSERT_STREQ(MyClass->GetDescriptor(&temp), "LMyClass;"); @@ -735,7 +741,7 @@ TEST_F(ClassLinkerTest, FindClass) { EXPECT_FALSE(MyClass->IsInitialized()); EXPECT_FALSE(MyClass->IsArrayInstance()); EXPECT_FALSE(MyClass->IsArrayClass()); - EXPECT_TRUE(MyClass->GetComponentType() == NULL); + EXPECT_TRUE(MyClass->GetComponentType() == nullptr); EXPECT_FALSE(MyClass->IsInterface()); EXPECT_FALSE(MyClass->IsPublic()); EXPECT_FALSE(MyClass->IsFinal()); @@ -750,10 +756,10 @@ TEST_F(ClassLinkerTest, FindClass) { EXPECT_EQ(JavaLangObject->GetClass()->GetClass(), MyClass->GetClass()->GetClass()); // created by class_linker - AssertArrayClass("[C", "C", NULL); - AssertArrayClass("[Ljava/lang/Object;", "Ljava/lang/Object;", NULL); + AssertArrayClass("[C", "C", nullptr); + AssertArrayClass("[Ljava/lang/Object;", "Ljava/lang/Object;", nullptr); // synthesized on the fly - AssertArrayClass("[[C", "[C", NULL); + AssertArrayClass("[[C", "[C", nullptr); AssertArrayClass("[[[LMyClass;", "[[LMyClass;", class_loader.Get()); // or not available at all AssertNonExistentClass("[[[[LNonExistentClass;"); @@ -761,7 +767,7 @@ TEST_F(ClassLinkerTest, FindClass) { TEST_F(ClassLinkerTest, LibCore) { ScopedObjectAccess soa(Thread::Current()); - AssertDexFile(java_lang_dex_file_, NULL); + AssertDexFile(java_lang_dex_file_, nullptr); } // The first reference array element must be a multiple of 4 bytes from the @@ -863,7 +869,7 @@ TEST_F(ClassLinkerTest, StaticFields) { // expression resolve to a copy of a constant value from the constant pool. // So <clinit> should be null. mirror::ArtMethod* clinit = statics->FindDirectMethod("<clinit>", "()V"); - EXPECT_TRUE(clinit == NULL); + EXPECT_TRUE(clinit == nullptr); EXPECT_EQ(9U, statics->NumStaticFields()); @@ -960,15 +966,15 @@ TEST_F(ClassLinkerTest, Interfaces) { mirror::ArtMethod* Ai = A->FindVirtualMethod("i", void_sig); mirror::ArtMethod* Aj1 = A->FindVirtualMethod("j1", void_sig); mirror::ArtMethod* Aj2 = A->FindVirtualMethod("j2", void_sig); - ASSERT_TRUE(Ii != NULL); - ASSERT_TRUE(Jj1 != NULL); - ASSERT_TRUE(Jj2 != NULL); - ASSERT_TRUE(Kj1 != NULL); - ASSERT_TRUE(Kj2 != NULL); - ASSERT_TRUE(Kk != NULL); - ASSERT_TRUE(Ai != NULL); - ASSERT_TRUE(Aj1 != NULL); - ASSERT_TRUE(Aj2 != NULL); + ASSERT_TRUE(Ii != nullptr); + ASSERT_TRUE(Jj1 != nullptr); + ASSERT_TRUE(Jj2 != nullptr); + ASSERT_TRUE(Kj1 != nullptr); + ASSERT_TRUE(Kj2 != nullptr); + ASSERT_TRUE(Kk != nullptr); + ASSERT_TRUE(Ai != nullptr); + ASSERT_TRUE(Aj1 != nullptr); + ASSERT_TRUE(Aj2 != nullptr); EXPECT_NE(Ii, Ai); EXPECT_NE(Jj1, Aj1); EXPECT_NE(Jj2, Aj2); @@ -989,7 +995,7 @@ TEST_F(ClassLinkerTest, Interfaces) { "Ljava/lang/String;"); mirror::ArtField* Kfoo = mirror::Class::FindStaticField(soa.Self(), K, "foo", "Ljava/lang/String;"); - ASSERT_TRUE(Afoo != NULL); + ASSERT_TRUE(Afoo != nullptr); EXPECT_EQ(Afoo, Bfoo); EXPECT_EQ(Afoo, Jfoo); EXPECT_EQ(Afoo, Kfoo); @@ -1007,20 +1013,20 @@ TEST_F(ClassLinkerTest, ResolveVerifyAndClinit) { Handle<mirror::ClassLoader> class_loader( hs.NewHandle(soa.Decode<mirror::ClassLoader*>(jclass_loader))); const DexFile* dex_file = Runtime::Current()->GetCompileTimeClassPath(jclass_loader)[0]; - CHECK(dex_file != NULL); + CHECK(dex_file != nullptr); mirror::Class* klass = class_linker_->FindClass(soa.Self(), "LStaticsFromCode;", class_loader); mirror::ArtMethod* clinit = klass->FindClassInitializer(); mirror::ArtMethod* getS0 = klass->FindDirectMethod("getS0", "()Ljava/lang/Object;"); const DexFile::StringId* string_id = dex_file->FindStringId("LStaticsFromCode;"); - ASSERT_TRUE(string_id != NULL); + ASSERT_TRUE(string_id != nullptr); const DexFile::TypeId* type_id = dex_file->FindTypeId(dex_file->GetIndexForStringId(*string_id)); - ASSERT_TRUE(type_id != NULL); + ASSERT_TRUE(type_id != nullptr); uint32_t type_idx = dex_file->GetIndexForTypeId(*type_id); mirror::Class* uninit = ResolveVerifyAndClinit(type_idx, clinit, Thread::Current(), true, false); - EXPECT_TRUE(uninit != NULL); + EXPECT_TRUE(uninit != nullptr); EXPECT_FALSE(uninit->IsInitialized()); mirror::Class* init = ResolveVerifyAndClinit(type_idx, getS0, Thread::Current(), true, false); - EXPECT_TRUE(init != NULL); + EXPECT_TRUE(init != nullptr); EXPECT_TRUE(init->IsInitialized()); } @@ -1117,7 +1123,7 @@ TEST_F(ClassLinkerTest, Preverified_InitializedBoot) { ScopedObjectAccess soa(Thread::Current()); mirror::Class* JavaLangObject = class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;"); - ASSERT_TRUE(JavaLangObject != NULL); + ASSERT_TRUE(JavaLangObject != nullptr); EXPECT_TRUE(JavaLangObject->IsInitialized()) << "Not testing already initialized class from the " "core"; CheckPreverified(JavaLangObject, true); diff --git a/runtime/image.cc b/runtime/image.cc index 478b486d91..f451df9e88 100644 --- a/runtime/image.cc +++ b/runtime/image.cc @@ -24,7 +24,7 @@ namespace art { const byte ImageHeader::kImageMagic[] = { 'a', 'r', 't', '\n' }; -const byte ImageHeader::kImageVersion[] = { '0', '0', '9', '\0' }; +const byte ImageHeader::kImageVersion[] = { '0', '1', '0', '\0' }; ImageHeader::ImageHeader(uint32_t image_begin, uint32_t image_size, diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc index 3fcb188697..6df7204555 100644 --- a/runtime/mirror/class.cc +++ b/runtime/mirror/class.cc @@ -278,14 +278,15 @@ void Class::DumpClass(std::ostream& os, int flags) { } void Class::SetReferenceInstanceOffsets(uint32_t new_reference_offsets) { - if (new_reference_offsets != CLASS_WALK_SUPER) { + if (kIsDebugBuild && (new_reference_offsets != kClassWalkSuper)) { // Sanity check that the number of bits set in the reference offset bitmap // agrees with the number of references - size_t count = 0; + uint32_t count = 0; for (Class* c = this; c != nullptr; c = c->GetSuperClass()) { count += c->NumReferenceInstanceFieldsDuringLinking(); } - CHECK_EQ((size_t)POPCOUNT(new_reference_offsets), count); + // +1 for the Class in Object. + CHECK_EQ(static_cast<uint32_t>(POPCOUNT(new_reference_offsets)) + 1, count); } // Not called within a transaction. SetField32<false>(OFFSET_OF_OBJECT_MEMBER(Class, reference_instance_offsets_), diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h index 0acf6952c2..2d4912191b 100644 --- a/runtime/mirror/class.h +++ b/runtime/mirror/class.h @@ -28,40 +28,6 @@ #include "primitive.h" #include "read_barrier_option.h" -/* - * A magic value for refOffsets. Ignore the bits and walk the super - * chain when this is the value. - * [This is an unlikely "natural" value, since it would be 30 non-ref instance - * fields followed by 2 ref instance fields.] - */ -#define CLASS_WALK_SUPER 3U -#define CLASS_BITS_PER_WORD (sizeof(uint32_t) * 8) -#define CLASS_OFFSET_ALIGNMENT 4 -#define CLASS_HIGH_BIT (1U << (CLASS_BITS_PER_WORD - 1)) -/* - * Given an offset, return the bit number which would encode that offset. - * Local use only. - */ -#define _CLASS_BIT_NUMBER_FROM_OFFSET(byteOffset) \ - ((unsigned int)(byteOffset) / \ - CLASS_OFFSET_ALIGNMENT) -/* - * Is the given offset too large to be encoded? - */ -#define CLASS_CAN_ENCODE_OFFSET(byteOffset) \ - (_CLASS_BIT_NUMBER_FROM_OFFSET(byteOffset) < CLASS_BITS_PER_WORD) -/* - * Return a single bit, encoding the offset. - * Undefined if the offset is too large, as defined above. - */ -#define CLASS_BIT_FROM_OFFSET(byteOffset) \ - (CLASS_HIGH_BIT >> _CLASS_BIT_NUMBER_FROM_OFFSET(byteOffset)) -/* - * Return an offset, given a bit number as returned from CLZ. - */ -#define CLASS_OFFSET_FROM_CLZ(rshift) \ - MemberOffset((static_cast<int>(rshift) * CLASS_OFFSET_ALIGNMENT)) - namespace art { struct ClassOffsets; @@ -81,6 +47,12 @@ class IfTable; // C++ mirror of java.lang.Class class MANAGED Class FINAL : public Object { public: + // A magic value for reference_instance_offsets_. Ignore the bits and walk the super chain when + // this is the value. + // [This is an unlikely "natural" value, since it would be 30 non-ref instance fields followed by + // 2 ref instance fields.] + static constexpr uint32_t kClassWalkSuper = 0xC0000000; + // Interface method table size. Increasing this value reduces the chance of two interface methods // colliding in the interface method table but increases the size of classes that implement // (non-marker) interfaces. diff --git a/runtime/mirror/object-inl.h b/runtime/mirror/object-inl.h index 166ea9c3e5..4d5f6213c7 100644 --- a/runtime/mirror/object-inl.h +++ b/runtime/mirror/object-inl.h @@ -888,18 +888,18 @@ inline bool Object::CasFieldStrongSequentiallyConsistentObject(MemberOffset fiel template<bool kVisitClass, bool kIsStatic, typename Visitor> inline void Object::VisitFieldsReferences(uint32_t ref_offsets, const Visitor& visitor) { - if (!kIsStatic && LIKELY(ref_offsets != CLASS_WALK_SUPER)) { - if (!kVisitClass) { - // Mask out the class from the reference offsets. - ref_offsets ^= kWordHighBitMask; + if (!kIsStatic && (ref_offsets != mirror::Class::kClassWalkSuper)) { + // Instance fields and not the slow-path. + if (kVisitClass) { + visitor(this, ClassOffset(), kIsStatic); } - DCHECK_EQ(ClassOffset().Uint32Value(), 0U); - // Found a reference offset bitmap. Visit the specified offsets. + uint32_t field_offset = mirror::kObjectHeaderSize; while (ref_offsets != 0) { - size_t right_shift = CLZ(ref_offsets); - MemberOffset field_offset = CLASS_OFFSET_FROM_CLZ(right_shift); - visitor(this, field_offset, kIsStatic); - ref_offsets &= ~(CLASS_HIGH_BIT >> right_shift); + if ((ref_offsets & 1) != 0) { + visitor(this, MemberOffset(field_offset), kIsStatic); + } + ref_offsets >>= 1; + field_offset += sizeof(mirror::HeapReference<mirror::Object>); } } else { // There is no reference offset bitmap. In the non-static case, walk up the class diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h index b68aef9c7f..4ed96fca7e 100644 --- a/runtime/mirror/object.h +++ b/runtime/mirror/object.h @@ -17,6 +17,7 @@ #ifndef ART_RUNTIME_MIRROR_OBJECT_H_ #define ART_RUNTIME_MIRROR_OBJECT_H_ +#include "globals.h" #include "object_reference.h" #include "offsets.h" #include "verify_object.h" @@ -60,6 +61,9 @@ class Throwable; // Checks that we don't do field assignments which violate the typing system. static constexpr bool kCheckFieldAssignments = false; +// Size of Object. +static constexpr uint32_t kObjectHeaderSize = kUseBrooksReadBarrier ? 16 : 8; + // C++ mirror of java.lang.Object class MANAGED LOCKABLE Object { public: diff --git a/runtime/mirror/object_test.cc b/runtime/mirror/object_test.cc index 7fa664d2dc..1aeba7487c 100644 --- a/runtime/mirror/object_test.cc +++ b/runtime/mirror/object_test.cc @@ -76,7 +76,8 @@ class ObjectTest : public CommonRuntimeTest { // Keep constants in sync. TEST_F(ObjectTest, Constants) { - EXPECT_EQ(kObjectReferenceSize, sizeof(mirror::HeapReference<mirror::Object>)); + EXPECT_EQ(kObjectReferenceSize, sizeof(HeapReference<Object>)); + EXPECT_EQ(kObjectHeaderSize, sizeof(Object)); } // Keep the assembly code constats in sync. |