summaryrefslogtreecommitdiffstats
path: root/runtime/class_linker.cc
diff options
context:
space:
mode:
authorJeff Hao <jeffhao@google.com>2016-06-28 23:47:09 +0000
committerJeff Hao <jeffhao@google.com>2016-06-29 01:23:37 +0000
commitfd43db68d204caaa0e411ca79a37af15d1c001af (patch)
tree1c26b5329dd7fee6884ec608e7fb1038c848ed1f /runtime/class_linker.cc
parent6777a3ceaf9ad3c7906805f0c05680d60db2b6b3 (diff)
downloadandroid_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.cc150
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;