summaryrefslogtreecommitdiffstats
path: root/runtime/thread.cc
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/thread.cc')
-rw-r--r--runtime/thread.cc113
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