diff options
author | Jeff Hao <jeffhao@google.com> | 2016-06-28 23:47:09 +0000 |
---|---|---|
committer | Jeff Hao <jeffhao@google.com> | 2016-06-29 01:23:37 +0000 |
commit | fd43db68d204caaa0e411ca79a37af15d1c001af (patch) | |
tree | 1c26b5329dd7fee6884ec608e7fb1038c848ed1f /runtime/class_linker.cc | |
parent | 6777a3ceaf9ad3c7906805f0c05680d60db2b6b3 (diff) | |
download | android_art-fd43db68d204caaa0e411ca79a37af15d1c001af.tar.gz android_art-fd43db68d204caaa0e411ca79a37af15d1c001af.tar.bz2 android_art-fd43db68d204caaa0e411ca79a37af15d1c001af.zip |
Revert "Optimize IMT"
This reverts commit 0790af1391b316c5c12b4e135be357008c060696.
Bug: 29188168 (for initial CL)
Bug: 29778499 (reason for revert)
Change-Id: I2c3e4ec2cebdd40faec67ddb721b7acdc8e90061
Diffstat (limited to 'runtime/class_linker.cc')
-rw-r--r-- | runtime/class_linker.cc | 150 |
1 files changed, 34 insertions, 116 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 36d93b8741..38a2a00a7f 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -857,13 +857,11 @@ static void SanityCheckObjectsCallback(mirror::Object* obj, void* arg ATTRIBUTE_ if (vtable != nullptr) { SanityCheckArtMethodPointerArray(vtable, nullptr, pointer_size, image_spaces); } - if (klass->ShouldHaveImt()) { - ImTable* imt = klass->GetImt(pointer_size); - for (size_t i = 0; i < ImTable::kSize; ++i) { - SanityCheckArtMethod(imt->Get(i, pointer_size), nullptr, image_spaces); + if (klass->ShouldHaveEmbeddedImtAndVTable()) { + for (size_t i = 0; i < mirror::Class::kImtSize; ++i) { + SanityCheckArtMethod( + klass->GetEmbeddedImTableEntry(i, pointer_size), nullptr, image_spaces); } - } - if (klass->ShouldHaveEmbeddedVTable()) { for (int32_t i = 0; i < klass->GetEmbeddedVTableLength(); ++i) { SanityCheckArtMethod(klass->GetEmbeddedVTableEntry(i, pointer_size), nullptr, image_spaces); } @@ -3458,11 +3456,16 @@ mirror::Class* ClassLinker::CreateArrayClass(Thread* self, const char* descripto new_class->SetClassFlags(mirror::kClassFlagObjectArray); } mirror::Class::SetStatus(new_class, mirror::Class::kStatusLoaded, self); - new_class->PopulateEmbeddedVTable(image_pointer_size_); + { + ArtMethod* imt[mirror::Class::kImtSize]; + std::fill_n(imt, arraysize(imt), Runtime::Current()->GetImtUnimplementedMethod()); + new_class->PopulateEmbeddedImtAndVTable(imt, image_pointer_size_); + } mirror::Class::SetStatus(new_class, mirror::Class::kStatusInitialized, self); // don't need to set new_class->SetObjectSize(..) // because Object::SizeOf delegates to Array::SizeOf + // All arrays have java/lang/Cloneable and java/io/Serializable as // interfaces. We need to set that up here, so that stuff like // "instanceof" works right. @@ -5060,11 +5063,9 @@ bool ClassLinker::LinkClass(Thread* self, if (!LinkSuperClass(klass)) { return false; } - ArtMethod* imt_data[ImTable::kSize]; - // If there are any new conflicts compared to super class. - bool new_conflict = false; - std::fill_n(imt_data, arraysize(imt_data), Runtime::Current()->GetImtUnimplementedMethod()); - if (!LinkMethods(self, klass, interfaces, &new_conflict, imt_data)) { + ArtMethod* imt[mirror::Class::kImtSize]; + std::fill_n(imt, arraysize(imt), Runtime::Current()->GetImtUnimplementedMethod()); + if (!LinkMethods(self, klass, interfaces, imt)) { return false; } if (!LinkInstanceFields(self, klass)) { @@ -5077,45 +5078,15 @@ bool ClassLinker::LinkClass(Thread* self, CreateReferenceInstanceOffsets(klass); CHECK_EQ(mirror::Class::kStatusLoaded, klass->GetStatus()); - ImTable* imt = nullptr; - if (klass->ShouldHaveImt()) { - // If there are any new conflicts compared to the super class we can not make a copy. There - // can be cases where both will have a conflict method at the same slot without having the same - // set of conflicts. In this case, we can not share the IMT since the conflict table slow path - // will possibly create a table that is incorrect for either of the classes. - // Same IMT with new_conflict does not happen very often. - if (!new_conflict && klass->HasSuperClass() && klass->GetSuperClass()->ShouldHaveImt()) { - ImTable* super_imt = klass->GetSuperClass()->GetImt(image_pointer_size_); - bool imt_equals = true; - for (size_t i = 0; i < ImTable::kSize && imt_equals; ++i) { - imt_equals = imt_equals && (super_imt->Get(i, image_pointer_size_) == imt_data[i]); - } - if (imt_equals) { - imt = super_imt; - } - } - if (imt == nullptr) { - LinearAlloc* allocator = GetAllocatorForClassLoader(klass->GetClassLoader()); - imt = reinterpret_cast<ImTable*>( - allocator->Alloc(self, ImTable::SizeInBytes(image_pointer_size_))); - if (imt == nullptr) { - return false; - } - imt->Populate(imt_data, image_pointer_size_); - } - } - if (!klass->IsTemp() || (!init_done_ && klass->GetClassSize() == class_size)) { // We don't need to retire this class as it has no embedded tables or it was created the // correct size during class linker initialization. CHECK_EQ(klass->GetClassSize(), class_size) << PrettyDescriptor(klass.Get()); - if (klass->ShouldHaveEmbeddedVTable()) { - klass->PopulateEmbeddedVTable(image_pointer_size_); - } - if (klass->ShouldHaveImt()) { - klass->SetImt(imt, image_pointer_size_); + if (klass->ShouldHaveEmbeddedImtAndVTable()) { + klass->PopulateEmbeddedImtAndVTable(imt, image_pointer_size_); } + // This will notify waiters on klass that saw the not yet resolved // class in the class_table_ during EnsureResolved. mirror::Class::SetStatus(klass, mirror::Class::kStatusResolved, self); @@ -5507,7 +5478,6 @@ bool ClassLinker::LinkSuperClass(Handle<mirror::Class> klass) { bool ClassLinker::LinkMethods(Thread* self, Handle<mirror::Class> klass, Handle<mirror::ObjectArray<mirror::Class>> interfaces, - bool* out_new_conflict, ArtMethod** out_imt) { self->AllowThreadSuspension(); // A map from vtable indexes to the method they need to be updated to point to. Used because we @@ -5519,7 +5489,7 @@ bool ClassLinker::LinkMethods(Thread* self, // any vtable entries with new default method implementations. return SetupInterfaceLookupTable(self, klass, interfaces) && LinkVirtualMethods(self, klass, /*out*/ &default_translations) - && LinkInterfaceMethods(self, klass, default_translations, out_new_conflict, out_imt); + && LinkInterfaceMethods(self, klass, default_translations, out_imt); } // Comparator for name and signature of a method, used in finding overriding methods. Implementation @@ -5677,7 +5647,7 @@ bool ClassLinker::LinkVirtualMethods( StackHandleScope<2> hs(self); Handle<mirror::Class> super_class(hs.NewHandle(klass->GetSuperClass())); MutableHandle<mirror::PointerArray> vtable; - if (super_class->ShouldHaveEmbeddedVTable()) { + if (super_class->ShouldHaveEmbeddedImtAndVTable()) { vtable = hs.NewHandle(AllocPointerArray(self, max_count)); if (UNLIKELY(vtable.Get() == nullptr)) { self->AssertPendingOOMException(); @@ -6077,7 +6047,6 @@ ArtMethod* ClassLinker::AddMethodToConflictTable(mirror::Class* klass, void ClassLinker::SetIMTRef(ArtMethod* unimplemented_method, ArtMethod* imt_conflict_method, ArtMethod* current_method, - /*out*/bool* new_conflict, /*out*/ArtMethod** imt_ref) { // Place method in imt if entry is empty, place conflict otherwise. if (*imt_ref == unimplemented_method) { @@ -6094,82 +6063,40 @@ void ClassLinker::SetIMTRef(ArtMethod* unimplemented_method, *imt_ref = current_method; } else { *imt_ref = imt_conflict_method; - *new_conflict = true; } } else { // Place the default conflict method. Note that there may be an existing conflict // method in the IMT, but it could be one tailored to the super class, with a // specific ImtConflictTable. *imt_ref = imt_conflict_method; - *new_conflict = true; } } void ClassLinker::FillIMTAndConflictTables(mirror::Class* klass) { - DCHECK(klass->ShouldHaveImt()) << PrettyClass(klass); + DCHECK(klass->ShouldHaveEmbeddedImtAndVTable()) << PrettyClass(klass); DCHECK(!klass->IsTemp()) << PrettyClass(klass); - ArtMethod* imt_data[ImTable::kSize]; + ArtMethod* imt[mirror::Class::kImtSize]; Runtime* const runtime = Runtime::Current(); ArtMethod* const unimplemented_method = runtime->GetImtUnimplementedMethod(); ArtMethod* const conflict_method = runtime->GetImtConflictMethod(); - std::fill_n(imt_data, arraysize(imt_data), unimplemented_method); + std::fill_n(imt, arraysize(imt), unimplemented_method); if (klass->GetIfTable() != nullptr) { - bool new_conflict = false; FillIMTFromIfTable(klass->GetIfTable(), unimplemented_method, conflict_method, klass, - /*create_conflict_tables*/true, - /*ignore_copied_methods*/false, - &new_conflict, - &imt_data[0]); + true, + false, + &imt[0]); } - if (!klass->ShouldHaveImt()) { - return; - } - // Compare the IMT with the super class including the conflict methods. If they are equivalent, - // we can just use the same pointer. - ImTable* imt = nullptr; - mirror::Class* super_class = klass->GetSuperClass(); - if (super_class != nullptr && super_class->ShouldHaveImt()) { - ImTable* super_imt = super_class->GetImt(image_pointer_size_); - bool same = true; - for (size_t i = 0; same && i < ImTable::kSize; ++i) { - ArtMethod* method = imt_data[i]; - ArtMethod* super_method = super_imt->Get(i, image_pointer_size_); - if (method != super_method) { - bool is_conflict_table = method->IsRuntimeMethod() && - method != unimplemented_method && - method != conflict_method; - // Verify conflict contents. - bool super_conflict_table = super_method->IsRuntimeMethod() && - super_method != unimplemented_method && - super_method != conflict_method; - if (!is_conflict_table || !super_conflict_table) { - same = false; - } else { - ImtConflictTable* table1 = method->GetImtConflictTable(image_pointer_size_); - ImtConflictTable* table2 = super_method->GetImtConflictTable(image_pointer_size_); - same = same && table1->Equals(table2, image_pointer_size_); - } - } - } - if (same) { - imt = super_imt; - } - } - if (imt == nullptr) { - imt = klass->GetImt(image_pointer_size_); - DCHECK(imt != nullptr); - imt->Populate(imt_data, image_pointer_size_); - } else { - klass->SetImt(imt, image_pointer_size_); + for (size_t i = 0; i < mirror::Class::kImtSize; ++i) { + klass->SetEmbeddedImTableEntry(i, imt[i], image_pointer_size_); } } static inline uint32_t GetIMTIndex(ArtMethod* interface_method) SHARED_REQUIRES(Locks::mutator_lock_) { - return interface_method->GetDexMethodIndex() % ImTable::kSize; + return interface_method->GetDexMethodIndex() % mirror::Class::kImtSize; } ImtConflictTable* ClassLinker::CreateImtConflictTable(size_t count, @@ -6191,9 +6118,8 @@ void ClassLinker::FillIMTFromIfTable(mirror::IfTable* if_table, mirror::Class* klass, bool create_conflict_tables, bool ignore_copied_methods, - /*out*/bool* new_conflict, - /*out*/ArtMethod** imt) { - uint32_t conflict_counts[ImTable::kSize] = {}; + ArtMethod** imt) { + uint32_t conflict_counts[mirror::Class::kImtSize] = {}; for (size_t i = 0, length = if_table->Count(); i < length; ++i) { mirror::Class* interface = if_table->GetInterface(i); const size_t num_virtuals = interface->NumVirtualMethods(); @@ -6235,7 +6161,6 @@ void ClassLinker::FillIMTFromIfTable(mirror::IfTable* if_table, SetIMTRef(unimplemented_method, imt_conflict_method, implementation_method, - /*out*/new_conflict, /*out*/&imt[imt_index]); } } @@ -6243,7 +6168,7 @@ void ClassLinker::FillIMTFromIfTable(mirror::IfTable* if_table, if (create_conflict_tables) { // Create the conflict tables. LinearAlloc* linear_alloc = GetAllocatorForClassLoader(klass->GetClassLoader()); - for (size_t i = 0; i < ImTable::kSize; ++i) { + for (size_t i = 0; i < mirror::Class::kImtSize; ++i) { size_t conflicts = conflict_counts[i]; if (imt[i] == imt_conflict_method) { ImtConflictTable* new_table = CreateImtConflictTable(conflicts, linear_alloc); @@ -6530,14 +6455,12 @@ static void SanityCheckVTable(Handle<mirror::Class> klass, uint32_t pointer_size void ClassLinker::FillImtFromSuperClass(Handle<mirror::Class> klass, ArtMethod* unimplemented_method, ArtMethod* imt_conflict_method, - bool* new_conflict, ArtMethod** imt) { DCHECK(klass->HasSuperClass()); mirror::Class* super_class = klass->GetSuperClass(); - if (super_class->ShouldHaveImt()) { - ImTable* super_imt = super_class->GetImt(image_pointer_size_); - for (size_t i = 0; i < ImTable::kSize; ++i) { - imt[i] = super_imt->Get(i, image_pointer_size_); + if (super_class->ShouldHaveEmbeddedImtAndVTable()) { + for (size_t i = 0; i < mirror::Class::kImtSize; ++i) { + imt[i] = super_class->GetEmbeddedImTableEntry(i, image_pointer_size_); } } else { // No imt in the super class, need to reconstruct from the iftable. @@ -6550,7 +6473,6 @@ void ClassLinker::FillImtFromSuperClass(Handle<mirror::Class> klass, klass.Get(), /*create_conflict_table*/false, /*ignore_copied_methods*/true, - /*out*/new_conflict, /*out*/imt); } } @@ -6561,7 +6483,6 @@ bool ClassLinker::LinkInterfaceMethods( Thread* self, Handle<mirror::Class> klass, const std::unordered_map<size_t, ClassLinker::MethodTranslation>& default_translations, - bool* out_new_conflict, ArtMethod** out_imt) { StackHandleScope<3> hs(self); Runtime* const runtime = Runtime::Current(); @@ -6597,7 +6518,6 @@ bool ClassLinker::LinkInterfaceMethods( FillImtFromSuperClass(klass, unimplemented_method, imt_conflict_method, - out_new_conflict, out_imt); } // Allocate method arrays before since we don't want miss visiting miranda method roots due to @@ -6729,7 +6649,6 @@ bool ClassLinker::LinkInterfaceMethods( SetIMTRef(unimplemented_method, imt_conflict_method, vtable_method, - /*out*/out_new_conflict, /*out*/imt_ptr); } break; @@ -6870,7 +6789,6 @@ bool ClassLinker::LinkInterfaceMethods( SetIMTRef(unimplemented_method, imt_conflict_method, current_method, - /*out*/out_new_conflict, /*out*/imt_ptr); } } @@ -7070,7 +6988,7 @@ bool ClassLinker::LinkInterfaceMethods( } // Fix up IMT next - for (size_t i = 0; i < ImTable::kSize; ++i) { + for (size_t i = 0; i < mirror::Class::kImtSize; ++i) { auto it = move_table.find(out_imt[i]); if (it != move_table.end()) { out_imt[i] = it->second; |