diff options
| -rw-r--r-- | runtime/asm_support.h | 6 | ||||
| -rw-r--r-- | runtime/class_linker.cc | 38 | ||||
| -rw-r--r-- | runtime/class_linker_test.cc | 1 | ||||
| -rw-r--r-- | runtime/gc/collector/mark_sweep-inl.h | 13 | ||||
| -rw-r--r-- | runtime/gc/collector/mark_sweep.cc | 23 | ||||
| -rw-r--r-- | runtime/gc/collector/mark_sweep.h | 13 | ||||
| -rw-r--r-- | runtime/gc/heap.cc | 2 | ||||
| -rw-r--r-- | runtime/image.cc | 2 | ||||
| -rw-r--r-- | runtime/mirror/class-inl.h | 13 | ||||
| -rw-r--r-- | runtime/mirror/class.cc | 1 | ||||
| -rw-r--r-- | runtime/mirror/class.h | 33 | ||||
| -rw-r--r-- | runtime/mirror/class_flags.h | 56 | ||||
| -rw-r--r-- | runtime/mirror/object-inl.h | 48 | ||||
| -rw-r--r-- | runtime/mirror/string.cc | 1 | ||||
| -rw-r--r-- | runtime/mirror/string.h | 7 | ||||
| -rw-r--r-- | runtime/modifiers.h | 24 |
16 files changed, 198 insertions, 83 deletions
diff --git a/runtime/asm_support.h b/runtime/asm_support.h index 35acd424ba..084c88e239 100644 --- a/runtime/asm_support.h +++ b/runtime/asm_support.h @@ -141,10 +141,10 @@ ADD_TEST_EQ(MIRROR_CLASS_COMPONENT_TYPE_OFFSET, #define MIRROR_CLASS_ACCESS_FLAGS_OFFSET (36 + MIRROR_OBJECT_HEADER_SIZE) ADD_TEST_EQ(MIRROR_CLASS_ACCESS_FLAGS_OFFSET, art::mirror::Class::AccessFlagsOffset().Int32Value()) -#define MIRROR_CLASS_OBJECT_SIZE_OFFSET (96 + MIRROR_OBJECT_HEADER_SIZE) +#define MIRROR_CLASS_OBJECT_SIZE_OFFSET (100 + MIRROR_OBJECT_HEADER_SIZE) ADD_TEST_EQ(MIRROR_CLASS_OBJECT_SIZE_OFFSET, art::mirror::Class::ObjectSizeOffset().Int32Value()) -#define MIRROR_CLASS_STATUS_OFFSET (108 + MIRROR_OBJECT_HEADER_SIZE) +#define MIRROR_CLASS_STATUS_OFFSET (112 + MIRROR_OBJECT_HEADER_SIZE) ADD_TEST_EQ(MIRROR_CLASS_STATUS_OFFSET, art::mirror::Class::StatusOffset().Int32Value()) @@ -153,7 +153,7 @@ ADD_TEST_EQ(static_cast<uint32_t>(MIRROR_CLASS_STATUS_INITIALIZED), static_cast<uint32_t>(art::mirror::Class::kStatusInitialized)) #define ACCESS_FLAGS_CLASS_IS_FINALIZABLE 0x80000000 ADD_TEST_EQ(static_cast<uint32_t>(ACCESS_FLAGS_CLASS_IS_FINALIZABLE), - static_cast<uint32_t>(kAccClassIsFinalizable)) + static_cast<uint32_t>(art::kAccClassIsFinalizable)) // Array offsets. #define MIRROR_ARRAY_LENGTH_OFFSET MIRROR_OBJECT_HEADER_SIZE diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index c179c64491..b547d079cd 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -358,9 +358,9 @@ void ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b // Setup String. Handle<mirror::Class> java_lang_String(hs.NewHandle( AllocClass(self, java_lang_Class.Get(), mirror::String::ClassSize(image_pointer_size_)))); + java_lang_String->SetStringClass(); mirror::String::SetClass(java_lang_String.Get()); mirror::Class::SetStatus(java_lang_String, mirror::Class::kStatusResolved, self); - java_lang_String->SetStringClass(); // Setup java.lang.ref.Reference. Handle<mirror::Class> java_lang_ref_Reference(hs.NewHandle( @@ -570,16 +570,13 @@ void ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b CHECK_EQ(java_lang_ref_Reference->GetClassSize(), mirror::Reference::ClassSize(image_pointer_size_)); class_root = FindSystemClass(self, "Ljava/lang/ref/FinalizerReference;"); - class_root->SetAccessFlags(class_root->GetAccessFlags() | - kAccClassIsReference | kAccClassIsFinalizerReference); + class_root->SetClassFlags(class_root->GetClassFlags() | mirror::kClassFlagFinalizerReference); class_root = FindSystemClass(self, "Ljava/lang/ref/PhantomReference;"); - class_root->SetAccessFlags(class_root->GetAccessFlags() | kAccClassIsReference | - kAccClassIsPhantomReference); + class_root->SetClassFlags(class_root->GetClassFlags() | mirror::kClassFlagPhantomReference); class_root = FindSystemClass(self, "Ljava/lang/ref/SoftReference;"); - class_root->SetAccessFlags(class_root->GetAccessFlags() | kAccClassIsReference); + class_root->SetClassFlags(class_root->GetClassFlags() | mirror::kClassFlagSoftReference); class_root = FindSystemClass(self, "Ljava/lang/ref/WeakReference;"); - class_root->SetAccessFlags(class_root->GetAccessFlags() | kAccClassIsReference | - kAccClassIsWeakReference); + class_root->SetClassFlags(class_root->GetClassFlags() | mirror::kClassFlagWeakReference); // Setup the ClassLoader, verifying the object_size_. class_root = FindSystemClass(self, "Ljava/lang/ClassLoader;"); @@ -2701,6 +2698,11 @@ mirror::Class* ClassLinker::CreateArrayClass(Thread* self, const char* descripto new_class->SetVTable(java_lang_Object->GetVTable()); new_class->SetPrimitiveType(Primitive::kPrimNot); new_class->SetClassLoader(component_type->GetClassLoader()); + if (component_type->IsPrimitive()) { + new_class->SetClassFlags(mirror::kClassFlagNoReferenceFields); + } else { + new_class->SetClassFlags(mirror::kClassFlagObjectArray); + } mirror::Class::SetStatus(new_class, mirror::Class::kStatusLoaded, self); { ArtMethod* imt[mirror::Class::kImtSize]; @@ -4385,9 +4387,9 @@ bool ClassLinker::LinkSuperClass(Handle<mirror::Class> klass) { } // Inherit reference flags (if any) from the superclass. - int reference_flags = (super->GetAccessFlags() & kAccReferenceFlagsMask); + int reference_flags = (super->GetClassFlags() & mirror::kClassFlagReference); if (reference_flags != 0) { - klass->SetAccessFlags(klass->GetAccessFlags() | reference_flags); + klass->SetClassFlags(klass->GetClassFlags() | reference_flags); } // Disallow custom direct subclasses of java.lang.ref.Reference. if (init_done_ && super == GetClassRoot(kJavaLangRefReference)) { @@ -5227,6 +5229,22 @@ bool ClassLinker::LinkFields(Thread* self, Handle<mirror::Class> klass, bool is_ *class_size = size; } else { klass->SetNumReferenceInstanceFields(num_reference_fields); + mirror::Class* super_class = klass->GetSuperClass(); + if (num_reference_fields == 0 || super_class == nullptr) { + // object has one reference field, klass, but we ignore it since we always visit the class. + // If the super_class is null then we are java.lang.Object. + if (super_class == nullptr || + (super_class->GetClassFlags() & mirror::kClassFlagNoReferenceFields) != 0) { + klass->SetClassFlags(klass->GetClassFlags() | mirror::kClassFlagNoReferenceFields); + } else if (kIsDebugBuild) { + size_t total_reference_instance_fields = 0; + while (super_class != nullptr) { + total_reference_instance_fields += super_class->NumReferenceInstanceFields(); + super_class = super_class->GetSuperClass(); + } + CHECK_GT(total_reference_instance_fields, 1u); + } + } if (!klass->IsVariableSize()) { std::string temp; DCHECK_GE(size, sizeof(mirror::Object)) << klass->GetDescriptor(&temp); diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc index 3c84d8fc0a..0d1c875fdf 100644 --- a/runtime/class_linker_test.cc +++ b/runtime/class_linker_test.cc @@ -488,6 +488,7 @@ struct ObjectOffsets : public CheckOffsets<mirror::Object> { struct ClassOffsets : public CheckOffsets<mirror::Class> { ClassOffsets() : CheckOffsets<mirror::Class>(false, "Ljava/lang/Class;") { addOffset(OFFSETOF_MEMBER(mirror::Class, access_flags_), "accessFlags"); + addOffset(OFFSETOF_MEMBER(mirror::Class, class_flags_), "classFlags"); addOffset(OFFSETOF_MEMBER(mirror::Class, class_loader_), "classLoader"); addOffset(OFFSETOF_MEMBER(mirror::Class, class_size_), "classSize"); addOffset(OFFSETOF_MEMBER(mirror::Class, clinit_thread_id_), "clinitThreadId"); diff --git a/runtime/gc/collector/mark_sweep-inl.h b/runtime/gc/collector/mark_sweep-inl.h index a3cc83132f..56edcc9d09 100644 --- a/runtime/gc/collector/mark_sweep-inl.h +++ b/runtime/gc/collector/mark_sweep-inl.h @@ -35,10 +35,17 @@ inline void MarkSweep::ScanObjectVisit(mirror::Object* obj, const MarkVisitor& v obj->VisitReferences(visitor, ref_visitor); if (kCountScannedTypes) { mirror::Class* klass = obj->GetClass<kVerifyNone>(); - if (UNLIKELY(klass == mirror::Class::GetJavaLangClass())) { + uint32_t class_flags = klass->GetClassFlags(); + if ((class_flags & mirror::kClassFlagNoReferenceFields) != 0) { + ++no_reference_class_count_; + } else if (class_flags == mirror::kClassFlagNormal) { + ++normal_count_; + } else if (class_flags == mirror::kClassFlagObjectArray) { + ++object_array_count_; + } else if (class_flags == mirror::kClassFlagClass) { ++class_count_; - } else if (UNLIKELY(klass->IsArrayClass<kVerifyNone>())) { - ++array_count_; + } else if ((class_flags & mirror::kClassFlagReference) != 0) { + ++reference_count_; } else { ++other_count_; } diff --git a/runtime/gc/collector/mark_sweep.cc b/runtime/gc/collector/mark_sweep.cc index b0a8a5bf2b..7ddc7ccc63 100644 --- a/runtime/gc/collector/mark_sweep.cc +++ b/runtime/gc/collector/mark_sweep.cc @@ -70,7 +70,6 @@ static constexpr bool kParallelProcessMarkStack = true; static constexpr bool kProfileLargeObjects = false; static constexpr bool kMeasureOverhead = false; static constexpr bool kCountTasks = false; -static constexpr bool kCountJavaLangRefs = false; static constexpr bool kCountMarkedObjects = false; // Turn off kCheckLocks when profiling the GC since it slows the GC down by up to 40%. @@ -114,15 +113,17 @@ void MarkSweep::InitializePhase() { mark_stack_ = heap_->GetMarkStack(); DCHECK(mark_stack_ != nullptr); immune_region_.Reset(); + no_reference_class_count_.StoreRelaxed(0); + normal_count_.StoreRelaxed(0); class_count_.StoreRelaxed(0); - array_count_.StoreRelaxed(0); + object_array_count_.StoreRelaxed(0); other_count_.StoreRelaxed(0); + reference_count_.StoreRelaxed(0); large_object_test_.StoreRelaxed(0); large_object_mark_.StoreRelaxed(0); overhead_time_ .StoreRelaxed(0); work_chunks_created_.StoreRelaxed(0); work_chunks_deleted_.StoreRelaxed(0); - reference_count_.StoreRelaxed(0); mark_null_count_.StoreRelaxed(0); mark_immune_count_.StoreRelaxed(0); mark_fastpath_count_.StoreRelaxed(0); @@ -1265,9 +1266,6 @@ void MarkSweep::SweepLargeObjects(bool swap_bitmaps) { // Process the "referent" field in a java.lang.ref.Reference. If the referent has not yet been // marked, put it on the appropriate list in the heap for later processing. void MarkSweep::DelayReferenceReferent(mirror::Class* klass, mirror::Reference* ref) { - if (kCountJavaLangRefs) { - ++reference_count_; - } heap_->GetReferenceProcessor()->DelayReferenceReferent(klass, ref, this); } @@ -1386,8 +1384,14 @@ inline mirror::Object* MarkSweep::IsMarked(mirror::Object* object) { void MarkSweep::FinishPhase() { TimingLogger::ScopedTiming t(__FUNCTION__, GetTimings()); if (kCountScannedTypes) { - VLOG(gc) << "MarkSweep scanned classes=" << class_count_.LoadRelaxed() - << " arrays=" << array_count_.LoadRelaxed() << " other=" << other_count_.LoadRelaxed(); + VLOG(gc) + << "MarkSweep scanned" + << " no reference objects=" << no_reference_class_count_.LoadRelaxed() + << " normal objects=" << normal_count_.LoadRelaxed() + << " classes=" << class_count_.LoadRelaxed() + << " object arrays=" << object_array_count_.LoadRelaxed() + << " references=" << reference_count_.LoadRelaxed() + << " other=" << other_count_.LoadRelaxed(); } if (kCountTasks) { VLOG(gc) << "Total number of work chunks allocated: " << work_chunks_created_.LoadRelaxed(); @@ -1399,9 +1403,6 @@ void MarkSweep::FinishPhase() { VLOG(gc) << "Large objects tested " << large_object_test_.LoadRelaxed() << " marked " << large_object_mark_.LoadRelaxed(); } - if (kCountJavaLangRefs) { - VLOG(gc) << "References scanned " << reference_count_.LoadRelaxed(); - } if (kCountMarkedObjects) { VLOG(gc) << "Marked: null=" << mark_null_count_.LoadRelaxed() << " immune=" << mark_immune_count_.LoadRelaxed() diff --git a/runtime/gc/collector/mark_sweep.h b/runtime/gc/collector/mark_sweep.h index 8bd1dc7cd5..371bba531d 100644 --- a/runtime/gc/collector/mark_sweep.h +++ b/runtime/gc/collector/mark_sweep.h @@ -245,7 +245,7 @@ class MarkSweep : public GarbageCollector { void RevokeAllThreadLocalBuffers(); // Whether or not we count how many of each type of object were scanned. - static const bool kCountScannedTypes = false; + static constexpr bool kCountScannedTypes = false; // Current space, we check this space first to avoid searching for the appropriate space for an // object. @@ -260,18 +260,23 @@ class MarkSweep : public GarbageCollector { // Parallel finger. AtomicInteger atomic_finger_; + + AtomicInteger no_reference_class_count_; + AtomicInteger normal_count_; // Number of classes scanned, if kCountScannedTypes. AtomicInteger class_count_; - // Number of arrays scanned, if kCountScannedTypes. - AtomicInteger array_count_; + // Number of object arrays scanned, if kCountScannedTypes. + AtomicInteger object_array_count_; // Number of non-class/arrays scanned, if kCountScannedTypes. AtomicInteger other_count_; + // Number of java.lang.ref.Reference instances. + AtomicInteger reference_count_; + AtomicInteger large_object_test_; AtomicInteger large_object_mark_; AtomicInteger overhead_time_; AtomicInteger work_chunks_created_; AtomicInteger work_chunks_deleted_; - AtomicInteger reference_count_; AtomicInteger mark_null_count_; AtomicInteger mark_immune_count_; AtomicInteger mark_fastpath_count_; diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc index d7f918b4ff..b8c44781a3 100644 --- a/runtime/gc/heap.cc +++ b/runtime/gc/heap.cc @@ -3707,7 +3707,7 @@ void Heap::AddModUnionTable(accounting::ModUnionTable* mod_union_table) { void Heap::CheckPreconditionsForAllocObject(mirror::Class* c, size_t byte_count) { CHECK(c == nullptr || (c->IsClassClass() && byte_count >= sizeof(mirror::Class)) || - (c->IsVariableSize() || c->GetObjectSize() == byte_count)); + (c->IsVariableSize() || c->GetObjectSize() == byte_count)) << c->GetClassFlags(); CHECK_GE(byte_count, sizeof(mirror::Object)); } diff --git a/runtime/image.cc b/runtime/image.cc index 2586959e55..8df17c6929 100644 --- a/runtime/image.cc +++ b/runtime/image.cc @@ -24,7 +24,7 @@ namespace art { const uint8_t ImageHeader::kImageMagic[] = { 'a', 'r', 't', '\n' }; -const uint8_t ImageHeader::kImageVersion[] = { '0', '1', '9', '\0' }; +const uint8_t ImageHeader::kImageVersion[] = { '0', '2', '0', '\0' }; ImageHeader::ImageHeader(uint32_t image_begin, uint32_t image_size, diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h index cd678f670b..b2c6e4da12 100644 --- a/runtime/mirror/class-inl.h +++ b/runtime/mirror/class-inl.h @@ -547,6 +547,7 @@ inline uint32_t Class::GetAccessFlags() { inline String* Class::GetName() { return GetFieldObject<String>(OFFSET_OF_OBJECT_MEMBER(Class, name_)); } + inline void Class::SetName(String* name) { if (Runtime::Current()->IsActiveTransaction()) { SetFieldObject<true>(OFFSET_OF_OBJECT_MEMBER(Class, name_), name); @@ -784,9 +785,17 @@ inline void Class::InitializeClassVisitor::operator()( inline void Class::SetAccessFlags(uint32_t new_access_flags) { // Called inside a transaction when setting pre-verified flag during boot image compilation. if (Runtime::Current()->IsActiveTransaction()) { - SetField32<true>(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_), new_access_flags); + SetField32<true>(AccessFlagsOffset(), new_access_flags); + } else { + SetField32<false>(AccessFlagsOffset(), new_access_flags); + } +} + +inline void Class::SetClassFlags(uint32_t new_flags) { + if (Runtime::Current()->IsActiveTransaction()) { + SetField32<true>(OFFSET_OF_OBJECT_MEMBER(Class, class_flags_), new_flags); } else { - SetField32<false>(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_), new_access_flags); + SetField32<false>(OFFSET_OF_OBJECT_MEMBER(Class, class_flags_), new_flags); } } diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc index 055b3e5110..228fd27f28 100644 --- a/runtime/mirror/class.cc +++ b/runtime/mirror/class.cc @@ -44,6 +44,7 @@ void Class::SetClassClass(Class* java_lang_Class) { << java_lang_Class_.Read() << " " << java_lang_Class; CHECK(java_lang_Class != nullptr); + java_lang_Class->SetClassFlags(java_lang_Class->GetClassFlags() | mirror::kClassFlagClass); java_lang_Class_ = GcRoot<Class>(java_lang_Class); } diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h index 3f375be9ca..cbcb517001 100644 --- a/runtime/mirror/class.h +++ b/runtime/mirror/class.h @@ -19,6 +19,7 @@ #include "base/iteration_range.h" #include "dex_file.h" +#include "class_flags.h" #include "gc_root.h" #include "gc/allocator_type.h" #include "invoke_type.h" @@ -201,6 +202,12 @@ class MANAGED Class FINAL : public Object { return OFFSET_OF_OBJECT_MEMBER(Class, access_flags_); } + template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> + ALWAYS_INLINE uint32_t GetClassFlags() SHARED_REQUIRES(Locks::mutator_lock_) { + return GetField32<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Class, class_flags_)); + } + void SetClassFlags(uint32_t new_flags) SHARED_REQUIRES(Locks::mutator_lock_); + void SetAccessFlags(uint32_t new_access_flags) SHARED_REQUIRES(Locks::mutator_lock_); // Returns true if the class is an interface. @@ -228,21 +235,19 @@ class MANAGED Class FINAL : public Object { } ALWAYS_INLINE bool IsStringClass() SHARED_REQUIRES(Locks::mutator_lock_) { - return (GetField32(AccessFlagsOffset()) & kAccClassIsStringClass) != 0; + return (GetClassFlags() & kClassFlagString) != 0; } ALWAYS_INLINE void SetStringClass() SHARED_REQUIRES(Locks::mutator_lock_) { - uint32_t flags = GetField32(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_)); - SetAccessFlags(flags | kAccClassIsStringClass); + SetClassFlags(GetClassFlags() | kClassFlagString | kClassFlagNoReferenceFields); } ALWAYS_INLINE bool IsClassLoaderClass() SHARED_REQUIRES(Locks::mutator_lock_) { - return (GetField32(AccessFlagsOffset()) & kAccClassIsClassLoaderClass) != 0; + return (GetClassFlags() & kClassFlagClassLoader) != 0; } ALWAYS_INLINE void SetClassLoaderClass() SHARED_REQUIRES(Locks::mutator_lock_) { - uint32_t flags = GetField32(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_)); - SetAccessFlags(flags | kAccClassIsClassLoaderClass); + SetClassFlags(GetClassFlags() | kClassFlagClassLoader); } // Returns true if the class is abstract. @@ -272,27 +277,27 @@ class MANAGED Class FINAL : public Object { template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> bool IsTypeOfReferenceClass() SHARED_REQUIRES(Locks::mutator_lock_) { - return (GetAccessFlags<kVerifyFlags>() & kAccClassIsReference) != 0; + return (GetClassFlags<kVerifyFlags>() & kClassFlagReference) != 0; } template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> bool IsWeakReferenceClass() SHARED_REQUIRES(Locks::mutator_lock_) { - return (GetAccessFlags<kVerifyFlags>() & kAccClassIsWeakReference) != 0; + return (GetClassFlags<kVerifyFlags>() & kClassFlagWeakReference) != 0; } template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> bool IsSoftReferenceClass() SHARED_REQUIRES(Locks::mutator_lock_) { - return (GetAccessFlags<kVerifyFlags>() & kAccReferenceFlagsMask) == kAccClassIsReference; + return (GetClassFlags<kVerifyFlags>() & kClassFlagSoftReference) != 0; } template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> bool IsFinalizerReferenceClass() SHARED_REQUIRES(Locks::mutator_lock_) { - return (GetAccessFlags<kVerifyFlags>() & kAccClassIsFinalizerReference) != 0; + return (GetClassFlags<kVerifyFlags>() & kClassFlagFinalizerReference) != 0; } template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> bool IsPhantomReferenceClass() SHARED_REQUIRES(Locks::mutator_lock_) { - return (GetAccessFlags<kVerifyFlags>() & kAccClassIsPhantomReference) != 0; + return (GetClassFlags<kVerifyFlags>() & kClassFlagPhantomReference) != 0; } // Can references of this type be assigned to by things of another type? For non-array types @@ -862,7 +867,8 @@ class MANAGED Class FINAL : public Object { uint32_t NumInstanceFields() SHARED_REQUIRES(Locks::mutator_lock_); ArtField* GetInstanceField(uint32_t i) SHARED_REQUIRES(Locks::mutator_lock_); - // Returns the number of instance fields containing reference types. + // Returns the number of instance fields containing reference types not counting fields in the + // super class. uint32_t NumReferenceInstanceFields() SHARED_REQUIRES(Locks::mutator_lock_) { DCHECK(IsResolved() || IsErroneous()); return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, num_reference_instance_fields_)); @@ -1225,6 +1231,9 @@ class MANAGED Class FINAL : public Object { // length-prefixed array. uint64_t virtual_methods_; + // Class flags to help speed up visiting object references. + uint32_t class_flags_; + // Total size of the Class instance; used when allocating storage on gc heap. // See also object_size_. uint32_t class_size_; diff --git a/runtime/mirror/class_flags.h b/runtime/mirror/class_flags.h new file mode 100644 index 0000000000..6c15639177 --- /dev/null +++ b/runtime/mirror/class_flags.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_RUNTIME_MIRROR_CLASS_FLAGS_H_ +#define ART_RUNTIME_MIRROR_CLASS_FLAGS_H_ + +#include <stdint.h> + +namespace art { +namespace mirror { + +// Object types stored in class to help GC with faster object marking. +static constexpr uint32_t kClassFlagNormal = 0x00000000; +// Only normal objects which have no reference fields, e.g. string or primitive array or normal +// class instance. +static constexpr uint32_t kClassFlagNoReferenceFields = 0x00000001; +static constexpr uint32_t kClassFlagString = 0x00000004; +static constexpr uint32_t kClassFlagObjectArray = 0x00000008; +static constexpr uint32_t kClassFlagClass = 0x00000010; + +// class is ClassLoader or one of its subclasses +static constexpr uint32_t kClassFlagClassLoader = 0x00000020; + +// class is a soft/weak/phantom ref +static constexpr uint32_t kClassFlagSoftReference = 0x00000040; +// class is a weak reference +static constexpr uint32_t kClassFlagWeakReference = 0x00000080; +// class is a finalizer reference +static constexpr uint32_t kClassFlagFinalizerReference = 0x00000100; +// class is a phantom reference +static constexpr uint32_t kClassFlagPhantomReference = 0x00000200; + +static constexpr uint32_t kClassFlagReference = + kClassFlagSoftReference | + kClassFlagWeakReference | + kClassFlagFinalizerReference | + kClassFlagPhantomReference; + +} // namespace mirror +} // namespace art + +#endif // ART_RUNTIME_MIRROR_CLASS_FLAGS_H_ + diff --git a/runtime/mirror/object-inl.h b/runtime/mirror/object-inl.h index 586ae30d19..702a0f49ea 100644 --- a/runtime/mirror/object-inl.h +++ b/runtime/mirror/object-inl.h @@ -24,6 +24,7 @@ #include "atomic.h" #include "array-inl.h" #include "class.h" +#include "class_flags.h" #include "class_linker.h" #include "class_loader-inl.h" #include "lock_word-inl.h" @@ -1010,20 +1011,43 @@ inline void Object::VisitReferences(const Visitor& visitor, const JavaLangRefVisitor& ref_visitor) { mirror::Class* klass = GetClass<kVerifyFlags>(); visitor(this, ClassOffset(), false); - if (klass == Class::GetJavaLangClass()) { - AsClass<kVerifyNone>()->VisitReferences(klass, visitor); - } else if (klass->IsArrayClass() || klass->IsStringClass()) { - if (klass->IsObjectArrayClass<kVerifyNone>()) { - AsObjectArray<mirror::Object, kVerifyNone>()->VisitReferences(visitor); - } - } else if (klass->IsClassLoaderClass()) { - mirror::ClassLoader* class_loader = AsClassLoader<kVerifyFlags>(); - class_loader->VisitReferences<kVerifyFlags>(klass, visitor); - } else { + const uint32_t class_flags = klass->GetClassFlags<kVerifyNone>(); + if (LIKELY(class_flags == kClassFlagNormal)) { DCHECK(!klass->IsVariableSize()); VisitInstanceFieldsReferences(klass, visitor); - if (UNLIKELY(klass->IsTypeOfReferenceClass<kVerifyNone>())) { - ref_visitor(klass, AsReference()); + DCHECK(!klass->IsClassClass()); + } else { + if ((class_flags & kClassFlagNoReferenceFields) == 0) { + DCHECK(!klass->IsStringClass()); + if (class_flags == kClassFlagClass) { + DCHECK(klass->IsClassClass()); + AsClass<kVerifyNone>()->VisitReferences(klass, visitor); + } else if (class_flags == kClassFlagObjectArray) { + DCHECK(klass->IsObjectArrayClass()); + AsObjectArray<mirror::Object, kVerifyNone>()->VisitReferences(visitor); + } else if ((class_flags & kClassFlagReference) != 0) { + VisitInstanceFieldsReferences(klass, visitor); + ref_visitor(klass, AsReference()); + } else { + mirror::ClassLoader* const class_loader = AsClassLoader<kVerifyFlags>(); + class_loader->VisitReferences<kVerifyFlags>(klass, visitor); + } + } else if (kIsDebugBuild) { + CHECK(!klass->IsClassClass()); + CHECK(!klass->IsObjectArrayClass()); + // String still has instance fields for reflection purposes but these don't exist in + // actual string instances. + if (!klass->IsStringClass()) { + size_t total_reference_instance_fields = 0; + mirror::Class* super_class = klass; + do { + total_reference_instance_fields += super_class->NumReferenceInstanceFields(); + super_class = super_class->GetSuperClass(); + } while (super_class != nullptr); + // The only reference field should be the object's class. This field is handled at the + // beginning of the function. + CHECK_EQ(total_reference_instance_fields, 1u); + } } } } diff --git a/runtime/mirror/string.cc b/runtime/mirror/string.cc index b6236b1eb3..45610dccc8 100644 --- a/runtime/mirror/string.cc +++ b/runtime/mirror/string.cc @@ -55,6 +55,7 @@ int32_t String::FastIndexOf(int32_t ch, int32_t start) { void String::SetClass(Class* java_lang_String) { CHECK(java_lang_String_.IsNull()); CHECK(java_lang_String != nullptr); + CHECK(java_lang_String->IsStringClass()); java_lang_String_ = GcRoot<Class>(java_lang_String); } diff --git a/runtime/mirror/string.h b/runtime/mirror/string.h index eb2e1f6977..fbee2d7bf3 100644 --- a/runtime/mirror/string.h +++ b/runtime/mirror/string.h @@ -157,10 +157,9 @@ class MANAGED String FINAL : public Object { return java_lang_String_.Read(); } - static void SetClass(Class* java_lang_String); - static void ResetClass(); - static void VisitRoots(RootVisitor* visitor) - SHARED_REQUIRES(Locks::mutator_lock_); + static void SetClass(Class* java_lang_String) SHARED_REQUIRES(Locks::mutator_lock_); + static void ResetClass() SHARED_REQUIRES(Locks::mutator_lock_); + static void VisitRoots(RootVisitor* visitor) SHARED_REQUIRES(Locks::mutator_lock_); private: void SetHashCode(int32_t new_hash_code) SHARED_REQUIRES(Locks::mutator_lock_) { diff --git a/runtime/modifiers.h b/runtime/modifiers.h index 0d9ec29db3..f7ab10be9d 100644 --- a/runtime/modifiers.h +++ b/runtime/modifiers.h @@ -19,6 +19,8 @@ #include <stdint.h> +namespace art { + static constexpr uint32_t kAccPublic = 0x0001; // class, field, method, ic static constexpr uint32_t kAccPrivate = 0x0002; // field, method, ic static constexpr uint32_t kAccProtected = 0x0004; // field, method, ic @@ -49,28 +51,8 @@ static constexpr uint32_t kAccFastNative = 0x00080000; // method (dex static constexpr uint32_t kAccMiranda = 0x00200000; // method (dex only) // Special runtime-only flags. -// Note: if only kAccClassIsReference is set, we have a soft reference. - -// class is ClassLoader or one of its subclasses -static constexpr uint32_t kAccClassIsClassLoaderClass = 0x10000000; - // class/ancestor overrides finalize() static constexpr uint32_t kAccClassIsFinalizable = 0x80000000; -// class is a soft/weak/phantom ref -static constexpr uint32_t kAccClassIsReference = 0x08000000; -// class is a weak reference -static constexpr uint32_t kAccClassIsWeakReference = 0x04000000; -// class is a finalizer reference -static constexpr uint32_t kAccClassIsFinalizerReference = 0x02000000; -// class is a phantom reference -static constexpr uint32_t kAccClassIsPhantomReference = 0x01000000; -// class is the string class -static constexpr uint32_t kAccClassIsStringClass = 0x00800000; - -static constexpr uint32_t kAccReferenceFlagsMask = (kAccClassIsReference - | kAccClassIsWeakReference - | kAccClassIsFinalizerReference - | kAccClassIsPhantomReference); // Valid (meaningful) bits for a field. static constexpr uint32_t kAccValidFieldFlags = kAccPublic | kAccPrivate | kAccProtected | @@ -95,5 +77,7 @@ static constexpr uint32_t kAccValidClassFlags = kAccPublic | kAccFinal | kAccSup static constexpr uint32_t kAccValidInterfaceFlags = kAccPublic | kAccInterface | kAccAbstract | kAccSynthetic | kAccAnnotation; +} // namespace art + #endif // ART_RUNTIME_MODIFIERS_H_ |