diff options
Diffstat (limited to 'runtime/thread.cc')
-rw-r--r-- | runtime/thread.cc | 113 |
1 files changed, 47 insertions, 66 deletions
diff --git a/runtime/thread.cc b/runtime/thread.cc index fdb1f9dd4c..e8e93555ac 100644 --- a/runtime/thread.cc +++ b/runtime/thread.cc @@ -1033,18 +1033,11 @@ void Thread::DumpJavaStack(std::ostream& os) const { // assumption that there is no exception pending on entry. Thus, stash any pending exception. // Thread::Current() instead of this in case a thread is dumping the stack of another suspended // thread. - StackHandleScope<3> scope(Thread::Current()); + StackHandleScope<1> scope(Thread::Current()); Handle<mirror::Throwable> exc; - Handle<mirror::Object> throw_location_this_object; - Handle<mirror::ArtMethod> throw_location_method; - uint32_t throw_location_dex_pc; bool have_exception = false; if (IsExceptionPending()) { - ThrowLocation exc_location; - exc = scope.NewHandle(GetException(&exc_location)); - throw_location_this_object = scope.NewHandle(exc_location.GetThis()); - throw_location_method = scope.NewHandle(exc_location.GetMethod()); - throw_location_dex_pc = exc_location.GetDexPc(); + exc = scope.NewHandle(GetException()); const_cast<Thread*>(this)->ClearException(); have_exception = true; } @@ -1055,10 +1048,7 @@ void Thread::DumpJavaStack(std::ostream& os) const { dumper.WalkStack(); if (have_exception) { - ThrowLocation exc_location(throw_location_this_object.Get(), - throw_location_method.Get(), - throw_location_dex_pc); - const_cast<Thread*>(this)->SetException(exc_location, exc.Get()); + const_cast<Thread*>(this)->SetException(exc.Get()); } } @@ -1148,8 +1138,6 @@ void Thread::Shutdown() { Thread::Thread(bool daemon) : tls32_(daemon), wait_monitor_(nullptr), interrupted_(false) { wait_mutex_ = new Mutex("a thread wait mutex"); wait_cond_ = new ConditionVariable("a thread wait condition variable", *wait_mutex_); - tlsPtr_.debug_invoke_req = new DebugInvokeReq; - tlsPtr_.single_step_control = nullptr; tlsPtr_.instrumentation_stack = new std::deque<instrumentation::InstrumentationStackFrame>; tlsPtr_.name = new std::string(kThreadNameDuringStartup); tlsPtr_.nested_signal_state = static_cast<jmp_buf*>(malloc(sizeof(jmp_buf))); @@ -1188,7 +1176,7 @@ void Thread::AssertPendingException() const { void Thread::AssertNoPendingException() const { if (UNLIKELY(IsExceptionPending())) { ScopedObjectAccess soa(Thread::Current()); - mirror::Throwable* exception = GetException(nullptr); + mirror::Throwable* exception = GetException(); LOG(FATAL) << "No pending exception expected: " << exception->Dump(); } } @@ -1196,7 +1184,7 @@ void Thread::AssertNoPendingException() const { void Thread::AssertNoPendingExceptionForNewException(const char* msg) const { if (UNLIKELY(IsExceptionPending())) { ScopedObjectAccess soa(Thread::Current()); - mirror::Throwable* exception = GetException(nullptr); + mirror::Throwable* exception = GetException(); LOG(FATAL) << "Throwing new exception '" << msg << "' with unexpected pending exception: " << exception->Dump(); } @@ -1301,7 +1289,6 @@ Thread::~Thread() { CleanupCpu(); } - delete tlsPtr_.debug_invoke_req; if (tlsPtr_.single_step_control != nullptr) { delete tlsPtr_.single_step_control; } @@ -1715,50 +1702,44 @@ jobjectArray Thread::InternalStackTraceToStackTraceElementArray( return result; } -void Thread::ThrowNewExceptionF(const ThrowLocation& throw_location, - const char* exception_class_descriptor, const char* fmt, ...) { +void Thread::ThrowNewExceptionF(const char* exception_class_descriptor, const char* fmt, ...) { va_list args; va_start(args, fmt); - ThrowNewExceptionV(throw_location, exception_class_descriptor, - fmt, args); + ThrowNewExceptionV(exception_class_descriptor, fmt, args); va_end(args); } -void Thread::ThrowNewExceptionV(const ThrowLocation& throw_location, - const char* exception_class_descriptor, +void Thread::ThrowNewExceptionV(const char* exception_class_descriptor, const char* fmt, va_list ap) { std::string msg; StringAppendV(&msg, fmt, ap); - ThrowNewException(throw_location, exception_class_descriptor, msg.c_str()); + ThrowNewException(exception_class_descriptor, msg.c_str()); } -void Thread::ThrowNewException(const ThrowLocation& throw_location, - const char* exception_class_descriptor, +void Thread::ThrowNewException(const char* exception_class_descriptor, const char* msg) { // Callers should either clear or call ThrowNewWrappedException. AssertNoPendingExceptionForNewException(msg); - ThrowNewWrappedException(throw_location, exception_class_descriptor, msg); + ThrowNewWrappedException(exception_class_descriptor, msg); } -void Thread::ThrowNewWrappedException(const ThrowLocation& throw_location, - const char* exception_class_descriptor, +static mirror::ClassLoader* GetCurrentClassLoader(Thread* self) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + mirror::ArtMethod* method = self->GetCurrentMethod(nullptr); + return method != nullptr + ? method->GetDeclaringClass()->GetClassLoader() + : nullptr; +} + +void Thread::ThrowNewWrappedException(const char* exception_class_descriptor, const char* msg) { DCHECK_EQ(this, Thread::Current()); ScopedObjectAccessUnchecked soa(this); - StackHandleScope<5> hs(soa.Self()); - // Ensure we don't forget arguments over object allocation. - Handle<mirror::Object> saved_throw_this(hs.NewHandle(throw_location.GetThis())); - Handle<mirror::ArtMethod> saved_throw_method(hs.NewHandle(throw_location.GetMethod())); - // Ignore the cause throw location. TODO: should we report this as a re-throw? - ScopedLocalRef<jobject> cause(GetJniEnv(), soa.AddLocalReference<jobject>(GetException(nullptr))); + StackHandleScope<3> hs(soa.Self()); + Handle<mirror::ClassLoader> class_loader(hs.NewHandle(GetCurrentClassLoader(soa.Self()))); + ScopedLocalRef<jobject> cause(GetJniEnv(), soa.AddLocalReference<jobject>(GetException())); ClearException(); Runtime* runtime = Runtime::Current(); - - mirror::ClassLoader* cl = nullptr; - if (saved_throw_method.Get() != nullptr) { - cl = saved_throw_method.Get()->GetDeclaringClass()->GetClassLoader(); - } - Handle<mirror::ClassLoader> class_loader(hs.NewHandle(cl)); Handle<mirror::Class> exception_class( hs.NewHandle(runtime->GetClassLinker()->FindClass(this, exception_class_descriptor, class_loader))); @@ -1779,9 +1760,7 @@ void Thread::ThrowNewWrappedException(const ThrowLocation& throw_location, // If we couldn't allocate the exception, throw the pre-allocated out of memory exception. if (exception.Get() == nullptr) { - ThrowLocation gc_safe_throw_location(saved_throw_this.Get(), saved_throw_method.Get(), - throw_location.GetDexPc()); - SetException(gc_safe_throw_location, Runtime::Current()->GetPreAllocatedOutOfMemoryError()); + SetException(Runtime::Current()->GetPreAllocatedOutOfMemoryError()); return; } @@ -1831,9 +1810,7 @@ void Thread::ThrowNewWrappedException(const ThrowLocation& throw_location, if (trace.get() != nullptr) { exception->SetStackState(down_cast<mirror::Throwable*>(DecodeJObject(trace.get()))); } - ThrowLocation gc_safe_throw_location(saved_throw_this.Get(), saved_throw_method.Get(), - throw_location.GetDexPc()); - SetException(gc_safe_throw_location, exception.Get()); + SetException(exception.Get()); } else { jvalue jv_args[2]; size_t i = 0; @@ -1848,9 +1825,7 @@ void Thread::ThrowNewWrappedException(const ThrowLocation& throw_location, } InvokeWithJValues(soa, exception.Get(), soa.EncodeMethod(exception_init_method), jv_args); if (LIKELY(!IsExceptionPending())) { - ThrowLocation gc_safe_throw_location(saved_throw_this.Get(), saved_throw_method.Get(), - throw_location.GetDexPc()); - SetException(gc_safe_throw_location, exception.Get()); + SetException(exception.Get()); } } } @@ -1858,14 +1833,13 @@ void Thread::ThrowNewWrappedException(const ThrowLocation& throw_location, void Thread::ThrowOutOfMemoryError(const char* msg) { LOG(WARNING) << StringPrintf("Throwing OutOfMemoryError \"%s\"%s", msg, (tls32_.throwing_OutOfMemoryError ? " (recursive case)" : "")); - ThrowLocation throw_location = GetCurrentLocationForThrow(); if (!tls32_.throwing_OutOfMemoryError) { tls32_.throwing_OutOfMemoryError = true; - ThrowNewException(throw_location, "Ljava/lang/OutOfMemoryError;", msg); + ThrowNewException("Ljava/lang/OutOfMemoryError;", msg); tls32_.throwing_OutOfMemoryError = false; } else { Dump(LOG(WARNING)); // The pre-allocated OOME has no stack, so help out and log one. - SetException(throw_location, Runtime::Current()->GetPreAllocatedOutOfMemoryError()); + SetException(Runtime::Current()->GetPreAllocatedOutOfMemoryError()); } } @@ -2030,8 +2004,7 @@ void Thread::DumpThreadOffset(std::ostream& os, uint32_t offset) { void Thread::QuickDeliverException() { // Get exception from thread. - ThrowLocation throw_location; - mirror::Throwable* exception = GetException(&throw_location); + mirror::Throwable* exception = GetException(); CHECK(exception != nullptr); // Don't leave exception visible while we try to find the handler, which may cause class // resolution. @@ -2041,7 +2014,7 @@ void Thread::QuickDeliverException() { if (is_deoptimization) { exception_handler.DeoptimizeStack(); } else { - exception_handler.FindCatch(throw_location, exception); + exception_handler.FindCatch(exception); } exception_handler.UpdateInstrumentationStack(); exception_handler.DoLongJump(); @@ -2093,14 +2066,6 @@ mirror::ArtMethod* Thread::GetCurrentMethod(uint32_t* dex_pc, bool abort_on_erro return visitor.method_; } -ThrowLocation Thread::GetCurrentLocationForThrow() { - Context* context = GetLongJumpContext(); - CurrentMethodVisitor visitor(this, context, true); - visitor.WalkStack(false); - ReleaseLongJumpContext(context); - return ThrowLocation(visitor.this_object_, visitor.method_, visitor.dex_pc_); -} - bool Thread::HoldsLock(mirror::Object* object) const { if (object == nullptr) { return false; @@ -2302,7 +2267,6 @@ void Thread::VisitRoots(RootCallback* visitor, void* arg) { visitor(reinterpret_cast<mirror::Object**>(&tlsPtr_.exception), arg, RootInfo(kRootNativeStack, thread_id)); } - tlsPtr_.throw_location.VisitRoots(visitor, arg); if (tlsPtr_.monitor_enter_object != nullptr) { visitor(&tlsPtr_.monitor_enter_object, arg, RootInfo(kRootNativeStack, thread_id)); } @@ -2436,4 +2400,21 @@ void Thread::DeactivateSingleStepControl() { delete ssc; } +void Thread::SetDebugInvokeReq(DebugInvokeReq* req) { + CHECK(Dbg::IsDebuggerActive()); + CHECK(GetInvokeReq() == nullptr) << "Debug invoke req already active in thread " << *this; + CHECK(Thread::Current() != this) << "Debug invoke can't be dispatched by the thread itself"; + CHECK(req != nullptr); + tlsPtr_.debug_invoke_req = req; +} + +void Thread::ClearDebugInvokeReq() { + CHECK(Dbg::IsDebuggerActive()); + CHECK(GetInvokeReq() != nullptr) << "Debug invoke req not active in thread " << *this; + CHECK(Thread::Current() == this) << "Debug invoke must be finished by the thread itself"; + // We do not own the DebugInvokeReq* so we must not delete it, it is the responsibility of + // the owner (the JDWP thread). + tlsPtr_.debug_invoke_req = nullptr; +} + } // namespace art |