summaryrefslogtreecommitdiffstats
path: root/runtime/thread_list.cc
diff options
context:
space:
mode:
authorIan Rogers <irogers@google.com>2014-09-10 14:44:24 -0700
committerIan Rogers <irogers@google.com>2014-09-12 14:57:53 -0700
commit7b078e8c04f3e1451dbdd18543c8b9692b5b067e (patch)
tree414229c6b87eb20ea24c40780752da5a3999a49a /runtime/thread_list.cc
parentf79ba17defbd9342e44ab9f3de0807054673d3c9 (diff)
downloadart-7b078e8c04f3e1451dbdd18543c8b9692b5b067e.tar.gz
art-7b078e8c04f3e1451dbdd18543c8b9692b5b067e.tar.bz2
art-7b078e8c04f3e1451dbdd18543c8b9692b5b067e.zip
Compile time performance improvements focusing on interpret-only.
Reduce virtual method dispatch in the method verifier and make more code inline-able. Add a StringPiece with const char* equality operator to avoid redundant StringPieces and strlens. Remove back link from register line to verifier and pass as argument to reduce size of RegisterLine. Remove instruction length from instruction flags and compute from the instruction, again to reduce size. Add suspend checks to resolve and verify to allow for more easy monitor inflation and reduce contention on Locks::thread_list_suspend_thread_lock_. Change ThrowEarlierClassFailure to throw pre-allocated exception. Avoid calls to Thread::Current() by passing self. Template specialize IsValidClassName. Make ANR reporting with SIGQUIT run using checkpoints rather than suspending all threads. This makes the stack/lock analysis less lock error prone. Extra Barrier assertions and condition variable time out is now returned as a boolean both from Barrier and ConditionVariable::Wait. 2 threaded host x86-64 interpret-only numbers from 341 samples: Before change: Avg 176.137ms 99% CI 3.468ms to 1060.770ms After change: Avg 139.163% 99% CI 3.027ms to 838.257ms Reduction in average compile time after change is 20.9%. Slow-down without change is 26.5%. Bug: 17471626 - Fix bug where RegTypeCache::JavaLangObject/String/Class/Throwable could return unresolved type when class loading is disabled. Bug: 17398101 Change-Id: Id59ce3cc520701c6ecf612f7152498107bc40684
Diffstat (limited to 'runtime/thread_list.cc')
-rw-r--r--runtime/thread_list.cc67
1 files changed, 50 insertions, 17 deletions
diff --git a/runtime/thread_list.cc b/runtime/thread_list.cc
index afb98cab45..3cc2a2892d 100644
--- a/runtime/thread_list.cc
+++ b/runtime/thread_list.cc
@@ -88,10 +88,7 @@ void ThreadList::DumpNativeStacks(std::ostream& os) {
}
void ThreadList::DumpForSigQuit(std::ostream& os) {
- {
- MutexLock mu(Thread::Current(), *Locks::thread_list_lock_);
- DumpLocked(os);
- }
+ Dump(os);
DumpUnattachedThreads(os);
}
@@ -133,12 +130,50 @@ void ThreadList::DumpUnattachedThreads(std::ostream& os) {
closedir(d);
}
-void ThreadList::DumpLocked(std::ostream& os) {
- os << "DALVIK THREADS (" << list_.size() << "):\n";
- for (const auto& thread : list_) {
- thread->Dump(os);
- os << "\n";
+// A closure used by Thread::Dump.
+class DumpCheckpoint FINAL : public Closure {
+ public:
+ explicit DumpCheckpoint(std::ostream* os) : os_(os), barrier_(0) {}
+
+ void Run(Thread* thread) OVERRIDE {
+ // Note thread and self may not be equal if thread was already suspended at the point of the
+ // request.
+ Thread* self = Thread::Current();
+ std::ostringstream local_os;
+ {
+ ScopedObjectAccess soa(self);
+ thread->Dump(local_os);
+ }
+ local_os << "\n";
+ {
+ // Use the logging lock to ensure serialization when writing to the common ostream.
+ MutexLock mu(self, *Locks::logging_lock_);
+ *os_ << local_os.str();
+ }
+ barrier_.Pass(self);
+ }
+
+ void WaitForThreadsToRunThroughCheckpoint(size_t threads_running_checkpoint) {
+ Thread* self = Thread::Current();
+ ScopedThreadStateChange tsc(self, kWaitingForCheckPointsToRun);
+ barrier_.Increment(self, threads_running_checkpoint);
+ }
+
+ private:
+ // The common stream that will accumulate all the dumps.
+ std::ostream* const os_;
+ // The barrier to be passed through and for the requestor to wait upon.
+ Barrier barrier_;
+};
+
+void ThreadList::Dump(std::ostream& os) {
+ {
+ MutexLock mu(Thread::Current(), *Locks::thread_list_lock_);
+ os << "DALVIK THREADS (" << list_.size() << "):\n";
}
+ DumpCheckpoint checkpoint(&os);
+ size_t threads_running_checkpoint = RunCheckpoint(&checkpoint);
+ checkpoint.WaitForThreadsToRunThroughCheckpoint(threads_running_checkpoint);
}
void ThreadList::AssertThreadsAreSuspended(Thread* self, Thread* ignore1, Thread* ignore2) {
@@ -155,12 +190,12 @@ void ThreadList::AssertThreadsAreSuspended(Thread* self, Thread* ignore1, Thread
#if HAVE_TIMED_RWLOCK
// Attempt to rectify locks so that we dump thread list with required locks before exiting.
-static void UnsafeLogFatalForThreadSuspendAllTimeout() NO_THREAD_SAFETY_ANALYSIS __attribute__((noreturn));
+static void UnsafeLogFatalForThreadSuspendAllTimeout() __attribute__((noreturn));
static void UnsafeLogFatalForThreadSuspendAllTimeout() {
Runtime* runtime = Runtime::Current();
std::ostringstream ss;
ss << "Thread suspend timeout\n";
- runtime->GetThreadList()->DumpLocked(ss);
+ runtime->GetThreadList()->Dump(ss);
LOG(FATAL) << ss.str();
exit(0);
}
@@ -266,12 +301,10 @@ size_t ThreadList::RunCheckpoint(Closure* checkpoint_function) {
// threads. Returns the number of successful requests.
size_t ThreadList::RunCheckpointOnRunnableThreads(Closure* checkpoint_function) {
Thread* self = Thread::Current();
- if (kIsDebugBuild) {
- Locks::mutator_lock_->AssertNotExclusiveHeld(self);
- Locks::thread_list_lock_->AssertNotHeld(self);
- Locks::thread_suspend_count_lock_->AssertNotHeld(self);
- CHECK_NE(self->GetState(), kRunnable);
- }
+ Locks::mutator_lock_->AssertNotExclusiveHeld(self);
+ Locks::thread_list_lock_->AssertNotHeld(self);
+ Locks::thread_suspend_count_lock_->AssertNotHeld(self);
+ CHECK_NE(self->GetState(), kRunnable);
size_t count = 0;
{