summaryrefslogtreecommitdiff
path: root/runtime/class_linker.cc
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/class_linker.cc')
-rw-r--r--runtime/class_linker.cc64
1 files changed, 31 insertions, 33 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 98fa897637..91b50006a9 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -1310,7 +1310,7 @@ void ClassLinker::VisitClassRoots(RootVisitor* visitor, VisitRootFlags flags) {
// reinit references to when reinitializing a ClassLinker from a
// mapped image.
void ClassLinker::VisitRoots(RootVisitor* visitor, VisitRootFlags flags) {
- class_roots_.VisitRoot(visitor, RootInfo(kRootVMInternal));
+ class_roots_.VisitRootIfNonNull(visitor, RootInfo(kRootVMInternal));
Thread* const self = Thread::Current();
{
ReaderMutexLock mu(self, dex_lock_);
@@ -1333,9 +1333,9 @@ void ClassLinker::VisitRoots(RootVisitor* visitor, VisitRootFlags flags) {
}
}
VisitClassRoots(visitor, flags);
- array_iftable_.VisitRoot(visitor, RootInfo(kRootVMInternal));
- for (size_t i = 0; i < kFindArrayCacheSize; ++i) {
- find_array_class_cache_[i].VisitRootIfNonNull(visitor, RootInfo(kRootVMInternal));
+ array_iftable_.VisitRootIfNonNull(visitor, RootInfo(kRootVMInternal));
+ for (GcRoot<mirror::Class>& root : find_array_class_cache_) {
+ root.VisitRootIfNonNull(visitor, RootInfo(kRootVMInternal));
}
}
@@ -4928,8 +4928,7 @@ bool ClassLinker::LinkInterfaceMethods(Thread* self, Handle<mirror::Class> klass
}
}
if (miranda_method == nullptr) {
- size_t size = ArtMethod::ObjectSize(image_pointer_size_);
- miranda_method = reinterpret_cast<ArtMethod*>(allocator.Alloc(size));
+ miranda_method = reinterpret_cast<ArtMethod*>(allocator.Alloc(method_size));
CHECK(miranda_method != nullptr);
// Point the interface table at a phantom slot.
new(miranda_method) ArtMethod(*interface_method, image_pointer_size_);
@@ -4970,50 +4969,49 @@ bool ClassLinker::LinkInterfaceMethods(Thread* self, Handle<mirror::Class> klass
}
StrideIterator<ArtMethod> out(
reinterpret_cast<uintptr_t>(virtuals) + old_method_count * method_size, method_size);
- // Copy the mirada methods before making a copy of the vtable so that moving GC doesn't miss
- // any roots. This is necessary since these miranda methods wont get their roots visited from
- // the class table root visiting until they are copied to the new virtuals array.
- const size_t old_vtable_count = vtable->GetLength();
- const size_t new_vtable_count = old_vtable_count + miranda_methods.size();
- size_t method_idx = old_vtable_count;
- for (auto* mir_method : miranda_methods) {
- ArtMethod* out_method = &*out;
- // Leave the declaring class alone as type indices are relative to it
- out_method->CopyFrom(mir_method, image_pointer_size_);
- out_method->SetAccessFlags(out_method->GetAccessFlags() | kAccMiranda);
- out_method->SetMethodIndex(0xFFFF & method_idx);
- move_table.emplace(mir_method, out_method);
+ // Copy over miranda methods before copying vtable since CopyOf may cause thread suspension and
+ // we want the roots of the miranda methods to get visited.
+ for (ArtMethod* mir_method : miranda_methods) {
+ out->CopyFrom(mir_method, image_pointer_size_);
+ out->SetAccessFlags(out->GetAccessFlags() | kAccMiranda);
+ move_table.emplace(mir_method, &*out);
++out;
- ++method_idx;
}
- DCHECK_EQ(new_vtable_count, method_idx);
UpdateClassVirtualMethods(klass.Get(), virtuals, new_method_count);
- // Done copying methods, they are all reachable from the class now, so we can end the no thread
+ // Done copying methods, they are all roots in the class now, so we can end the no thread
// suspension assert.
self->EndAssertNoThreadSuspension(old_cause);
+
+ const size_t old_vtable_count = vtable->GetLength();
+ const size_t new_vtable_count = old_vtable_count + miranda_methods.size();
+ miranda_methods.clear();
vtable.Assign(down_cast<mirror::PointerArray*>(vtable->CopyOf(self, new_vtable_count)));
if (UNLIKELY(vtable.Get() == nullptr)) {
self->AssertPendingOOMException();
return false;
}
+ out = StrideIterator<ArtMethod>(
+ reinterpret_cast<uintptr_t>(virtuals) + old_method_count * method_size, method_size);
+ size_t vtable_pos = old_vtable_count;
+ for (size_t i = old_method_count; i < new_method_count; ++i) {
+ // Leave the declaring class alone as type indices are relative to it
+ out->SetMethodIndex(0xFFFF & vtable_pos);
+ vtable->SetElementPtrSize(vtable_pos, &*out, image_pointer_size_);
+ ++out;
+ ++vtable_pos;
+ }
+ CHECK_EQ(vtable_pos, new_vtable_count);
// Update old vtable methods.
- for (method_idx = 0; method_idx < old_vtable_count; ++method_idx) {
- auto* m = vtable->GetElementPtrSize<ArtMethod*>(method_idx, image_pointer_size_);
+ for (size_t i = 0; i < old_vtable_count; ++i) {
+ auto* m = vtable->GetElementPtrSize<ArtMethod*>(i, image_pointer_size_);
DCHECK(m != nullptr) << PrettyClass(klass.Get());
auto it = move_table.find(m);
if (it != move_table.end()) {
auto* new_m = it->second;
DCHECK(new_m != nullptr) << PrettyClass(klass.Get());
- vtable->SetElementPtrSize(method_idx, new_m, image_pointer_size_);
+ vtable->SetElementPtrSize(i, new_m, image_pointer_size_);
}
}
- // Update miranda methods.
- out = StrideIterator<ArtMethod>(
- reinterpret_cast<uintptr_t>(virtuals) + old_method_count * method_size, method_size);
- for (; method_idx < new_vtable_count; ++method_idx) {
- vtable->SetElementPtrSize(method_idx, &*out, image_pointer_size_);
- ++out;
- }
klass->SetVTable(vtable.Get());
// Go fix up all the stale miranda pointers.
@@ -5214,7 +5212,7 @@ bool ClassLinker::LinkFields(Thread* self, Handle<mirror::Class> klass, bool is_
ArtField* field = &fields[i];
VLOG(class_linker) << "LinkFields: " << (is_static ? "static" : "instance")
<< " class=" << PrettyClass(klass.Get()) << " field=" << PrettyField(field) << " offset="
- << field->GetOffset();
+ << field->GetOffsetDuringLinking();
if (i != 0) {
ArtField* const prev_field = &fields[i - 1];
// NOTE: The field names can be the same. This is not possible in the Java language