diff options
-rw-r--r-- | runtime/base/mutex.cc | 5 | ||||
-rw-r--r-- | runtime/base/mutex.h | 4 | ||||
-rw-r--r-- | runtime/entrypoints_order_test.cc | 3 | ||||
-rw-r--r-- | runtime/runtime.cc | 26 | ||||
-rw-r--r-- | runtime/runtime.h | 8 | ||||
-rw-r--r-- | runtime/thread.cc | 14 | ||||
-rw-r--r-- | runtime/thread.h | 17 | ||||
-rw-r--r-- | runtime/verifier/method_verifier.cc | 8 | ||||
-rw-r--r-- | runtime/verifier/method_verifier.h | 3 | ||||
-rw-r--r-- | runtime/verifier/reg_type.cc | 4 | ||||
-rw-r--r-- | runtime/verifier/reg_type.h | 2 | ||||
-rw-r--r-- | runtime/verifier/reg_type_cache.cc | 38 | ||||
-rw-r--r-- | runtime/verifier/reg_type_cache.h | 6 |
13 files changed, 58 insertions, 80 deletions
diff --git a/runtime/base/mutex.cc b/runtime/base/mutex.cc index 2ec2b0c1de..13dcb8c634 100644 --- a/runtime/base/mutex.cc +++ b/runtime/base/mutex.cc @@ -46,7 +46,6 @@ Mutex* Locks::intern_table_lock_ = nullptr; Mutex* Locks::jni_libraries_lock_ = nullptr; Mutex* Locks::logging_lock_ = nullptr; Mutex* Locks::mem_maps_lock_ = nullptr; -Mutex* Locks::method_verifiers_lock_ = nullptr; Mutex* Locks::modify_ldt_lock_ = nullptr; ReaderWriterMutex* Locks::mutator_lock_ = nullptr; Mutex* Locks::profiler_lock_ = nullptr; @@ -1002,10 +1001,6 @@ void Locks::Init() { classlinker_classes_lock_ = new ReaderWriterMutex("ClassLinker classes lock", current_lock_level); - UPDATE_CURRENT_LOCK_LEVEL(kMethodVerifiersLock); - DCHECK(method_verifiers_lock_ == nullptr); - method_verifiers_lock_ = new Mutex("Method verifiers lock", current_lock_level); - UPDATE_CURRENT_LOCK_LEVEL(kMonitorPoolLock); DCHECK(allocated_monitor_ids_lock_ == nullptr); allocated_monitor_ids_lock_ = new Mutex("allocated monitor ids lock", current_lock_level); diff --git a/runtime/base/mutex.h b/runtime/base/mutex.h index f9e1e6238a..6e7b04fc93 100644 --- a/runtime/base/mutex.h +++ b/runtime/base/mutex.h @@ -588,11 +588,9 @@ class Locks { // Guards lists of classes within the class linker. static ReaderWriterMutex* classlinker_classes_lock_ ACQUIRED_AFTER(breakpoint_lock_); - static Mutex* method_verifiers_lock_ ACQUIRED_AFTER(classlinker_classes_lock_); - // When declaring any Mutex add DEFAULT_MUTEX_ACQUIRED_AFTER to use annotalysis to check the code // doesn't try to hold a higher level Mutex. - #define DEFAULT_MUTEX_ACQUIRED_AFTER ACQUIRED_AFTER(Locks::method_verifiers_lock_) + #define DEFAULT_MUTEX_ACQUIRED_AFTER ACQUIRED_AFTER(Locks::classlinker_classes_lock_) static Mutex* allocated_monitor_ids_lock_ ACQUIRED_AFTER(classlinker_classes_lock_); diff --git a/runtime/entrypoints_order_test.cc b/runtime/entrypoints_order_test.cc index 0fdfcb3afe..88209a3d3c 100644 --- a/runtime/entrypoints_order_test.cc +++ b/runtime/entrypoints_order_test.cc @@ -129,7 +129,8 @@ class EntrypointsOrderTest : public CommonRuntimeTest { EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, held_mutexes, nested_signal_state, sizeof(void*) * kLockLevelCount); EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, nested_signal_state, flip_function, sizeof(void*)); - EXPECT_OFFSET_DIFF(Thread, tlsPtr_.flip_function, Thread, wait_mutex_, sizeof(void*), + EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, flip_function, method_verifier, sizeof(void*)); + EXPECT_OFFSET_DIFF(Thread, tlsPtr_.method_verifier, Thread, wait_mutex_, sizeof(void*), thread_tlsptr_end); } diff --git a/runtime/runtime.cc b/runtime/runtime.cc index a2f1481e63..189559e695 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -1331,12 +1331,6 @@ void Runtime::VisitNonThreadRoots(RootCallback* callback, void* arg) { callee_save_methods_[i].VisitRootIfNonNull(callback, arg, RootInfo(kRootVMInternal)); } verifier::MethodVerifier::VisitStaticRoots(callback, arg); - { - MutexLock mu(Thread::Current(), *Locks::method_verifiers_lock_); - for (verifier::MethodVerifier* verifier : method_verifiers_) { - verifier->VisitRoots(callback, arg); - } - } VisitTransactionRoots(callback, arg); instrumentation_.VisitRoots(callback, arg); } @@ -1508,26 +1502,6 @@ void Runtime::SetCompileTimeClassPath(jobject class_loader, compile_time_class_paths_.Put(class_loader, class_path); } -void Runtime::AddMethodVerifier(verifier::MethodVerifier* verifier) { - DCHECK(verifier != nullptr); - if (gAborting) { - return; - } - MutexLock mu(Thread::Current(), *Locks::method_verifiers_lock_); - method_verifiers_.insert(verifier); -} - -void Runtime::RemoveMethodVerifier(verifier::MethodVerifier* verifier) { - DCHECK(verifier != nullptr); - if (gAborting) { - return; - } - MutexLock mu(Thread::Current(), *Locks::method_verifiers_lock_); - auto it = method_verifiers_.find(verifier); - CHECK(it != method_verifiers_.end()); - method_verifiers_.erase(it); -} - void Runtime::StartProfiler(const char* profile_output_filename) { profile_output_filename_ = profile_output_filename; profiler_started_ = diff --git a/runtime/runtime.h b/runtime/runtime.h index d54972c7a6..3cf22bf269 100644 --- a/runtime/runtime.h +++ b/runtime/runtime.h @@ -456,11 +456,6 @@ class Runtime { return use_compile_time_class_path_; } - void AddMethodVerifier(verifier::MethodVerifier* verifier) - LOCKS_EXCLUDED(Locks::method_verifiers_lock_); - void RemoveMethodVerifier(verifier::MethodVerifier* verifier) - LOCKS_EXCLUDED(Locks::method_verifiers_lock_); - const std::vector<const DexFile*>& GetCompileTimeClassPath(jobject class_loader); // The caller is responsible for ensuring the class_path DexFiles remain @@ -642,9 +637,6 @@ class Runtime { Mutex fault_message_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER; std::string fault_message_ GUARDED_BY(fault_message_lock_); - // Method verifier set, used so that we can update their GC roots. - std::set<verifier::MethodVerifier*> method_verifiers_ GUARDED_BY(Locks::method_verifiers_lock_); - // A non-zero value indicates that a thread has been created but not yet initialized. Guarded by // the shutdown lock so that threads aren't born while we're shutting down. size_t threads_being_born_ GUARDED_BY(Locks::runtime_shutdown_lock_); diff --git a/runtime/thread.cc b/runtime/thread.cc index 8e98d530a9..affb6cd747 100644 --- a/runtime/thread.cc +++ b/runtime/thread.cc @@ -70,6 +70,7 @@ #include "thread-inl.h" #include "utils.h" #include "verifier/dex_gc_map.h" +#include "verifier/method_verifier.h" #include "verify_object-inl.h" #include "vmap_table.h" #include "well_known_classes.h" @@ -2296,6 +2297,9 @@ void Thread::VisitRoots(RootCallback* visitor, void* arg) { mapper.VisitShadowFrame(shadow_frame); } } + if (tlsPtr_.method_verifier != nullptr) { + tlsPtr_.method_verifier->VisitRoots(visitor, arg, RootInfo(kRootNativeStack, thread_id)); + } // Visit roots on this thread's stack Context* context = GetLongJumpContext(); RootCallbackVisitor visitor_to_callback(visitor, arg, thread_id); @@ -2417,4 +2421,14 @@ void Thread::ClearDebugInvokeReq() { tlsPtr_.debug_invoke_req = nullptr; } +void Thread::SetVerifier(verifier::MethodVerifier* verifier) { + CHECK(tlsPtr_.method_verifier == nullptr); + tlsPtr_.method_verifier = verifier; +} + +void Thread::ClearVerifier(verifier::MethodVerifier* verifier) { + CHECK_EQ(tlsPtr_.method_verifier, verifier); + tlsPtr_.method_verifier = nullptr; +} + } // namespace art diff --git a/runtime/thread.h b/runtime/thread.h index 2e9ae3c42d..da7af83e0b 100644 --- a/runtime/thread.h +++ b/runtime/thread.h @@ -62,6 +62,11 @@ namespace mirror { class StackTraceElement; class Throwable; } // namespace mirror + +namespace verifier { +class MethodVerifier; +} // namespace verifier + class BaseMutex; class ClassLinker; class Closure; @@ -875,6 +880,9 @@ class Thread { return tls32_.suspended_at_suspend_check; } + void SetVerifier(verifier::MethodVerifier* verifier); + void ClearVerifier(verifier::MethodVerifier* verifier); + private: explicit Thread(bool daemon); ~Thread() LOCKS_EXCLUDED(Locks::mutator_lock_, @@ -1055,10 +1063,8 @@ class Thread { pthread_self(0), last_no_thread_suspension_cause(nullptr), thread_local_start(nullptr), thread_local_pos(nullptr), thread_local_end(nullptr), thread_local_objects(0), thread_local_alloc_stack_top(nullptr), thread_local_alloc_stack_end(nullptr), - nested_signal_state(nullptr), flip_function(nullptr) { - for (size_t i = 0; i < kLockLevelCount; ++i) { - held_mutexes[i] = nullptr; - } + nested_signal_state(nullptr), flip_function(nullptr), method_verifier(nullptr) { + std::fill(held_mutexes, held_mutexes + kLockLevelCount, nullptr); } // The biased card table, see CardTable for details. @@ -1172,6 +1178,9 @@ class Thread { // The function used for thread flip. Closure* flip_function; + + // Current method verifier, used for root marking. + verifier::MethodVerifier* method_verifier; } tlsPtr_; // Guards the 'interrupted_' and 'wait_monitor_' members. diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc index b3f686d5c1..9ceb6f4748 100644 --- a/runtime/verifier/method_verifier.cc +++ b/runtime/verifier/method_verifier.cc @@ -395,12 +395,12 @@ MethodVerifier::MethodVerifier(Thread* self, has_virtual_or_interface_invokes_(false), verify_to_dump_(verify_to_dump), allow_thread_suspension_(allow_thread_suspension) { - Runtime::Current()->AddMethodVerifier(this); + self->SetVerifier(this); DCHECK(class_def != nullptr); } MethodVerifier::~MethodVerifier() { - Runtime::Current()->RemoveMethodVerifier(this); + Thread::Current()->ClearVerifier(this); STLDeleteElements(&failure_messages_); } @@ -4334,8 +4334,8 @@ void MethodVerifier::VisitStaticRoots(RootCallback* callback, void* arg) { RegTypeCache::VisitStaticRoots(callback, arg); } -void MethodVerifier::VisitRoots(RootCallback* callback, void* arg) { - reg_types_.VisitRoots(callback, arg); +void MethodVerifier::VisitRoots(RootCallback* callback, void* arg, const RootInfo& root_info) { + reg_types_.VisitRoots(callback, arg, root_info); } } // namespace verifier diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h index d7c2071cbc..6b813efa0a 100644 --- a/runtime/verifier/method_verifier.h +++ b/runtime/verifier/method_verifier.h @@ -227,7 +227,8 @@ class MethodVerifier { static void VisitStaticRoots(RootCallback* callback, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void VisitRoots(RootCallback* callback, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void VisitRoots(RootCallback* callback, void* arg, const RootInfo& roots) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Accessors used by the compiler via CompilerCallback const DexFile::CodeItem* CodeItem() const; diff --git a/runtime/verifier/reg_type.cc b/runtime/verifier/reg_type.cc index 3510665193..201169f794 100644 --- a/runtime/verifier/reg_type.cc +++ b/runtime/verifier/reg_type.cc @@ -778,8 +778,8 @@ void RegType::CheckInvariants() const { } } -void RegType::VisitRoots(RootCallback* callback, void* arg) const { - klass_.VisitRootIfNonNull(callback, arg, RootInfo(kRootUnknown)); +void RegType::VisitRoots(RootCallback* callback, void* arg, const RootInfo& root_info) const { + klass_.VisitRootIfNonNull(callback, arg, root_info); } void UninitializedThisReferenceType::CheckInvariants() const { diff --git a/runtime/verifier/reg_type.h b/runtime/verifier/reg_type.h index 05958b52b5..73e131eff5 100644 --- a/runtime/verifier/reg_type.h +++ b/runtime/verifier/reg_type.h @@ -250,7 +250,7 @@ class RegType { virtual ~RegType() {} - void VisitRoots(RootCallback* callback, void* arg) const + void VisitRoots(RootCallback* callback, void* arg, const RootInfo& root_info) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); protected: diff --git a/runtime/verifier/reg_type_cache.cc b/runtime/verifier/reg_type_cache.cc index 22696c7e8d..6e578573ba 100644 --- a/runtime/verifier/reg_type_cache.cc +++ b/runtime/verifier/reg_type_cache.cc @@ -238,9 +238,7 @@ const RegType& RegTypeCache::FromClass(const char* descriptor, mirror::Class* kl } } -RegTypeCache::RegTypeCache(bool can_load_classes) - : entries_lock_("entries lock"), - can_load_classes_(can_load_classes) { +RegTypeCache::RegTypeCache(bool can_load_classes) : can_load_classes_(can_load_classes) { if (kIsDebugBuild) { Thread::Current()->AssertThreadSuspensionIsAllowable(gAborting == 0); } @@ -563,35 +561,33 @@ void RegTypeCache::VisitStaticRoots(RootCallback* callback, void* arg) { // Visit the primitive types, this is required since if there are no active verifiers they wont // be in the entries array, and therefore not visited as roots. if (primitive_initialized_) { - UndefinedType::GetInstance()->VisitRoots(callback, arg); - ConflictType::GetInstance()->VisitRoots(callback, arg); - BooleanType::GetInstance()->VisitRoots(callback, arg); - ByteType::GetInstance()->VisitRoots(callback, arg); - ShortType::GetInstance()->VisitRoots(callback, arg); - CharType::GetInstance()->VisitRoots(callback, arg); - IntegerType::GetInstance()->VisitRoots(callback, arg); - LongLoType::GetInstance()->VisitRoots(callback, arg); - LongHiType::GetInstance()->VisitRoots(callback, arg); - FloatType::GetInstance()->VisitRoots(callback, arg); - DoubleLoType::GetInstance()->VisitRoots(callback, arg); - DoubleHiType::GetInstance()->VisitRoots(callback, arg); + RootInfo ri(kRootUnknown); + UndefinedType::GetInstance()->VisitRoots(callback, arg, ri); + ConflictType::GetInstance()->VisitRoots(callback, arg, ri); + BooleanType::GetInstance()->VisitRoots(callback, arg, ri); + ByteType::GetInstance()->VisitRoots(callback, arg, ri); + ShortType::GetInstance()->VisitRoots(callback, arg, ri); + CharType::GetInstance()->VisitRoots(callback, arg, ri); + IntegerType::GetInstance()->VisitRoots(callback, arg, ri); + LongLoType::GetInstance()->VisitRoots(callback, arg, ri); + LongHiType::GetInstance()->VisitRoots(callback, arg, ri); + FloatType::GetInstance()->VisitRoots(callback, arg, ri); + DoubleLoType::GetInstance()->VisitRoots(callback, arg, ri); + DoubleHiType::GetInstance()->VisitRoots(callback, arg, ri); for (int32_t value = kMinSmallConstant; value <= kMaxSmallConstant; ++value) { - small_precise_constants_[value - kMinSmallConstant]->VisitRoots(callback, arg); + small_precise_constants_[value - kMinSmallConstant]->VisitRoots(callback, arg, ri); } } } -void RegTypeCache::VisitRoots(RootCallback* callback, void* arg) { - MutexLock mu(Thread::Current(), entries_lock_); +void RegTypeCache::VisitRoots(RootCallback* callback, void* arg, const RootInfo& root_info) { // Exclude the static roots that are visited by VisitStaticRoots(). for (size_t i = primitive_count_; i < entries_.size(); ++i) { - entries_[i]->VisitRoots(callback, arg); + entries_[i]->VisitRoots(callback, arg, root_info); } } void RegTypeCache::AddEntry(RegType* new_entry) { - // TODO: There is probably a faster way to do this by using thread local roots. - MutexLock mu(Thread::Current(), entries_lock_); entries_.push_back(new_entry); } diff --git a/runtime/verifier/reg_type_cache.h b/runtime/verifier/reg_type_cache.h index 4b56fd69ca..01032a032c 100644 --- a/runtime/verifier/reg_type_cache.h +++ b/runtime/verifier/reg_type_cache.h @@ -137,7 +137,8 @@ class RegTypeCache { void Dump(std::ostream& os) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); const RegType& RegTypeFromPrimitiveType(Primitive::Type) const; - void VisitRoots(RootCallback* callback, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void VisitRoots(RootCallback* callback, void* arg, const RootInfo& root_info) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static void VisitStaticRoots(RootCallback* callback, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -171,9 +172,6 @@ class RegTypeCache { // Number of well known primitives that will be copied into a RegTypeCache upon construction. static uint16_t primitive_count_; - // Guards adding and visitng roots to prevent race conditions. - Mutex entries_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER; - // The actual storage for the RegTypes. std::vector<const RegType*> entries_; |