diff options
| -rw-r--r-- | compiler/driver/compiler_driver.cc | 169 | ||||
| -rw-r--r-- | compiler/image_writer.cc | 54 | ||||
| -rw-r--r-- | compiler/image_writer.h | 5 | ||||
| -rw-r--r-- | runtime/class_linker.cc | 109 | ||||
| -rw-r--r-- | runtime/class_linker.h | 6 | ||||
| -rw-r--r-- | runtime/class_table.cc | 4 | ||||
| -rw-r--r-- | runtime/class_table.h | 9 | ||||
| -rw-r--r-- | runtime/debugger.cc | 38 | ||||
| -rw-r--r-- | runtime/instrumentation.cc | 26 |
9 files changed, 230 insertions, 190 deletions
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index a35f306612..affa52a37a 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -690,66 +690,76 @@ bool CompilerDriver::IsMethodToCompile(const MethodReference& method_ref) const return methods_to_compile_->find(tmp.c_str()) != methods_to_compile_->end(); } -static void ResolveExceptionsForMethod( - ArtMethod* method_handle, std::set<std::pair<uint16_t, const DexFile*>>& exceptions_to_resolve) - SHARED_REQUIRES(Locks::mutator_lock_) { - const DexFile::CodeItem* code_item = method_handle->GetCodeItem(); - if (code_item == nullptr) { - return; // native or abstract method - } - if (code_item->tries_size_ == 0) { - return; // nothing to process - } - const uint8_t* encoded_catch_handler_list = DexFile::GetCatchHandlerData(*code_item, 0); - size_t num_encoded_catch_handlers = DecodeUnsignedLeb128(&encoded_catch_handler_list); - for (size_t i = 0; i < num_encoded_catch_handlers; i++) { - int32_t encoded_catch_handler_size = DecodeSignedLeb128(&encoded_catch_handler_list); - bool has_catch_all = false; - if (encoded_catch_handler_size <= 0) { - encoded_catch_handler_size = -encoded_catch_handler_size; - has_catch_all = true; - } - for (int32_t j = 0; j < encoded_catch_handler_size; j++) { - uint16_t encoded_catch_handler_handlers_type_idx = - DecodeUnsignedLeb128(&encoded_catch_handler_list); - // Add to set of types to resolve if not already in the dex cache resolved types - if (!method_handle->IsResolvedTypeIdx(encoded_catch_handler_handlers_type_idx)) { - exceptions_to_resolve.insert( - std::pair<uint16_t, const DexFile*>(encoded_catch_handler_handlers_type_idx, - method_handle->GetDexFile())); +class ResolveCatchBlockExceptionsClassVisitor : public ClassVisitor { + public: + ResolveCatchBlockExceptionsClassVisitor( + std::set<std::pair<uint16_t, const DexFile*>>& exceptions_to_resolve) + : exceptions_to_resolve_(exceptions_to_resolve) {} + + void ResolveExceptionsForMethod(ArtMethod* method_handle) SHARED_REQUIRES(Locks::mutator_lock_) { + const DexFile::CodeItem* code_item = method_handle->GetCodeItem(); + if (code_item == nullptr) { + return; // native or abstract method + } + if (code_item->tries_size_ == 0) { + return; // nothing to process + } + const uint8_t* encoded_catch_handler_list = DexFile::GetCatchHandlerData(*code_item, 0); + size_t num_encoded_catch_handlers = DecodeUnsignedLeb128(&encoded_catch_handler_list); + for (size_t i = 0; i < num_encoded_catch_handlers; i++) { + int32_t encoded_catch_handler_size = DecodeSignedLeb128(&encoded_catch_handler_list); + bool has_catch_all = false; + if (encoded_catch_handler_size <= 0) { + encoded_catch_handler_size = -encoded_catch_handler_size; + has_catch_all = true; + } + for (int32_t j = 0; j < encoded_catch_handler_size; j++) { + uint16_t encoded_catch_handler_handlers_type_idx = + DecodeUnsignedLeb128(&encoded_catch_handler_list); + // Add to set of types to resolve if not already in the dex cache resolved types + if (!method_handle->IsResolvedTypeIdx(encoded_catch_handler_handlers_type_idx)) { + exceptions_to_resolve_.emplace(encoded_catch_handler_handlers_type_idx, + method_handle->GetDexFile()); + } + // ignore address associated with catch handler + DecodeUnsignedLeb128(&encoded_catch_handler_list); + } + if (has_catch_all) { + // ignore catch all address + DecodeUnsignedLeb128(&encoded_catch_handler_list); } - // ignore address associated with catch handler - DecodeUnsignedLeb128(&encoded_catch_handler_list); - } - if (has_catch_all) { - // ignore catch all address - DecodeUnsignedLeb128(&encoded_catch_handler_list); } } -} -static bool ResolveCatchBlockExceptionsClassVisitor(mirror::Class* c, void* arg) - SHARED_REQUIRES(Locks::mutator_lock_) { - auto* exceptions_to_resolve = - reinterpret_cast<std::set<std::pair<uint16_t, const DexFile*>>*>(arg); - const auto pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize(); - for (auto& m : c->GetVirtualMethods(pointer_size)) { - ResolveExceptionsForMethod(&m, *exceptions_to_resolve); + virtual bool Visit(mirror::Class* c) OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) { + const auto pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize(); + for (auto& m : c->GetVirtualMethods(pointer_size)) { + ResolveExceptionsForMethod(&m); + } + for (auto& m : c->GetDirectMethods(pointer_size)) { + ResolveExceptionsForMethod(&m); + } + return true; } - for (auto& m : c->GetDirectMethods(pointer_size)) { - ResolveExceptionsForMethod(&m, *exceptions_to_resolve); + + private: + std::set<std::pair<uint16_t, const DexFile*>>& exceptions_to_resolve_; +}; + +class RecordImageClassesVisitor : public ClassVisitor { + public: + explicit RecordImageClassesVisitor(std::unordered_set<std::string>* image_classes) + : image_classes_(image_classes) {} + + bool Visit(mirror::Class* klass) OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) { + std::string temp; + image_classes_->insert(klass->GetDescriptor(&temp)); + return true; } - return true; -} -static bool RecordImageClassesVisitor(mirror::Class* klass, void* arg) - SHARED_REQUIRES(Locks::mutator_lock_) { - std::unordered_set<std::string>* image_classes = - reinterpret_cast<std::unordered_set<std::string>*>(arg); - std::string temp; - image_classes->insert(klass->GetDescriptor(&temp)); - return true; -} + private: + std::unordered_set<std::string>* const image_classes_; +}; // Make a list of descriptors for classes to include in the image void CompilerDriver::LoadImageClasses(TimingLogger* timings) { @@ -787,8 +797,8 @@ void CompilerDriver::LoadImageClasses(TimingLogger* timings) { hs.NewHandle(class_linker->FindSystemClass(self, "Ljava/lang/Throwable;"))); do { unresolved_exception_types.clear(); - class_linker->VisitClasses(ResolveCatchBlockExceptionsClassVisitor, - &unresolved_exception_types); + ResolveCatchBlockExceptionsClassVisitor visitor(unresolved_exception_types); + class_linker->VisitClasses(&visitor); for (const std::pair<uint16_t, const DexFile*>& exception_type : unresolved_exception_types) { uint16_t exception_type_idx = exception_type.first; const DexFile* dex_file = exception_type.second; @@ -811,7 +821,8 @@ void CompilerDriver::LoadImageClasses(TimingLogger* timings) { // We walk the roots looking for classes so that we'll pick up the // above classes plus any classes them depend on such super // classes, interfaces, and the required ClassLinker roots. - class_linker->VisitClasses(RecordImageClassesVisitor, image_classes_.get()); + RecordImageClassesVisitor visitor(image_classes_.get()); + class_linker->VisitClasses(&visitor); CHECK_NE(image_classes_->size(), 0U); } @@ -899,6 +910,29 @@ class ClinitImageUpdate { } private: + class FindImageClassesVisitor : public ClassVisitor { + public: + explicit FindImageClassesVisitor(ClinitImageUpdate* data) : data_(data) {} + + bool Visit(mirror::Class* klass) OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) { + std::string temp; + const char* name = klass->GetDescriptor(&temp); + if (data_->image_class_descriptors_->find(name) != data_->image_class_descriptors_->end()) { + data_->image_classes_.push_back(klass); + } else { + // Check whether it is initialized and has a clinit. They must be kept, too. + if (klass->IsInitialized() && klass->FindClassInitializer( + Runtime::Current()->GetClassLinker()->GetImagePointerSize()) != nullptr) { + data_->image_classes_.push_back(klass); + } + } + return true; + } + + private: + ClinitImageUpdate* const data_; + }; + ClinitImageUpdate(std::unordered_set<std::string>* image_class_descriptors, Thread* self, ClassLinker* linker) SHARED_REQUIRES(Locks::mutator_lock_) : @@ -915,25 +949,8 @@ class ClinitImageUpdate { // Find all the already-marked classes. WriterMutexLock mu(self, *Locks::heap_bitmap_lock_); - linker->VisitClasses(FindImageClasses, this); - } - - static bool FindImageClasses(mirror::Class* klass, void* arg) - SHARED_REQUIRES(Locks::mutator_lock_) { - ClinitImageUpdate* data = reinterpret_cast<ClinitImageUpdate*>(arg); - std::string temp; - const char* name = klass->GetDescriptor(&temp); - if (data->image_class_descriptors_->find(name) != data->image_class_descriptors_->end()) { - data->image_classes_.push_back(klass); - } else { - // Check whether it is initialized and has a clinit. They must be kept, too. - if (klass->IsInitialized() && klass->FindClassInitializer( - Runtime::Current()->GetClassLinker()->GetImagePointerSize()) != nullptr) { - data->image_classes_.push_back(klass); - } - } - - return true; + FindImageClassesVisitor visitor(this); + linker->VisitClasses(&visitor); } void VisitClinitClassesObject(mirror::Object* object) const @@ -1731,7 +1748,7 @@ class ResolveClassFieldsAndMethodsVisitor : public CompilationVisitor { explicit ResolveClassFieldsAndMethodsVisitor(const ParallelCompilationManager* manager) : manager_(manager) {} - virtual void Visit(size_t class_def_index) OVERRIDE REQUIRES(!Locks::mutator_lock_) { + void Visit(size_t class_def_index) OVERRIDE REQUIRES(!Locks::mutator_lock_) { ATRACE_CALL(); Thread* const self = Thread::Current(); jobject jclass_loader = manager_->GetClassLoader(); diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc index 293a488ccf..dda36fa2ef 100644 --- a/compiler/image_writer.cc +++ b/compiler/image_writer.cc @@ -539,16 +539,19 @@ bool ImageWriter::AllocMemory() { return true; } +class ComputeLazyFieldsForClassesVisitor : public ClassVisitor { + public: + bool Visit(Class* c) OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) { + StackHandleScope<1> hs(Thread::Current()); + mirror::Class::ComputeName(hs.NewHandle(c)); + return true; + } +}; + void ImageWriter::ComputeLazyFieldsForImageClasses() { ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - class_linker->VisitClassesWithoutClassesLock(ComputeLazyFieldsForClassesVisitor, nullptr); -} - -bool ImageWriter::ComputeLazyFieldsForClassesVisitor(Class* c, void* /*arg*/) { - Thread* self = Thread::Current(); - StackHandleScope<1> hs(self); - mirror::Class::ComputeName(hs.NewHandle(c)); - return true; + ComputeLazyFieldsForClassesVisitor visitor; + class_linker->VisitClassesWithoutClassesLock(&visitor); } void ImageWriter::ComputeEagerResolvedStringsCallback(Object* obj, void* arg ATTRIBUTE_UNUSED) { @@ -592,9 +595,20 @@ bool ImageWriter::IsImageClass(Class* klass) { return compiler_driver_.IsImageClass(klass->GetDescriptor(&temp)); } -struct NonImageClasses { - ImageWriter* image_writer; - std::set<std::string>* non_image_classes; +class NonImageClassesVisitor : public ClassVisitor { + public: + explicit NonImageClassesVisitor(ImageWriter* image_writer) : image_writer_(image_writer) {} + + bool Visit(Class* klass) OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) { + if (!image_writer_->IsImageClass(klass)) { + std::string temp; + non_image_classes_.insert(klass->GetDescriptor(&temp)); + } + return true; + } + + std::set<std::string> non_image_classes_; + ImageWriter* const image_writer_; }; void ImageWriter::PruneNonImageClasses() { @@ -606,14 +620,11 @@ void ImageWriter::PruneNonImageClasses() { Thread* self = Thread::Current(); // Make a list of classes we would like to prune. - std::set<std::string> non_image_classes; - NonImageClasses context; - context.image_writer = this; - context.non_image_classes = &non_image_classes; - class_linker->VisitClasses(NonImageClassesVisitor, &context); + NonImageClassesVisitor visitor(this); + class_linker->VisitClasses(&visitor); // Remove the undesired classes from the class roots. - for (const std::string& it : non_image_classes) { + for (const std::string& it : visitor.non_image_classes_) { bool result = class_linker->RemoveClass(it.c_str(), nullptr); DCHECK(result); } @@ -669,15 +680,6 @@ void ImageWriter::PruneNonImageClasses() { class_linker->DropFindArrayClassCache(); } -bool ImageWriter::NonImageClassesVisitor(Class* klass, void* arg) { - NonImageClasses* context = reinterpret_cast<NonImageClasses*>(arg); - if (!context->image_writer->IsImageClass(klass)) { - std::string temp; - context->non_image_classes->insert(klass->GetDescriptor(&temp)); - } - return true; -} - void ImageWriter::CheckNonImageClassesRemoved() { if (compiler_driver_.GetImageClasses() != nullptr) { gc::Heap* heap = Runtime::Current()->GetHeap(); diff --git a/compiler/image_writer.h b/compiler/image_writer.h index 42b1cbf58a..cabd918354 100644 --- a/compiler/image_writer.h +++ b/compiler/image_writer.h @@ -217,8 +217,6 @@ class ImageWriter FINAL { // Preinitializes some otherwise lazy fields (such as Class name) to avoid runtime image dirtying. void ComputeLazyFieldsForImageClasses() SHARED_REQUIRES(Locks::mutator_lock_); - static bool ComputeLazyFieldsForClassesVisitor(mirror::Class* klass, void* arg) - SHARED_REQUIRES(Locks::mutator_lock_); // Wire dex cache resolved strings to strings in the image to avoid runtime resolution. void ComputeEagerResolvedStrings() SHARED_REQUIRES(Locks::mutator_lock_); @@ -227,8 +225,6 @@ class ImageWriter FINAL { // Remove unwanted classes from various roots. void PruneNonImageClasses() SHARED_REQUIRES(Locks::mutator_lock_); - static bool NonImageClassesVisitor(mirror::Class* c, void* arg) - SHARED_REQUIRES(Locks::mutator_lock_); // Verify unwanted classes removed. void CheckNonImageClassesRemoved() SHARED_REQUIRES(Locks::mutator_lock_); @@ -376,6 +372,7 @@ class ImageWriter FINAL { friend class FixupClassVisitor; friend class FixupRootVisitor; friend class FixupVisitor; + friend class NonImageClassesVisitor; DISALLOW_COPY_AND_ASSIGN(ImageWriter); }; diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index ce54c14d5d..3883246778 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -1332,16 +1332,16 @@ void ClassLinker::VisitRoots(RootVisitor* visitor, VisitRootFlags flags) { } } -void ClassLinker::VisitClassesInternal(ClassVisitor* visitor, void* arg) { +void ClassLinker::VisitClassesInternal(ClassVisitor* visitor) { for (auto& pair : classes_) { ClassTable* const class_table = pair.second; - if (!class_table->Visit(visitor, arg)) { + if (!class_table->Visit(visitor)) { return; } } } -void ClassLinker::VisitClasses(ClassVisitor* visitor, void* arg) { +void ClassLinker::VisitClasses(ClassVisitor* visitor) { if (dex_cache_image_class_lookup_required_) { MoveImageClassesToClassTable(); } @@ -1350,79 +1350,85 @@ void ClassLinker::VisitClasses(ClassVisitor* visitor, void* arg) { // Not safe to have thread suspension when we are holding a lock. if (self != nullptr) { ScopedAssertNoThreadSuspension nts(self, __FUNCTION__); - VisitClassesInternal(visitor, arg); + VisitClassesInternal(visitor); } else { - VisitClassesInternal(visitor, arg); + VisitClassesInternal(visitor); } } -static bool GetClassesVisitorSet(mirror::Class* c, void* arg) { - std::set<mirror::Class*>* classes = reinterpret_cast<std::set<mirror::Class*>*>(arg); - classes->insert(c); - return true; -} - -struct GetClassesVisitorArrayArg { - Handle<mirror::ObjectArray<mirror::Class>>* classes; - int32_t index; - bool success; +class GetClassesInToVector : public ClassVisitor { + public: + bool Visit(mirror::Class* klass) OVERRIDE { + classes_.push_back(klass); + return true; + } + std::vector<mirror::Class*> classes_; }; -static bool GetClassesVisitorArray(mirror::Class* c, void* varg) - SHARED_REQUIRES(Locks::mutator_lock_) { - GetClassesVisitorArrayArg* arg = reinterpret_cast<GetClassesVisitorArrayArg*>(varg); - if (arg->index < (*arg->classes)->GetLength()) { - (*arg->classes)->Set(arg->index, c); - arg->index++; - return true; - } else { - arg->success = false; +class GetClassInToObjectArray : public ClassVisitor { + public: + explicit GetClassInToObjectArray(mirror::ObjectArray<mirror::Class>* arr) + : arr_(arr), index_(0) {} + + bool Visit(mirror::Class* klass) OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) { + ++index_; + if (index_ <= arr_->GetLength()) { + arr_->Set(index_ - 1, klass); + return true; + } return false; } -} -void ClassLinker::VisitClassesWithoutClassesLock(ClassVisitor* visitor, void* arg) { + bool Succeeded() const SHARED_REQUIRES(Locks::mutator_lock_) { + return index_ <= arr_->GetLength(); + } + + private: + mirror::ObjectArray<mirror::Class>* const arr_; + int32_t index_; +}; + +void ClassLinker::VisitClassesWithoutClassesLock(ClassVisitor* visitor) { // TODO: it may be possible to avoid secondary storage if we iterate over dex caches. The problem // is avoiding duplicates. if (!kMovingClasses) { - std::set<mirror::Class*> classes; - VisitClasses(GetClassesVisitorSet, &classes); - for (mirror::Class* klass : classes) { - if (!visitor(klass, arg)) { + GetClassesInToVector accumulator; + VisitClasses(&accumulator); + for (mirror::Class* klass : accumulator.classes_) { + if (!visitor->Visit(klass)) { return; } } } else { - Thread* self = Thread::Current(); + Thread* const self = Thread::Current(); StackHandleScope<1> hs(self); - MutableHandle<mirror::ObjectArray<mirror::Class>> classes = - hs.NewHandle<mirror::ObjectArray<mirror::Class>>(nullptr); - GetClassesVisitorArrayArg local_arg; - local_arg.classes = &classes; - local_arg.success = false; + auto classes = hs.NewHandle<mirror::ObjectArray<mirror::Class>>(nullptr); // We size the array assuming classes won't be added to the class table during the visit. // If this assumption fails we iterate again. - while (!local_arg.success) { + while (true) { size_t class_table_size; { ReaderMutexLock mu(self, *Locks::classlinker_classes_lock_); - class_table_size = NumZygoteClasses() + NumNonZygoteClasses(); + // Add 100 in case new classes get loaded when we are filling in the object array. + class_table_size = NumZygoteClasses() + NumNonZygoteClasses() + 100; } mirror::Class* class_type = mirror::Class::GetJavaLangClass(); mirror::Class* array_of_class = FindArrayClass(self, &class_type); classes.Assign( mirror::ObjectArray<mirror::Class>::Alloc(self, array_of_class, class_table_size)); CHECK(classes.Get() != nullptr); // OOME. - local_arg.index = 0; - local_arg.success = true; - VisitClasses(GetClassesVisitorArray, &local_arg); + GetClassInToObjectArray accumulator(classes.Get()); + VisitClasses(&accumulator); + if (accumulator.Succeeded()) { + break; + } } for (int32_t i = 0; i < classes->GetLength(); ++i) { // If the class table shrank during creation of the clases array we expect null elements. If // the class table grew then the loop repeats. If classes are created after the loop has // finished then we don't visit. mirror::Class* klass = classes->Get(i); - if (klass != nullptr && !visitor(klass, arg)) { + if (klass != nullptr && !visitor->Visit(klass)) { return; } } @@ -5563,13 +5569,22 @@ const char* ClassLinker::MethodShorty(uint32_t method_idx, ArtMethod* referrer, return dex_file.GetMethodShorty(method_id, length); } -bool DumpClassVisitor(mirror::Class* klass, void* arg) SHARED_REQUIRES(Locks::mutator_lock_) { - klass->DumpClass(LOG(ERROR), reinterpret_cast<ssize_t>(arg)); - return true; -} +class DumpClassVisitor : public ClassVisitor { + public: + explicit DumpClassVisitor(int flags) : flags_(flags) {} + + bool Visit(mirror::Class* klass) OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) { + klass->DumpClass(LOG(ERROR), flags_); + return true; + } + + private: + const int flags_; +}; void ClassLinker::DumpAllClasses(int flags) { - VisitClasses(&DumpClassVisitor, reinterpret_cast<void*>(flags)); + DumpClassVisitor visitor(flags); + VisitClasses(&visitor); } static OatFile::OatMethod CreateOatMethod(const void* code) { diff --git a/runtime/class_linker.h b/runtime/class_linker.h index 13375639b7..c53ff616e5 100644 --- a/runtime/class_linker.h +++ b/runtime/class_linker.h @@ -288,14 +288,14 @@ class ClassLinker { const OatFile* GetPrimaryOatFile() REQUIRES(!dex_lock_); - void VisitClasses(ClassVisitor* visitor, void* arg) + void VisitClasses(ClassVisitor* visitor) REQUIRES(!Locks::classlinker_classes_lock_) SHARED_REQUIRES(Locks::mutator_lock_); // Less efficient variant of VisitClasses that copies the class_table_ into secondary storage // so that it can visit individual classes without holding the doesn't hold the // Locks::classlinker_classes_lock_. As the Locks::classlinker_classes_lock_ isn't held this code // can race with insertion and deletion of classes while the visitor is being called. - void VisitClassesWithoutClassesLock(ClassVisitor* visitor, void* arg) + void VisitClassesWithoutClassesLock(ClassVisitor* visitor) SHARED_REQUIRES(Locks::mutator_lock_) REQUIRES(!dex_lock_); void VisitClassRoots(RootVisitor* visitor, VisitRootFlags flags) @@ -486,7 +486,7 @@ class ClassLinker { typedef SafeMap<GcRoot<mirror::ClassLoader>, ClassTable*, CompareClassLoaderGcRoot> ClassLoaderClassTable; - void VisitClassesInternal(ClassVisitor* visitor, void* arg) + void VisitClassesInternal(ClassVisitor* visitor) REQUIRES(Locks::classlinker_classes_lock_) SHARED_REQUIRES(Locks::mutator_lock_); // Returns the number of zygote and image classes. diff --git a/runtime/class_table.cc b/runtime/class_table.cc index f775235505..c245d4e780 100644 --- a/runtime/class_table.cc +++ b/runtime/class_table.cc @@ -71,10 +71,10 @@ void ClassTable::VisitRoots(RootVisitor* visitor, VisitRootFlags flags ATTRIBUTE } } -bool ClassTable::Visit(ClassVisitor* visitor, void* arg) { +bool ClassTable::Visit(ClassVisitor* visitor) { for (ClassSet& class_set : classes_) { for (GcRoot<mirror::Class>& root : class_set) { - if (!visitor(root.Read(), arg)) { + if (!visitor->Visit(root.Read())) { return false; } } diff --git a/runtime/class_table.h b/runtime/class_table.h index af25131ab4..252a47dd25 100644 --- a/runtime/class_table.h +++ b/runtime/class_table.h @@ -36,7 +36,12 @@ namespace mirror { class ClassLoader; } // namespace mirror -typedef bool (ClassVisitor)(mirror::Class* c, void* arg); +class ClassVisitor { + public: + virtual ~ClassVisitor() {} + // Return true to continue visiting. + virtual bool Visit(mirror::Class* klass) = 0; +}; // Each loader has a ClassTable class ClassTable { @@ -66,7 +71,7 @@ class ClassTable { REQUIRES(Locks::classlinker_classes_lock_) SHARED_REQUIRES(Locks::mutator_lock_); // Return false if the callback told us to exit. - bool Visit(ClassVisitor* visitor, void* arg) + bool Visit(ClassVisitor* visitor) REQUIRES(Locks::classlinker_classes_lock_) SHARED_REQUIRES(Locks::mutator_lock_); mirror::Class* Lookup(const char* descriptor, size_t hash) diff --git a/runtime/debugger.cc b/runtime/debugger.cc index 287a50bb04..f0de65b816 100644 --- a/runtime/debugger.cc +++ b/runtime/debugger.cc @@ -948,33 +948,27 @@ JDWP::JdwpError Dbg::GetReflectedType(JDWP::RefTypeId class_id, JDWP::ExpandBuf* return JDWP::ERR_NONE; } -void Dbg::GetClassList(std::vector<JDWP::RefTypeId>* classes) { - // Get the complete list of reference classes (i.e. all classes except - // the primitive types). - // Returns a newly-allocated buffer full of RefTypeId values. - struct ClassListCreator { - explicit ClassListCreator(std::vector<JDWP::RefTypeId>* classes_in) : classes(classes_in) { - } +// Get the complete list of reference classes (i.e. all classes except +// the primitive types). +// Returns a newly-allocated buffer full of RefTypeId values. +class ClassListCreator : public ClassVisitor { + public: + explicit ClassListCreator(std::vector<JDWP::RefTypeId>* classes) : classes_(classes) {} - static bool Visit(mirror::Class* c, void* arg) { - return reinterpret_cast<ClassListCreator*>(arg)->Visit(c); - } - - // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses - // annotalysis. - bool Visit(mirror::Class* c) NO_THREAD_SAFETY_ANALYSIS { - if (!c->IsPrimitive()) { - classes->push_back(gRegistry->AddRefType(c)); - } - return true; + bool Visit(mirror::Class* c) OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) { + if (!c->IsPrimitive()) { + classes_->push_back(Dbg::GetObjectRegistry()->AddRefType(c)); } + return true; + } - std::vector<JDWP::RefTypeId>* const classes; - }; + private: + std::vector<JDWP::RefTypeId>* const classes_; +}; +void Dbg::GetClassList(std::vector<JDWP::RefTypeId>* classes) { ClassListCreator clc(classes); - Runtime::Current()->GetClassLinker()->VisitClassesWithoutClassesLock(ClassListCreator::Visit, - &clc); + Runtime::Current()->GetClassLinker()->VisitClassesWithoutClassesLock(&clc); } JDWP::JdwpError Dbg::GetClassInfo(JDWP::RefTypeId class_id, JDWP::JdwpTypeTag* pTypeTag, diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc index 9711cf238e..e28d578121 100644 --- a/runtime/instrumentation.cc +++ b/runtime/instrumentation.cc @@ -49,12 +49,20 @@ constexpr bool kVerboseInstrumentation = false; static constexpr StackVisitor::StackWalkKind kInstrumentationStackWalk = StackVisitor::StackWalkKind::kSkipInlinedFrames; -static bool InstallStubsClassVisitor(mirror::Class* klass, void* arg) - REQUIRES(Locks::mutator_lock_) { - Instrumentation* instrumentation = reinterpret_cast<Instrumentation*>(arg); - instrumentation->InstallStubsForClass(klass); - return true; // we visit all classes. -} +class InstallStubsClassVisitor : public ClassVisitor { + public: + explicit InstallStubsClassVisitor(Instrumentation* instrumentation) + : instrumentation_(instrumentation) {} + + bool Visit(mirror::Class* klass) OVERRIDE REQUIRES(Locks::mutator_lock_) { + instrumentation_->InstallStubsForClass(klass); + return true; // we visit all classes. + } + + private: + Instrumentation* const instrumentation_; +}; + Instrumentation::Instrumentation() : instrumentation_stubs_installed_(false), entry_exit_stubs_installed_(false), @@ -563,14 +571,16 @@ void Instrumentation::ConfigureStubs(const char* key, InstrumentationLevel desir entry_exit_stubs_installed_ = true; interpreter_stubs_installed_ = false; } - runtime->GetClassLinker()->VisitClasses(InstallStubsClassVisitor, this); + InstallStubsClassVisitor visitor(this); + runtime->GetClassLinker()->VisitClasses(&visitor); instrumentation_stubs_installed_ = true; MutexLock mu(self, *Locks::thread_list_lock_); runtime->GetThreadList()->ForEach(InstrumentationInstallStack, this); } else { interpreter_stubs_installed_ = false; entry_exit_stubs_installed_ = false; - runtime->GetClassLinker()->VisitClasses(InstallStubsClassVisitor, this); + InstallStubsClassVisitor visitor(this); + runtime->GetClassLinker()->VisitClasses(&visitor); // Restore stack only if there is no method currently deoptimized. bool empty; { |