diff options
Diffstat (limited to 'runtime/class_linker.cc')
-rw-r--r-- | runtime/class_linker.cc | 122 |
1 files changed, 59 insertions, 63 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 1c3375c93a..41adae4c8a 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -57,6 +57,7 @@ #include "gc/accounting/heap_bitmap-inl.h" #include "gc/accounting/space_bitmap-inl.h" #include "gc/heap.h" +#include "gc/heap-visit-objects-inl.h" #include "gc/scoped_gc_critical_section.h" #include "gc/space/image_space.h" #include "gc/space/space-inl.h" @@ -863,24 +864,6 @@ struct TrampolineCheckData { bool error; }; -static void CheckTrampolines(mirror::Object* obj, void* arg) NO_THREAD_SAFETY_ANALYSIS { - if (obj->IsClass()) { - ObjPtr<mirror::Class> klass = obj->AsClass(); - TrampolineCheckData* d = reinterpret_cast<TrampolineCheckData*>(arg); - for (ArtMethod& m : klass->GetMethods(d->pointer_size)) { - const void* entrypoint = m.GetEntryPointFromQuickCompiledCodePtrSize(d->pointer_size); - if (entrypoint == d->quick_resolution_trampoline || - entrypoint == d->quick_imt_conflict_trampoline || - entrypoint == d->quick_generic_jni_trampoline || - entrypoint == d->quick_to_interpreter_bridge_trampoline) { - d->m = &m; - d->error = true; - return; - } - } - } -} - bool ClassLinker::InitFromBootImage(std::string* error_msg) { VLOG(startup) << __FUNCTION__ << " entering"; CHECK(!init_done_); @@ -945,7 +928,24 @@ bool ClassLinker::InitFromBootImage(std::string* error_msg) { data.quick_generic_jni_trampoline = ith_quick_generic_jni_trampoline; data.quick_to_interpreter_bridge_trampoline = ith_quick_to_interpreter_bridge_trampoline; ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_); - spaces[i]->GetLiveBitmap()->Walk(CheckTrampolines, &data); + auto visitor = [&](mirror::Object* obj) REQUIRES_SHARED(Locks::mutator_lock_) { + if (obj->IsClass()) { + ObjPtr<mirror::Class> klass = obj->AsClass(); + for (ArtMethod& m : klass->GetMethods(data.pointer_size)) { + const void* entrypoint = + m.GetEntryPointFromQuickCompiledCodePtrSize(data.pointer_size); + if (entrypoint == data.quick_resolution_trampoline || + entrypoint == data.quick_imt_conflict_trampoline || + entrypoint == data.quick_generic_jni_trampoline || + entrypoint == data.quick_to_interpreter_bridge_trampoline) { + data.m = &m; + data.error = true; + return; + } + } + } + }; + spaces[i]->GetLiveBitmap()->Walk(visitor); if (data.error) { ArtMethod* m = data.m; LOG(ERROR) << "Found a broken ArtMethod: " << ArtMethod::PrettyMethod(m); @@ -1620,7 +1620,46 @@ class ImageSanityChecks FINAL { static void CheckObjects(gc::Heap* heap, ClassLinker* class_linker) REQUIRES_SHARED(Locks::mutator_lock_) { ImageSanityChecks isc(heap, class_linker); - heap->VisitObjects(ImageSanityChecks::SanityCheckObjectsCallback, &isc); + auto visitor = [&](mirror::Object* obj) REQUIRES_SHARED(Locks::mutator_lock_) { + DCHECK(obj != nullptr); + CHECK(obj->GetClass() != nullptr) << "Null class in object " << obj; + CHECK(obj->GetClass()->GetClass() != nullptr) << "Null class class " << obj; + if (obj->IsClass()) { + auto klass = obj->AsClass(); + for (ArtField& field : klass->GetIFields()) { + CHECK_EQ(field.GetDeclaringClass(), klass); + } + for (ArtField& field : klass->GetSFields()) { + CHECK_EQ(field.GetDeclaringClass(), klass); + } + const auto pointer_size = isc.pointer_size_; + for (auto& m : klass->GetMethods(pointer_size)) { + isc.SanityCheckArtMethod(&m, klass); + } + auto* vtable = klass->GetVTable(); + if (vtable != nullptr) { + isc.SanityCheckArtMethodPointerArray(vtable, nullptr); + } + if (klass->ShouldHaveImt()) { + ImTable* imt = klass->GetImt(pointer_size); + for (size_t i = 0; i < ImTable::kSize; ++i) { + isc.SanityCheckArtMethod(imt->Get(i, pointer_size), nullptr); + } + } + if (klass->ShouldHaveEmbeddedVTable()) { + for (int32_t i = 0; i < klass->GetEmbeddedVTableLength(); ++i) { + isc.SanityCheckArtMethod(klass->GetEmbeddedVTableEntry(i, pointer_size), nullptr); + } + } + mirror::IfTable* iftable = klass->GetIfTable(); + for (int32_t i = 0; i < klass->GetIfTableCount(); ++i) { + if (iftable->GetMethodArrayCount(i) > 0) { + isc.SanityCheckArtMethodPointerArray(iftable->GetMethodArray(i), nullptr); + } + } + } + }; + heap->VisitObjects(visitor); } static void CheckPointerArray(gc::Heap* heap, @@ -1632,49 +1671,6 @@ class ImageSanityChecks FINAL { isc.SanityCheckArtMethodPointerArray(arr, size); } - static void SanityCheckObjectsCallback(mirror::Object* obj, void* arg) - REQUIRES_SHARED(Locks::mutator_lock_) { - DCHECK(obj != nullptr); - CHECK(obj->GetClass() != nullptr) << "Null class in object " << obj; - CHECK(obj->GetClass()->GetClass() != nullptr) << "Null class class " << obj; - if (obj->IsClass()) { - ImageSanityChecks* isc = reinterpret_cast<ImageSanityChecks*>(arg); - - auto klass = obj->AsClass(); - for (ArtField& field : klass->GetIFields()) { - CHECK_EQ(field.GetDeclaringClass(), klass); - } - for (ArtField& field : klass->GetSFields()) { - CHECK_EQ(field.GetDeclaringClass(), klass); - } - const auto pointer_size = isc->pointer_size_; - for (auto& m : klass->GetMethods(pointer_size)) { - isc->SanityCheckArtMethod(&m, klass); - } - auto* vtable = klass->GetVTable(); - if (vtable != nullptr) { - isc->SanityCheckArtMethodPointerArray(vtable, nullptr); - } - if (klass->ShouldHaveImt()) { - ImTable* imt = klass->GetImt(pointer_size); - for (size_t i = 0; i < ImTable::kSize; ++i) { - isc->SanityCheckArtMethod(imt->Get(i, pointer_size), nullptr); - } - } - if (klass->ShouldHaveEmbeddedVTable()) { - for (int32_t i = 0; i < klass->GetEmbeddedVTableLength(); ++i) { - isc->SanityCheckArtMethod(klass->GetEmbeddedVTableEntry(i, pointer_size), nullptr); - } - } - mirror::IfTable* iftable = klass->GetIfTable(); - for (int32_t i = 0; i < klass->GetIfTableCount(); ++i) { - if (iftable->GetMethodArrayCount(i) > 0) { - isc->SanityCheckArtMethodPointerArray(iftable->GetMethodArray(i), nullptr); - } - } - } - } - private: ImageSanityChecks(gc::Heap* heap, ClassLinker* class_linker) : spaces_(heap->GetBootImageSpaces()), |