summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--runtime/base/mutex.cc5
-rw-r--r--runtime/base/mutex.h4
-rw-r--r--runtime/entrypoints_order_test.cc3
-rw-r--r--runtime/runtime.cc26
-rw-r--r--runtime/runtime.h8
-rw-r--r--runtime/thread.cc14
-rw-r--r--runtime/thread.h17
-rw-r--r--runtime/verifier/method_verifier.cc8
-rw-r--r--runtime/verifier/method_verifier.h3
-rw-r--r--runtime/verifier/reg_type.cc4
-rw-r--r--runtime/verifier/reg_type.h2
-rw-r--r--runtime/verifier/reg_type_cache.cc38
-rw-r--r--runtime/verifier/reg_type_cache.h6
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_;