summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicolas Geoffray <ngeoffray@google.com>2015-03-05 10:40:17 +0000
committerNicolas Geoffray <ngeoffray@google.com>2015-03-09 10:09:33 +0000
commit14691c5e786e8c2c5734f687e4c96217340771be (patch)
tree7c2156671b323c70ffdd1d48d5e2f1d1de79c5fc
parent3d7d2af4c6502b771b032ee9bf3ab30e78f9c60d (diff)
downloadart-14691c5e786e8c2c5734f687e4c96217340771be.zip
art-14691c5e786e8c2c5734f687e4c96217340771be.tar.gz
art-14691c5e786e8c2c5734f687e4c96217340771be.tar.bz2
Compute the right catch location for the debugger.
Also remove tls ThrowLocation, it is not needed anymore. Change-Id: I78fddf09ce968ca475e39c17fa76d699c589c8d9
-rw-r--r--compiler/driver/compiler_driver.cc8
-rw-r--r--compiler/oat_writer.cc2
-rw-r--r--runtime/arch/stub_test.cc4
-rw-r--r--runtime/check_jni.cc9
-rw-r--r--runtime/class_linker.cc18
-rw-r--r--runtime/class_linker_test.cc2
-rw-r--r--runtime/debugger.cc127
-rw-r--r--runtime/debugger.h3
-rw-r--r--runtime/entrypoints/entrypoint_utils-inl.h7
-rw-r--r--runtime/entrypoints/entrypoint_utils.cc5
-rw-r--r--runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc2
-rw-r--r--runtime/entrypoints/quick/quick_throw_entrypoints.cc4
-rw-r--r--runtime/entrypoints_order_test.cc3
-rw-r--r--runtime/instrumentation.cc11
-rw-r--r--runtime/instrumentation.h8
-rw-r--r--runtime/interpreter/interpreter_common.cc84
-rw-r--r--runtime/interpreter/interpreter_goto_table_impl.cc4
-rw-r--r--runtime/interpreter/interpreter_switch_impl.cc4
-rw-r--r--runtime/jit/jit_instrumentation.h3
-rw-r--r--runtime/jni_internal.cc42
-rw-r--r--runtime/mirror/art_method.cc7
-rw-r--r--runtime/mirror/class.cc12
-rw-r--r--runtime/mirror/object_test.cc18
-rw-r--r--runtime/monitor.cc2
-rw-r--r--runtime/oat.h2
-rw-r--r--runtime/quick_exception_handler.cc10
-rw-r--r--runtime/quick_exception_handler.h3
-rw-r--r--runtime/reflection.cc2
-rw-r--r--runtime/runtime.cc11
-rw-r--r--runtime/thread.cc66
-rw-r--r--runtime/thread.h15
-rw-r--r--runtime/trace.cc6
-rw-r--r--runtime/trace.h4
33 files changed, 220 insertions, 288 deletions
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 029fd46..98abc18 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -1610,7 +1610,7 @@ static bool SkipClass(jobject class_loader, const DexFile& dex_file, mirror::Cla
static void CheckAndClearResolveException(Thread* self)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
CHECK(self->IsExceptionPending());
- mirror::Throwable* exception = self->GetException(nullptr);
+ mirror::Throwable* exception = self->GetException();
std::string temp;
const char* descriptor = exception->GetClass()->GetDescriptor(&temp);
const char* expected_exceptions[] = {
@@ -1755,7 +1755,7 @@ static void ResolveType(const ParallelCompilationManager* manager, size_t type_i
if (klass == nullptr) {
CHECK(soa.Self()->IsExceptionPending());
- mirror::Throwable* exception = soa.Self()->GetException(nullptr);
+ mirror::Throwable* exception = soa.Self()->GetException();
VLOG(compiler) << "Exception during type resolution: " << exception->Dump();
if (exception->GetClass()->DescriptorEquals("Ljava/lang/OutOfMemoryError;")) {
// There's little point continuing compilation if the heap is exhausted.
@@ -1970,7 +1970,7 @@ static void InitializeClass(const ParallelCompilationManager* manager, size_t cl
if (!success) {
CHECK(soa.Self()->IsExceptionPending());
- mirror::Throwable* exception = soa.Self()->GetException(nullptr);
+ mirror::Throwable* exception = soa.Self()->GetException();
VLOG(compiler) << "Initialization of " << descriptor << " aborted because of "
<< exception->Dump();
std::ostream* file_log = manager->GetCompiler()->
@@ -2233,7 +2233,7 @@ void CompilerDriver::CompileMethod(Thread* self, const DexFile::CodeItem* code_i
if (self->IsExceptionPending()) {
ScopedObjectAccess soa(self);
LOG(FATAL) << "Unexpected exception compiling: " << PrettyMethod(method_idx, dex_file) << "\n"
- << self->GetException(nullptr)->Dump();
+ << self->GetException()->Dump();
}
}
diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc
index c32a992..b3bb438 100644
--- a/compiler/oat_writer.cc
+++ b/compiler/oat_writer.cc
@@ -930,7 +930,7 @@ class OatWriter::InitImageMethodVisitor : public OatDexMethodVisitor {
LOG(ERROR) << "Unexpected failure to resolve a method: "
<< PrettyMethod(it.GetMemberIndex(), *dex_file_, true);
soa.Self()->AssertPendingException();
- mirror::Throwable* exc = soa.Self()->GetException(nullptr);
+ mirror::Throwable* exc = soa.Self()->GetException();
std::string dump = exc->Dump();
LOG(FATAL) << dump;
}
diff --git a/runtime/arch/stub_test.cc b/runtime/arch/stub_test.cc
index 0d41a8f..0769687 100644
--- a/runtime/arch/stub_test.cc
+++ b/runtime/arch/stub_test.cc
@@ -1171,7 +1171,7 @@ TEST_F(StubTest, AllocObjectArray) {
reinterpret_cast<size_t>(nullptr),
StubTest::GetEntrypoint(self, kQuickAllocArrayResolved),
self);
- EXPECT_FALSE(self->IsExceptionPending()) << PrettyTypeOf(self->GetException(nullptr));
+ EXPECT_FALSE(self->IsExceptionPending()) << PrettyTypeOf(self->GetException());
EXPECT_NE(reinterpret_cast<size_t>(nullptr), result);
mirror::Object* obj = reinterpret_cast<mirror::Object*>(result);
EXPECT_TRUE(obj->IsArrayInstance());
@@ -2060,7 +2060,7 @@ TEST_F(StubTest, IMT) {
env->CallBooleanMethod(jarray_list, add_jmethod, jobj);
- ASSERT_FALSE(self->IsExceptionPending()) << PrettyTypeOf(self->GetException(nullptr));
+ ASSERT_FALSE(self->IsExceptionPending()) << PrettyTypeOf(self->GetException());
// Contains.
diff --git a/runtime/check_jni.cc b/runtime/check_jni.cc
index 7db1d72..2b0167d 100644
--- a/runtime/check_jni.cc
+++ b/runtime/check_jni.cc
@@ -1065,11 +1065,10 @@ class ScopedCheck {
// Verify that, if an exception has been raised, the native code doesn't
// make any JNI calls other than the Exception* methods.
if ((flags_ & kFlag_ExcepOkay) == 0 && self->IsExceptionPending()) {
- ThrowLocation throw_location;
- mirror::Throwable* exception = self->GetException(&throw_location);
- std::string type(PrettyTypeOf(exception));
- AbortF("JNI %s called with pending exception '%s' thrown in %s",
- function_name_, type.c_str(), throw_location.Dump().c_str());
+ mirror::Throwable* exception = self->GetException();
+ AbortF("JNI %s called with pending exception %s",
+ function_name_,
+ exception->Dump().c_str());
return false;
}
return true;
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 2989b8c..f0c8819 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -103,7 +103,7 @@ static void ThrowEarlierClassFailure(mirror::Class* c)
if (runtime->IsAotCompiler()) {
// At compile time, accurate errors and NCDFE are disabled to speed compilation.
mirror::Throwable* pre_allocated = runtime->GetPreAllocatedNoClassDefFoundError();
- self->SetException(ThrowLocation(), pre_allocated);
+ self->SetException(pre_allocated);
} else {
ThrowLocation throw_location = self->GetCurrentLocationForThrow();
if (c->GetVerifyErrorClass() != NULL) {
@@ -123,7 +123,7 @@ static void VlogClassInitializationFailure(Handle<mirror::Class> klass)
if (VLOG_IS_ON(class_linker)) {
std::string temp;
LOG(INFO) << "Failed to initialize class " << klass->GetDescriptor(&temp) << " from "
- << klass->GetLocation() << "\n" << Thread::Current()->GetException(nullptr)->Dump();
+ << klass->GetLocation() << "\n" << Thread::Current()->GetException()->Dump();
}
}
@@ -2195,7 +2195,7 @@ mirror::Class* ClassLinker::FindClass(Thread* self, const char* descriptor,
// expected and will be wrapped in a ClassNotFoundException. Use the pre-allocated error to
// trigger the chaining with a proper stack trace.
mirror::Throwable* pre_allocated = Runtime::Current()->GetPreAllocatedNoClassDefFoundError();
- self->SetException(ThrowLocation(), pre_allocated);
+ self->SetException(pre_allocated);
return nullptr;
}
} else if (Runtime::Current()->UseCompileTimeClassPath()) {
@@ -2227,7 +2227,7 @@ mirror::Class* ClassLinker::FindClass(Thread* self, const char* descriptor,
} else {
// Use the pre-allocated NCDFE at compile time to avoid wasting time constructing exceptions.
mirror::Throwable* pre_allocated = Runtime::Current()->GetPreAllocatedNoClassDefFoundError();
- self->SetException(ThrowLocation(), pre_allocated);
+ self->SetException(pre_allocated);
return nullptr;
}
} else {
@@ -3529,13 +3529,13 @@ void ClassLinker::VerifyClass(Thread* self, Handle<mirror::Class> klass) {
PrettyDescriptor(klass.Get()).c_str(),
PrettyDescriptor(super.Get()).c_str()));
LOG(WARNING) << error_msg << " in " << klass->GetDexCache()->GetLocation()->ToModifiedUtf8();
- Handle<mirror::Throwable> cause(hs.NewHandle(self->GetException(nullptr)));
+ Handle<mirror::Throwable> cause(hs.NewHandle(self->GetException()));
if (cause.Get() != nullptr) {
self->ClearException();
}
ThrowVerifyError(klass.Get(), "%s", error_msg.c_str());
if (cause.Get() != nullptr) {
- self->GetException(nullptr)->SetCause(cause.Get());
+ self->GetException()->SetCause(cause.Get());
}
ClassReference ref(klass->GetDexCache()->GetDexFile(), klass->GetDexClassDefIndex());
if (Runtime::Current()->IsAotCompiler()) {
@@ -4168,7 +4168,7 @@ bool ClassLinker::InitializeClass(Thread* self, Handle<mirror::Class> klass,
<< PrettyDescriptor(handle_scope_super.Get())
<< " that has unexpected status " << handle_scope_super->GetStatus()
<< "\nPending exception:\n"
- << (self->GetException(nullptr) != nullptr ? self->GetException(nullptr)->Dump() : "");
+ << (self->GetException() != nullptr ? self->GetException()->Dump() : "");
ObjectLock<mirror::Class> lock(self, klass);
// Initialization failed because the super-class is erroneous.
klass->SetStatus(mirror::Class::kStatusError, self);
@@ -5671,12 +5671,12 @@ mirror::Class* ClassLinker::ResolveType(const DexFile& dex_file, uint16_t type_i
<< "Expected pending exception for failed resolution of: " << descriptor;
// Convert a ClassNotFoundException to a NoClassDefFoundError.
StackHandleScope<1> hs(self);
- Handle<mirror::Throwable> cause(hs.NewHandle(self->GetException(nullptr)));
+ Handle<mirror::Throwable> cause(hs.NewHandle(self->GetException()));
if (cause->InstanceOf(GetClassRoot(kJavaLangClassNotFoundException))) {
DCHECK(resolved == nullptr); // No Handle needed to preserve resolved.
self->ClearException();
ThrowNoClassDefFoundError("Failed resolution of: %s", descriptor);
- self->GetException(nullptr)->SetCause(cause.Get());
+ self->GetException()->SetCause(cause.Get());
}
}
}
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index 64e129c..1789ab1 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -48,7 +48,7 @@ class ClassLinkerTest : public CommonRuntimeTest {
Thread* self = Thread::Current();
EXPECT_TRUE(class_linker_->FindSystemClass(self, descriptor.c_str()) == nullptr);
EXPECT_TRUE(self->IsExceptionPending());
- mirror::Object* exception = self->GetException(nullptr);
+ mirror::Object* exception = self->GetException();
self->ClearException();
mirror::Class* exception_class =
class_linker_->FindSystemClass(self, "Ljava/lang/NoClassDefFoundError;");
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index 246125b..964e84c 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -280,11 +280,9 @@ class DebugInstrumentationListener FINAL : public instrumentation::Instrumentati
Dbg::PostFieldModificationEvent(method, dex_pc, this_object, field, &field_value);
}
- void ExceptionCaught(Thread* thread ATTRIBUTE_UNUSED, const ThrowLocation& throw_location,
- mirror::ArtMethod* catch_method, uint32_t catch_dex_pc,
- mirror::Throwable* exception_object)
+ void ExceptionCaught(Thread* thread ATTRIBUTE_UNUSED, mirror::Throwable* exception_object)
OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- Dbg::PostException(throw_location, catch_method, catch_dex_pc, exception_object);
+ Dbg::PostException(exception_object);
}
// We only care about how many backward branches were executed in the Jit.
@@ -2785,19 +2783,110 @@ void Dbg::PostFieldModificationEvent(mirror::ArtMethod* m, int dex_pc,
gJdwpState->PostFieldEvent(&location, f, this_object, field_value, true);
}
-void Dbg::PostException(const ThrowLocation& throw_location,
- mirror::ArtMethod* catch_method,
- uint32_t catch_dex_pc, mirror::Throwable* exception_object) {
+/**
+ * Finds the location where this exception will be caught. We search until we reach the top
+ * frame, in which case this exception is considered uncaught.
+ */
+class CatchLocationFinder : public StackVisitor {
+ public:
+ CatchLocationFinder(Thread* self, const Handle<mirror::Throwable>& exception, Context* context)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ : StackVisitor(self, context),
+ self_(self),
+ exception_(exception),
+ handle_scope_(self),
+ this_at_throw_(handle_scope_.NewHandle<mirror::Object>(nullptr)),
+ catch_method_(handle_scope_.NewHandle<mirror::ArtMethod>(nullptr)),
+ throw_method_(handle_scope_.NewHandle<mirror::ArtMethod>(nullptr)),
+ catch_dex_pc_(DexFile::kDexNoIndex),
+ throw_dex_pc_(DexFile::kDexNoIndex) {
+ }
+
+ bool VisitFrame() OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ mirror::ArtMethod* method = GetMethod();
+ DCHECK(method != nullptr);
+ if (method->IsRuntimeMethod()) {
+ // Ignore callee save method.
+ DCHECK(method->IsCalleeSaveMethod());
+ return true;
+ }
+
+ uint32_t dex_pc = GetDexPc();
+ if (throw_method_.Get() == nullptr) {
+ // First Java method found. It is either the method that threw the exception,
+ // or the Java native method that is reporting an exception thrown by
+ // native code.
+ this_at_throw_.Assign(GetThisObject());
+ throw_method_.Assign(method);
+ throw_dex_pc_ = dex_pc;
+ }
+
+ if (dex_pc != DexFile::kDexNoIndex) {
+ StackHandleScope<2> hs(self_);
+ uint32_t found_dex_pc;
+ Handle<mirror::Class> exception_class(hs.NewHandle(exception_->GetClass()));
+ Handle<mirror::ArtMethod> h_method(hs.NewHandle(method));
+ bool unused_clear_exception;
+ found_dex_pc = mirror::ArtMethod::FindCatchBlock(
+ h_method, exception_class, dex_pc, &unused_clear_exception);
+ if (found_dex_pc != DexFile::kDexNoIndex) {
+ catch_method_.Assign(method);
+ catch_dex_pc_ = found_dex_pc;
+ return false; // End stack walk.
+ }
+ }
+ return true; // Continue stack walk.
+ }
+
+ mirror::ArtMethod* GetCatchMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return catch_method_.Get();
+ }
+
+ mirror::ArtMethod* GetThrowMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return throw_method_.Get();
+ }
+
+ mirror::Object* GetThisAtThrow() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return this_at_throw_.Get();
+ }
+
+ uint32_t GetCatchDexPc() const {
+ return catch_dex_pc_;
+ }
+
+ uint32_t GetThrowDexPc() const {
+ return throw_dex_pc_;
+ }
+
+ private:
+ Thread* const self_;
+ const Handle<mirror::Throwable>& exception_;
+ StackHandleScope<3> handle_scope_;
+ MutableHandle<mirror::Object> this_at_throw_;
+ MutableHandle<mirror::ArtMethod> catch_method_;
+ MutableHandle<mirror::ArtMethod> throw_method_;
+ uint32_t catch_dex_pc_;
+ uint32_t throw_dex_pc_;
+
+ DISALLOW_COPY_AND_ASSIGN(CatchLocationFinder);
+};
+
+void Dbg::PostException(mirror::Throwable* exception_object) {
if (!IsDebuggerActive()) {
return;
}
+ StackHandleScope<1> handle_scope(Thread::Current());
+ Handle<mirror::Throwable> h_exception(handle_scope.NewHandle(exception_object));
+ std::unique_ptr<Context> context(Context::Create());
+ CatchLocationFinder clf(Thread::Current(), h_exception, context.get());
+ clf.WalkStack(/* include_transitions */ false);
JDWP::EventLocation exception_throw_location;
- SetEventLocation(&exception_throw_location, throw_location.GetMethod(), throw_location.GetDexPc());
+ SetEventLocation(&exception_throw_location, clf.GetThrowMethod(), clf.GetThrowDexPc());
JDWP::EventLocation exception_catch_location;
- SetEventLocation(&exception_catch_location, catch_method, catch_dex_pc);
+ SetEventLocation(&exception_catch_location, clf.GetCatchMethod(), clf.GetCatchDexPc());
- gJdwpState->PostException(&exception_throw_location, exception_object, &exception_catch_location,
- throw_location.GetThis());
+ gJdwpState->PostException(&exception_throw_location, h_exception.Get(), &exception_catch_location,
+ clf.GetThisAtThrow());
}
void Dbg::PostClassPrepare(mirror::Class* c) {
@@ -3704,18 +3793,12 @@ void Dbg::ExecuteMethod(DebugInvokeReq* pReq) {
// We can be called while an exception is pending. We need
// to preserve that across the method invocation.
- StackHandleScope<4> hs(soa.Self());
- auto old_throw_this_object = hs.NewHandle<mirror::Object>(nullptr);
- auto old_throw_method = hs.NewHandle<mirror::ArtMethod>(nullptr);
+ StackHandleScope<2> hs(soa.Self());
auto old_exception = hs.NewHandle<mirror::Throwable>(nullptr);
- uint32_t old_throw_dex_pc;
{
ThrowLocation old_throw_location;
- mirror::Throwable* old_exception_obj = soa.Self()->GetException(&old_throw_location);
- old_throw_this_object.Assign(old_throw_location.GetThis());
- old_throw_method.Assign(old_throw_location.GetMethod());
+ mirror::Throwable* old_exception_obj = soa.Self()->GetException();
old_exception.Assign(old_exception_obj);
- old_throw_dex_pc = old_throw_location.GetDexPc();
soa.Self()->ClearException();
}
@@ -3738,7 +3821,7 @@ void Dbg::ExecuteMethod(DebugInvokeReq* pReq) {
pReq->result_value = InvokeWithJValues(soa, pReq->receiver, soa.EncodeMethod(m.Get()),
reinterpret_cast<jvalue*>(pReq->arg_values));
- mirror::Throwable* exception = soa.Self()->GetException(nullptr);
+ mirror::Throwable* exception = soa.Self()->GetException();
soa.Self()->ClearException();
pReq->exception = gRegistry->Add(exception);
pReq->result_tag = BasicTagFromDescriptor(m.Get()->GetShorty());
@@ -3767,9 +3850,7 @@ void Dbg::ExecuteMethod(DebugInvokeReq* pReq) {
}
if (old_exception.Get() != nullptr) {
- ThrowLocation gc_safe_throw_location(old_throw_this_object.Get(), old_throw_method.Get(),
- old_throw_dex_pc);
- soa.Self()->SetException(gc_safe_throw_location, old_exception.Get());
+ soa.Self()->SetException(old_exception.Get());
}
}
diff --git a/runtime/debugger.h b/runtime/debugger.h
index 0c22148..428ded7 100644
--- a/runtime/debugger.h
+++ b/runtime/debugger.h
@@ -529,8 +529,7 @@ class Dbg {
mirror::Object* this_object, mirror::ArtField* f,
const JValue* field_value)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- static void PostException(const ThrowLocation& throw_location, mirror::ArtMethod* catch_method,
- uint32_t catch_dex_pc, mirror::Throwable* exception)
+ static void PostException(mirror::Throwable* exception)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static void PostThreadStart(Thread* t)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h
index 9d84e4a..149c6b4 100644
--- a/runtime/entrypoints/entrypoint_utils-inl.h
+++ b/runtime/entrypoints/entrypoint_utils-inl.h
@@ -613,9 +613,8 @@ inline mirror::String* ResolveStringFromCode(mirror::ArtMethod* referrer,
inline void UnlockJniSynchronizedMethod(jobject locked, Thread* self) {
// Save any pending exception over monitor exit call.
mirror::Throwable* saved_exception = NULL;
- ThrowLocation saved_throw_location;
if (UNLIKELY(self->IsExceptionPending())) {
- saved_exception = self->GetException(&saved_throw_location);
+ saved_exception = self->GetException();
self->ClearException();
}
// Decode locked object and unlock, before popping local references.
@@ -624,11 +623,11 @@ inline void UnlockJniSynchronizedMethod(jobject locked, Thread* self) {
LOG(FATAL) << "Synchronized JNI code returning with an exception:\n"
<< saved_exception->Dump()
<< "\nEncountered second exception during implicit MonitorExit:\n"
- << self->GetException(NULL)->Dump();
+ << self->GetException()->Dump();
}
// Restore pending exception.
if (saved_exception != NULL) {
- self->SetException(saved_throw_location, saved_exception);
+ self->SetException(saved_exception);
}
}
diff --git a/runtime/entrypoints/entrypoint_utils.cc b/runtime/entrypoints/entrypoint_utils.cc
index 5ea9f70..af528b7 100644
--- a/runtime/entrypoints/entrypoint_utils.cc
+++ b/runtime/entrypoints/entrypoint_utils.cc
@@ -187,8 +187,7 @@ void ThrowStackOverflowError(Thread* self) {
error_msg = "Could not create stack trace.";
}
// Throw the exception.
- self->SetException(self->GetCurrentLocationForThrow(),
- reinterpret_cast<mirror::Throwable*>(self->DecodeJObject(exc.get())));
+ self->SetException(reinterpret_cast<mirror::Throwable*>(self->DecodeJObject(exc.get())));
} else {
// Could not allocate a string object.
error_msg = "Couldn't throw new StackOverflowError because JNI NewStringUTF failed.";
@@ -302,7 +301,7 @@ JValue InvokeProxyInvocationHandler(ScopedObjectAccessAlreadyRunnable& soa, cons
} else {
// In the case of checked exceptions that aren't declared, the exception must be wrapped by
// a UndeclaredThrowableException.
- mirror::Throwable* exception = soa.Self()->GetException(NULL);
+ mirror::Throwable* exception = soa.Self()->GetException();
if (exception->IsCheckedException()) {
mirror::Object* rcvr = soa.Decode<mirror::Object*>(rcvr_jobj);
mirror::Class* proxy_class = rcvr->GetClass();
diff --git a/runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc b/runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc
index 14ab320..d88d262 100644
--- a/runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc
@@ -29,7 +29,7 @@ namespace art {
extern "C" void artDeoptimize(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
ScopedQuickEntrypointChecks sqec(self);
- self->SetException(ThrowLocation(), Thread::GetDeoptimizationException());
+ self->SetException(Thread::GetDeoptimizationException());
self->QuickDeliverException();
}
diff --git a/runtime/entrypoints/quick/quick_throw_entrypoints.cc b/runtime/entrypoints/quick/quick_throw_entrypoints.cc
index 25df40b..127f9e0 100644
--- a/runtime/entrypoints/quick/quick_throw_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_throw_entrypoints.cc
@@ -41,12 +41,12 @@ extern "C" void artDeliverExceptionFromCode(mirror::Throwable* exception, Thread
* exception_ in thread and delivering the exception.
*/
ScopedQuickEntrypointChecks sqec(self);
- ThrowLocation throw_location = self->GetCurrentLocationForThrow();
if (exception == nullptr) {
+ ThrowLocation throw_location = self->GetCurrentLocationForThrow();
self->ThrowNewException(throw_location, "Ljava/lang/NullPointerException;",
"throw with null exception");
} else {
- self->SetException(throw_location, exception);
+ self->SetException(exception);
}
self->QuickDeliverException();
}
diff --git a/runtime/entrypoints_order_test.cc b/runtime/entrypoints_order_test.cc
index 9173357..0fdfcb3 100644
--- a/runtime/entrypoints_order_test.cc
+++ b/runtime/entrypoints_order_test.cc
@@ -93,8 +93,7 @@ class EntrypointsOrderTest : public CommonRuntimeTest {
EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, opeer, jpeer, sizeof(void*));
EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, jpeer, stack_begin, sizeof(void*));
EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, stack_begin, stack_size, sizeof(void*));
- EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, stack_size, throw_location, sizeof(void*));
- EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, throw_location, stack_trace_sample, sizeof(ThrowLocation));
+ EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, stack_size, stack_trace_sample, sizeof(void*));
EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, stack_trace_sample, wait_next, sizeof(void*));
EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, wait_next, monitor_enter_object, sizeof(void*));
EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, monitor_enter_object, top_handle_scope, sizeof(void*));
diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc
index c94dab9..085062c 100644
--- a/runtime/instrumentation.cc
+++ b/runtime/instrumentation.cc
@@ -949,19 +949,16 @@ void Instrumentation::FieldWriteEventImpl(Thread* thread, mirror::Object* this_o
}
}
-void Instrumentation::ExceptionCaughtEvent(Thread* thread, const ThrowLocation& throw_location,
- mirror::ArtMethod* catch_method,
- uint32_t catch_dex_pc,
+void Instrumentation::ExceptionCaughtEvent(Thread* thread,
mirror::Throwable* exception_object) const {
if (HasExceptionCaughtListeners()) {
- DCHECK_EQ(thread->GetException(nullptr), exception_object);
+ DCHECK_EQ(thread->GetException(), exception_object);
thread->ClearException();
std::shared_ptr<std::list<InstrumentationListener*>> original(exception_caught_listeners_);
for (InstrumentationListener* listener : *original.get()) {
- listener->ExceptionCaught(thread, throw_location, catch_method, catch_dex_pc,
- exception_object);
+ listener->ExceptionCaught(thread, exception_object);
}
- thread->SetException(throw_location, exception_object);
+ thread->SetException(exception_object);
}
}
diff --git a/runtime/instrumentation.h b/runtime/instrumentation.h
index b667a40..e3f18f1 100644
--- a/runtime/instrumentation.h
+++ b/runtime/instrumentation.h
@@ -90,9 +90,7 @@ struct InstrumentationListener {
uint32_t dex_pc, mirror::ArtField* field, const JValue& field_value) = 0;
// Call-back when an exception is caught.
- virtual void ExceptionCaught(Thread* thread, const ThrowLocation& throw_location,
- mirror::ArtMethod* catch_method, uint32_t catch_dex_pc,
- mirror::Throwable* exception_object)
+ virtual void ExceptionCaught(Thread* thread, mirror::Throwable* exception_object)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;
// Call-back for when we get a backward branch.
@@ -322,9 +320,7 @@ class Instrumentation {
}
// Inform listeners that an exception was caught.
- void ExceptionCaughtEvent(Thread* thread, const ThrowLocation& throw_location,
- mirror::ArtMethod* catch_method, uint32_t catch_dex_pc,
- mirror::Throwable* exception_object) const
+ void ExceptionCaughtEvent(Thread* thread, mirror::Throwable* exception_object) const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Called when an instrumented method is entered. The intended link register (lr) is saved so
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc
index 754602f..3f09bd3 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -413,90 +413,16 @@ EXPLICIT_DO_IPUT_QUICK_ALL_TEMPLATE_DECL(Primitive::kPrimNot) // iput-objec
#undef EXPLICIT_DO_IPUT_QUICK_ALL_TEMPLATE_DECL
#undef EXPLICIT_DO_IPUT_QUICK_TEMPLATE_DECL
-/**
- * Finds the location where this exception will be caught. We search until we reach either the top
- * frame or a native frame, in which cases this exception is considered uncaught.
- */
-class CatchLocationFinder : public StackVisitor {
- public:
- explicit CatchLocationFinder(Thread* self, Handle<mirror::Throwable>* exception)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
- : StackVisitor(self, nullptr), self_(self), handle_scope_(self), exception_(exception),
- catch_method_(handle_scope_.NewHandle<mirror::ArtMethod>(nullptr)),
- catch_dex_pc_(DexFile::kDexNoIndex), clear_exception_(false) {
- }
-
- bool VisitFrame() OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- mirror::ArtMethod* method = GetMethod();
- if (method == nullptr) {
- return true;
- }
- if (method->IsRuntimeMethod()) {
- // Ignore callee save method.
- DCHECK(method->IsCalleeSaveMethod());
- return true;
- }
- if (method->IsNative()) {
- return false; // End stack walk.
- }
- DCHECK(!method->IsNative());
- uint32_t dex_pc = GetDexPc();
- if (dex_pc != DexFile::kDexNoIndex) {
- uint32_t found_dex_pc;
- {
- StackHandleScope<3> hs(self_);
- Handle<mirror::Class> exception_class(hs.NewHandle((*exception_)->GetClass()));
- Handle<mirror::ArtMethod> h_method(hs.NewHandle(method));
- found_dex_pc = mirror::ArtMethod::FindCatchBlock(h_method, exception_class, dex_pc,
- &clear_exception_);
- }
- if (found_dex_pc != DexFile::kDexNoIndex) {
- catch_method_.Assign(method);
- catch_dex_pc_ = found_dex_pc;
- return false; // End stack walk.
- }
- }
- return true; // Continue stack walk.
- }
-
- ArtMethod* GetCatchMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return catch_method_.Get();
- }
-
- uint32_t GetCatchDexPc() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return catch_dex_pc_;
- }
-
- bool NeedClearException() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return clear_exception_;
- }
-
- private:
- Thread* const self_;
- StackHandleScope<1> handle_scope_;
- Handle<mirror::Throwable>* exception_;
- MutableHandle<mirror::ArtMethod> catch_method_;
- uint32_t catch_dex_pc_;
- bool clear_exception_;
-
-
- DISALLOW_COPY_AND_ASSIGN(CatchLocationFinder);
-};
-
uint32_t FindNextInstructionFollowingException(Thread* self,
ShadowFrame& shadow_frame,
uint32_t dex_pc,
const instrumentation::Instrumentation* instrumentation) {
self->VerifyStack();
- ThrowLocation throw_location;
StackHandleScope<3> hs(self);
- Handle<mirror::Throwable> exception(hs.NewHandle(self->GetException(&throw_location)));
+ Handle<mirror::Throwable> exception(hs.NewHandle(self->GetException()));
if (instrumentation->HasExceptionCaughtListeners()
&& self->IsExceptionThrownByCurrentMethod(exception.Get())) {
- CatchLocationFinder clf(self, &exception);
- clf.WalkStack(false);
- instrumentation->ExceptionCaughtEvent(self, throw_location, clf.GetCatchMethod(),
- clf.GetCatchDexPc(), exception.Get());
+ instrumentation->ExceptionCaughtEvent(self, exception.Get());
}
bool clear_exception = false;
uint32_t found_dex_pc;
@@ -848,7 +774,7 @@ static void CheckExceptionGenerateClassNotFound(Thread* self)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
if (self->IsExceptionPending()) {
// If it is not an InternalError, wrap it.
- std::string type(PrettyTypeOf(self->GetException(nullptr)));
+ std::string type(PrettyTypeOf(self->GetException()));
if (type != "java.lang.InternalError") {
self->ThrowNewWrappedException(self->GetCurrentLocationForThrow(),
"Ljava/lang/ClassNotFoundException;",
@@ -903,7 +829,7 @@ static void UnstartedRuntimeInvoke(Thread* self, const DexFile::CodeItem* code_
// This might have an error pending. But semantics are to just return null.
if (self->IsExceptionPending()) {
// If it is an InternalError, keep it. See CheckExceptionGenerateClassNotFound.
- std::string type(PrettyTypeOf(self->GetException(nullptr)));
+ std::string type(PrettyTypeOf(self->GetException()));
if (type != "java.lang.InternalError") {
self->ClearException();
}
@@ -936,7 +862,7 @@ static void UnstartedRuntimeInvoke(Thread* self, const DexFile::CodeItem* code_
if (!ok) {
std::string error_msg = StringPrintf("Failed in Class.newInstance for '%s' with %s",
PrettyClass(h_klass.Get()).c_str(),
- PrettyTypeOf(self->GetException(nullptr)).c_str());
+ PrettyTypeOf(self->GetException()).c_str());
self->ThrowNewWrappedException(self->GetCurrentLocationForThrow(),
"Ljava/lang/InternalError;",
error_msg.c_str());
diff --git a/runtime/interpreter/interpreter_goto_table_impl.cc b/runtime/interpreter/interpreter_goto_table_impl.cc
index 37324ea..f1ab747 100644
--- a/runtime/interpreter/interpreter_goto_table_impl.cc
+++ b/runtime/interpreter/interpreter_goto_table_impl.cc
@@ -244,7 +244,7 @@ JValue ExecuteGotoImpl(Thread* self, const DexFile::CodeItem* code_item, ShadowF
HANDLE_INSTRUCTION_END();
HANDLE_INSTRUCTION_START(MOVE_EXCEPTION) {
- Throwable* exception = self->GetException(nullptr);
+ Throwable* exception = self->GetException();
DCHECK(exception != nullptr) << "No pending exception on MOVE_EXCEPTION instruction";
shadow_frame.SetVRegReference(inst->VRegA_11x(inst_data), exception);
self->ClearException();
@@ -605,7 +605,7 @@ JValue ExecuteGotoImpl(Thread* self, const DexFile::CodeItem* code_item, ShadowF
"Throwing '%s' that is not instance of Throwable",
exception->GetClass()->GetDescriptor(&temp));
} else {
- self->SetException(shadow_frame.GetCurrentLocationForThrow(), exception->AsThrowable());
+ self->SetException(exception->AsThrowable());
}
HANDLE_PENDING_EXCEPTION();
}
diff --git a/runtime/interpreter/interpreter_switch_impl.cc b/runtime/interpreter/interpreter_switch_impl.cc
index 2f85587..dceed47 100644
--- a/runtime/interpreter/interpreter_switch_impl.cc
+++ b/runtime/interpreter/interpreter_switch_impl.cc
@@ -163,7 +163,7 @@ JValue ExecuteSwitchImpl(Thread* self, const DexFile::CodeItem* code_item,
break;
case Instruction::MOVE_EXCEPTION: {
PREAMBLE();
- Throwable* exception = self->GetException(nullptr);
+ Throwable* exception = self->GetException();
DCHECK(exception != nullptr) << "No pending exception on MOVE_EXCEPTION instruction";
shadow_frame.SetVRegReference(inst->VRegA_11x(inst_data), exception);
self->ClearException();
@@ -515,7 +515,7 @@ JValue ExecuteSwitchImpl(Thread* self, const DexFile::CodeItem* code_item,
"Throwing '%s' that is not instance of Throwable",
exception->GetClass()->GetDescriptor(&temp));
} else {
- self->SetException(shadow_frame.GetCurrentLocationForThrow(), exception->AsThrowable());
+ self->SetException(exception->AsThrowable());
}
HANDLE_PENDING_EXCEPTION();
break;
diff --git a/runtime/jit/jit_instrumentation.h b/runtime/jit/jit_instrumentation.h
index 9576f4b..9d122e0 100644
--- a/runtime/jit/jit_instrumentation.h
+++ b/runtime/jit/jit_instrumentation.h
@@ -83,8 +83,7 @@ class JitInstrumentationListener : public instrumentation::InstrumentationListen
mirror::ArtMethod* /*method*/, uint32_t /*dex_pc*/,
mirror::ArtField* /*field*/, const JValue& /*field_value*/)
OVERRIDE { }
- virtual void ExceptionCaught(Thread* /*thread*/, const ThrowLocation& /*throw_location*/,
- mirror::ArtMethod* /*catch_method*/, uint32_t /*catch_dex_pc*/,
+ virtual void ExceptionCaught(Thread* /*thread*/,
mirror::Throwable* /*exception_object*/) OVERRIDE { }
virtual void DexPcMoved(Thread* /*self*/, mirror::Object* /*this_object*/,
diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc
index 561302e..213de6f 100644
--- a/runtime/jni_internal.cc
+++ b/runtime/jni_internal.cc
@@ -196,16 +196,16 @@ static jfieldID FindFieldID(const ScopedObjectAccess& soa, jclass jni_class, con
if (field_type == nullptr) {
// Failed to find type from the signature of the field.
DCHECK(soa.Self()->IsExceptionPending());
- ThrowLocation throw_location;
StackHandleScope<1> hs2(soa.Self());
- Handle<mirror::Throwable> cause(hs2.NewHandle(soa.Self()->GetException(&throw_location)));
+ Handle<mirror::Throwable> cause(hs2.NewHandle(soa.Self()->GetException()));
soa.Self()->ClearException();
std::string temp;
+ ThrowLocation throw_location = soa.Self()->GetCurrentLocationForThrow();
soa.Self()->ThrowNewExceptionF(throw_location, "Ljava/lang/NoSuchFieldError;",
"no type \"%s\" found and so no field \"%s\" "
"could be found in class \"%s\" or its superclasses", sig, name,
c->GetDescriptor(&temp));
- soa.Self()->GetException(nullptr)->SetCause(cause.Get());
+ soa.Self()->GetException()->SetCause(cause.Get());
return nullptr;
}
std::string temp;
@@ -282,8 +282,7 @@ int ThrowNewException(JNIEnv* env, jclass exception_class, const char* msg, jobj
return JNI_ERR;
}
ScopedObjectAccess soa(env);
- ThrowLocation throw_location = soa.Self()->GetCurrentLocationForThrow();
- soa.Self()->SetException(throw_location, soa.Decode<mirror::Throwable*>(exception.get()));
+ soa.Self()->SetException(soa.Decode<mirror::Throwable*>(exception.get()));
return JNI_OK;
}
@@ -433,8 +432,7 @@ class JNI {
if (exception == nullptr) {
return JNI_ERR;
}
- ThrowLocation throw_location = soa.Self()->GetCurrentLocationForThrow();
- soa.Self()->SetException(throw_location, exception);
+ soa.Self()->SetException(exception);
return JNI_OK;
}
@@ -456,25 +454,14 @@ class JNI {
ScopedObjectAccess soa(env);
// If we have no exception to describe, pass through.
- if (!soa.Self()->GetException(nullptr)) {
+ if (!soa.Self()->GetException()) {
return;
}
- StackHandleScope<3> hs(soa.Self());
- // TODO: Use nullptr instead of null handles?
- auto old_throw_this_object(hs.NewHandle<mirror::Object>(nullptr));
- auto old_throw_method(hs.NewHandle<mirror::ArtMethod>(nullptr));
- auto old_exception(hs.NewHandle<mirror::Throwable>(nullptr));
- uint32_t old_throw_dex_pc;
- {
- ThrowLocation old_throw_location;
- mirror::Throwable* old_exception_obj = soa.Self()->GetException(&old_throw_location);
- old_throw_this_object.Assign(old_throw_location.GetThis());
- old_throw_method.Assign(old_throw_location.GetMethod());
- old_exception.Assign(old_exception_obj);
- old_throw_dex_pc = old_throw_location.GetDexPc();
- soa.Self()->ClearException();
- }
+ StackHandleScope<1> hs(soa.Self());
+ Handle<mirror::Throwable> old_exception(
+ hs.NewHandle<mirror::Throwable>(soa.Self()->GetException()));
+ soa.Self()->ClearException();
ScopedLocalRef<jthrowable> exception(env,
soa.AddLocalReference<jthrowable>(old_exception.Get()));
ScopedLocalRef<jclass> exception_class(env, env->GetObjectClass(exception.get()));
@@ -485,20 +472,17 @@ class JNI {
} else {
env->CallVoidMethod(exception.get(), mid);
if (soa.Self()->IsExceptionPending()) {
- LOG(WARNING) << "JNI WARNING: " << PrettyTypeOf(soa.Self()->GetException(nullptr))
+ LOG(WARNING) << "JNI WARNING: " << PrettyTypeOf(soa.Self()->GetException())
<< " thrown while calling printStackTrace";
soa.Self()->ClearException();
}
}
- ThrowLocation gc_safe_throw_location(old_throw_this_object.Get(), old_throw_method.Get(),
- old_throw_dex_pc);
-
- soa.Self()->SetException(gc_safe_throw_location, old_exception.Get());
+ soa.Self()->SetException(old_exception.Get());
}
static jthrowable ExceptionOccurred(JNIEnv* env) {
ScopedObjectAccess soa(env);
- mirror::Object* exception = soa.Self()->GetException(nullptr);
+ mirror::Object* exception = soa.Self()->GetException();
return soa.AddLocalReference<jthrowable>(exception);
}
diff --git a/runtime/mirror/art_method.cc b/runtime/mirror/art_method.cc
index 85fc5f3..bc58709 100644
--- a/runtime/mirror/art_method.cc
+++ b/runtime/mirror/art_method.cc
@@ -271,9 +271,8 @@ uint32_t ArtMethod::FindCatchBlock(Handle<ArtMethod> h_this, Handle<Class> excep
const DexFile::CodeItem* code_item = h_this->GetCodeItem();
// Set aside the exception while we resolve its type.
Thread* self = Thread::Current();
- ThrowLocation throw_location;
StackHandleScope<1> hs(self);
- Handle<mirror::Throwable> exception(hs.NewHandle(self->GetException(&throw_location)));
+ Handle<mirror::Throwable> exception(hs.NewHandle(self->GetException()));
self->ClearException();
// Default to handler not found.
uint32_t found_dex_pc = DexFile::kDexNoIndex;
@@ -309,7 +308,7 @@ uint32_t ArtMethod::FindCatchBlock(Handle<ArtMethod> h_this, Handle<Class> excep
}
// Put the exception back.
if (exception.Get() != nullptr) {
- self->SetException(throw_location, exception.Get());
+ self->SetException(exception.Get());
}
return found_dex_pc;
}
@@ -434,7 +433,7 @@ void ArtMethod::Invoke(Thread* self, uint32_t* args, uint32_t args_size, JValue*
#else
(*art_quick_invoke_stub)(this, args, args_size, self, result, shorty);
#endif
- if (UNLIKELY(self->GetException(nullptr) == Thread::GetDeoptimizationException())) {
+ if (UNLIKELY(self->GetException() == Thread::GetDeoptimizationException())) {
// Unusual case where we were running generated code and an
// exception was thrown to force the activations to be removed from the
// stack. Continue execution in the interpreter.
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index 96b15dd..6f4ef60 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -77,13 +77,9 @@ void Class::SetStatus(Status new_status, Thread* self) {
<< "Attempt to set as erroneous an already erroneous class " << PrettyClass(this);
// Stash current exception.
- StackHandleScope<3> hs(self);
- ThrowLocation old_throw_location;
- Handle<mirror::Throwable> old_exception(hs.NewHandle(self->GetException(&old_throw_location)));
+ StackHandleScope<1> hs(self);
+ Handle<mirror::Throwable> old_exception(hs.NewHandle(self->GetException()));
CHECK(old_exception.Get() != nullptr);
- Handle<mirror::Object> old_throw_this_object(hs.NewHandle(old_throw_location.GetThis()));
- Handle<mirror::ArtMethod> old_throw_method(hs.NewHandle(old_throw_location.GetMethod()));
- uint32_t old_throw_dex_pc = old_throw_location.GetDexPc();
Class* eiie_class;
// Do't attempt to use FindClass if we have an OOM error since this can try to do more
// allocations and may cause infinite loops.
@@ -109,9 +105,7 @@ void Class::SetStatus(Status new_status, Thread* self) {
}
// Restore exception.
- ThrowLocation gc_safe_throw_location(old_throw_this_object.Get(), old_throw_method.Get(),
- old_throw_dex_pc);
- self->SetException(gc_safe_throw_location, old_exception.Get());
+ self->SetException(old_exception.Get());
}
static_assert(sizeof(Status) == sizeof(uint32_t), "Size of status not equal to uint32");
if (Runtime::Current()->IsActiveTransaction()) {
diff --git a/runtime/mirror/object_test.cc b/runtime/mirror/object_test.cc
index 9b345a6..21972a1 100644
--- a/runtime/mirror/object_test.cc
+++ b/runtime/mirror/object_test.cc
@@ -124,12 +124,12 @@ TEST_F(ObjectTest, AllocObjectArray) {
EXPECT_TRUE(oa->Get(-1) == NULL);
EXPECT_TRUE(soa.Self()->IsExceptionPending());
- EXPECT_EQ(aioobe, soa.Self()->GetException(NULL)->GetClass());
+ EXPECT_EQ(aioobe, soa.Self()->GetException()->GetClass());
soa.Self()->ClearException();
EXPECT_TRUE(oa->Get(2) == NULL);
EXPECT_TRUE(soa.Self()->IsExceptionPending());
- EXPECT_EQ(aioobe, soa.Self()->GetException(NULL)->GetClass());
+ EXPECT_EQ(aioobe, soa.Self()->GetException()->GetClass());
soa.Self()->ClearException();
ASSERT_TRUE(oa->GetClass() != NULL);
@@ -213,12 +213,12 @@ void TestPrimitiveArray(ClassLinker* cl) {
EXPECT_EQ(0, a->Get(-1));
EXPECT_TRUE(soa.Self()->IsExceptionPending());
- EXPECT_EQ(aioobe, soa.Self()->GetException(NULL)->GetClass());
+ EXPECT_EQ(aioobe, soa.Self()->GetException()->GetClass());
soa.Self()->ClearException();
EXPECT_EQ(0, a->Get(2));
EXPECT_TRUE(soa.Self()->IsExceptionPending());
- EXPECT_EQ(aioobe, soa.Self()->GetException(NULL)->GetClass());
+ EXPECT_EQ(aioobe, soa.Self()->GetException()->GetClass());
soa.Self()->ClearException();
}
@@ -262,12 +262,12 @@ TEST_F(ObjectTest, PrimitiveArray_Double_Alloc) {
EXPECT_DOUBLE_EQ(0, a->Get(-1));
EXPECT_TRUE(soa.Self()->IsExceptionPending());
- EXPECT_EQ(aioobe, soa.Self()->GetException(NULL)->GetClass());
+ EXPECT_EQ(aioobe, soa.Self()->GetException()->GetClass());
soa.Self()->ClearException();
EXPECT_DOUBLE_EQ(0, a->Get(2));
EXPECT_TRUE(soa.Self()->IsExceptionPending());
- EXPECT_EQ(aioobe, soa.Self()->GetException(NULL)->GetClass());
+ EXPECT_EQ(aioobe, soa.Self()->GetException()->GetClass());
soa.Self()->ClearException();
}
@@ -292,12 +292,12 @@ TEST_F(ObjectTest, PrimitiveArray_Float_Alloc) {
EXPECT_FLOAT_EQ(0, a->Get(-1));
EXPECT_TRUE(soa.Self()->IsExceptionPending());
- EXPECT_EQ(aioobe, soa.Self()->GetException(NULL)->GetClass());
+ EXPECT_EQ(aioobe, soa.Self()->GetException()->GetClass());
soa.Self()->ClearException();
EXPECT_FLOAT_EQ(0, a->Get(2));
EXPECT_TRUE(soa.Self()->IsExceptionPending());
- EXPECT_EQ(aioobe, soa.Self()->GetException(NULL)->GetClass());
+ EXPECT_EQ(aioobe, soa.Self()->GetException()->GetClass());
soa.Self()->ClearException();
}
@@ -335,7 +335,7 @@ TEST_F(ObjectTest, CreateMultiArray) {
dims->Set<false>(0, -1);
multi = Array::CreateMultiArray(soa.Self(), c, dims);
EXPECT_TRUE(soa.Self()->IsExceptionPending());
- EXPECT_EQ(PrettyDescriptor(soa.Self()->GetException(NULL)->GetClass()),
+ EXPECT_EQ(PrettyDescriptor(soa.Self()->GetException()->GetClass()),
"java.lang.NegativeArraySizeException");
soa.Self()->ClearException();
diff --git a/runtime/monitor.cc b/runtime/monitor.cc
index 45a971d..dce8bac 100644
--- a/runtime/monitor.cc
+++ b/runtime/monitor.cc
@@ -306,7 +306,7 @@ static void ThrowIllegalMonitorStateExceptionF(const char* fmt, ...)
std::ostringstream ss;
self->Dump(ss);
LOG(Runtime::Current()->IsStarted() ? INFO : ERROR)
- << self->GetException(NULL)->Dump() << "\n" << ss.str();
+ << self->GetException()->Dump() << "\n" << ss.str();
}
va_end(args);
}
diff --git a/runtime/oat.h b/runtime/oat.h
index f973b28..5540ade 100644
--- a/runtime/oat.h
+++ b/runtime/oat.h
@@ -32,7 +32,7 @@ class InstructionSetFeatures;
class PACKED(4) OatHeader {
public:
static constexpr uint8_t kOatMagic[] = { 'o', 'a', 't', '\n' };
- static constexpr uint8_t kOatVersion[] = { '0', '5', '6', '\0' };
+ static constexpr uint8_t kOatVersion[] = { '0', '5', '7', '\0' };
static constexpr const char* kImageLocationKey = "image-location";
static constexpr const char* kDex2OatCmdLineKey = "dex2oat-cmdline";
diff --git a/runtime/quick_exception_handler.cc b/runtime/quick_exception_handler.cc
index 1ddb761..0eb8eca 100644
--- a/runtime/quick_exception_handler.cc
+++ b/runtime/quick_exception_handler.cc
@@ -114,8 +114,7 @@ class CatchBlockStackVisitor FINAL : public StackVisitor {
DISALLOW_COPY_AND_ASSIGN(CatchBlockStackVisitor);
};
-void QuickExceptionHandler::FindCatch(const ThrowLocation& throw_location,
- mirror::Throwable* exception) {
+void QuickExceptionHandler::FindCatch(mirror::Throwable* exception) {
DCHECK(!is_deoptimization_);
if (kDebugExceptionDelivery) {
mirror::String* msg = exception->GetDetailMessage();
@@ -145,15 +144,14 @@ void QuickExceptionHandler::FindCatch(const ThrowLocation& throw_location,
DCHECK(!self_->IsExceptionPending());
} else {
// Put exception back in root set with clear throw location.
- self_->SetException(ThrowLocation(), exception_ref.Get());
+ self_->SetException(exception_ref.Get());
}
// The debugger may suspend this thread and walk its stack. Let's do this before popping
// instrumentation frames.
instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
if (instrumentation->HasExceptionCaughtListeners()
&& self_->IsExceptionThrownByCurrentMethod(exception)) {
- instrumentation->ExceptionCaughtEvent(self_, throw_location, handler_method_, handler_dex_pc_,
- exception_ref.Get());
+ instrumentation->ExceptionCaughtEvent(self_, exception_ref.Get());
}
}
@@ -283,7 +281,7 @@ void QuickExceptionHandler::DeoptimizeStack() {
visitor.WalkStack(true);
// Restore deoptimization exception
- self_->SetException(ThrowLocation(), Thread::GetDeoptimizationException());
+ self_->SetException(Thread::GetDeoptimizationException());
}
// Unwinds all instrumentation stack frame prior to catch handler or upcall.
diff --git a/runtime/quick_exception_handler.h b/runtime/quick_exception_handler.h
index a0e6a79..08619fa 100644
--- a/runtime/quick_exception_handler.h
+++ b/runtime/quick_exception_handler.h
@@ -44,8 +44,7 @@ class QuickExceptionHandler {
UNREACHABLE();
}
- void FindCatch(const ThrowLocation& throw_location, mirror::Throwable* exception)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void FindCatch(mirror::Throwable* exception) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void DeoptimizeStack() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void UpdateInstrumentationStack() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
NO_RETURN void DoLongJump() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/runtime/reflection.cc b/runtime/reflection.cc
index 2aeb92d..4acd07f 100644
--- a/runtime/reflection.cc
+++ b/runtime/reflection.cc
@@ -366,7 +366,7 @@ static void CheckMethodArguments(JavaVMExt* vm, mirror::ArtMethod* m, uint32_t*
CHECK(self->IsExceptionPending());
LOG(ERROR) << "Internal error: unresolvable type for argument type in JNI invoke: "
<< h_m->GetTypeDescriptorFromTypeIdx(type_idx) << "\n"
- << self->GetException(nullptr)->Dump();
+ << self->GetException()->Dump();
self->ClearException();
++error_count;
} else if (!param_type->IsPrimitive()) {
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 383308c..2043672 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -306,11 +306,8 @@ struct AbortState {
DCHECK(Locks::mutator_lock_->IsExclusiveHeld(self) || Locks::mutator_lock_->IsSharedHeld(self));
self->Dump(os);
if (self->IsExceptionPending()) {
- ThrowLocation throw_location;
- mirror::Throwable* exception = self->GetException(&throw_location);
- os << "Pending exception " << PrettyTypeOf(exception)
- << " thrown by '" << throw_location.Dump() << "'\n"
- << exception->Dump();
+ mirror::Throwable* exception = self->GetException();
+ os << "Pending exception " << exception->Dump();
}
}
@@ -1020,14 +1017,14 @@ bool Runtime::Init(const RuntimeOptions& raw_options, bool ignore_unrecognized)
self->ThrowNewException(ThrowLocation(), "Ljava/lang/OutOfMemoryError;",
"OutOfMemoryError thrown while trying to throw OutOfMemoryError; "
"no stack trace available");
- pre_allocated_OutOfMemoryError_ = GcRoot<mirror::Throwable>(self->GetException(NULL));
+ pre_allocated_OutOfMemoryError_ = GcRoot<mirror::Throwable>(self->GetException());
self->ClearException();
// Pre-allocate a NoClassDefFoundError for the common case of failing to find a system class
// ahead of checking the application's class loader.
self->ThrowNewException(ThrowLocation(), "Ljava/lang/NoClassDefFoundError;",
"Class not found using the boot class loader; no stack trace available");
- pre_allocated_NoClassDefFoundError_ = GcRoot<mirror::Throwable>(self->GetException(NULL));
+ pre_allocated_NoClassDefFoundError_ = GcRoot<mirror::Throwable>(self->GetException());
self->ClearException();
// Look for a native bridge.
diff --git a/runtime/thread.cc b/runtime/thread.cc
index fdb1f9d..e31af16 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());
}
}
@@ -1188,7 +1178,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 +1186,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();
}
@@ -1740,25 +1730,24 @@ void Thread::ThrowNewException(const ThrowLocation& throw_location,
ThrowNewWrappedException(throw_location, exception_class_descriptor, msg);
}
+static mirror::ClassLoader* GetClassLoaderFromThrowLocation(const ThrowLocation& throw_location)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return throw_location.GetMethod() != nullptr
+ ? throw_location.GetMethod()->GetDeclaringClass()->GetClassLoader()
+ : nullptr;
+}
+
void Thread::ThrowNewWrappedException(const ThrowLocation& throw_location,
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(GetClassLoaderFromThrowLocation(throw_location)));
+ 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 +1768,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 +1818,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 +1833,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 +1841,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(GetCurrentLocationForThrow(), "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 +2012,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 +2022,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();
@@ -2302,7 +2283,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));
}
diff --git a/runtime/thread.h b/runtime/thread.h
index e4c91b7..af02dc7 100644
--- a/runtime/thread.h
+++ b/runtime/thread.h
@@ -326,11 +326,7 @@ class Thread {
return tlsPtr_.exception != nullptr;
}
- mirror::Throwable* GetException(ThrowLocation* throw_location) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- if (throw_location != nullptr) {
- *throw_location = tlsPtr_.throw_location;
- }
+ mirror::Throwable* GetException() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return tlsPtr_.exception;
}
@@ -338,17 +334,15 @@ class Thread {
void AssertNoPendingException() const;
void AssertNoPendingExceptionForNewException(const char* msg) const;
- void SetException(const ThrowLocation& throw_location, mirror::Throwable* new_exception)
+ void SetException(mirror::Throwable* new_exception)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
CHECK(new_exception != NULL);
// TODO: DCHECK(!IsExceptionPending());
tlsPtr_.exception = new_exception;
- tlsPtr_.throw_location = throw_location;
}
void ClearException() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
tlsPtr_.exception = nullptr;
- tlsPtr_.throw_location.Clear();
}
// Find catch block and perform long jump to appropriate exception handle
@@ -1034,7 +1028,7 @@ class Thread {
struct PACKED(4) tls_ptr_sized_values {
tls_ptr_sized_values() : card_table(nullptr), exception(nullptr), stack_end(nullptr),
managed_stack(), suspend_trigger(nullptr), jni_env(nullptr), self(nullptr), opeer(nullptr),
- jpeer(nullptr), stack_begin(nullptr), stack_size(0), throw_location(),
+ jpeer(nullptr), stack_begin(nullptr), stack_size(0),
stack_trace_sample(nullptr), wait_next(nullptr), monitor_enter_object(nullptr),
top_handle_scope(nullptr), class_loader_override(nullptr), long_jump_context(nullptr),
instrumentation_stack(nullptr), debug_invoke_req(nullptr), single_step_control(nullptr),
@@ -1084,9 +1078,6 @@ class Thread {
// Size of the stack.
size_t stack_size;
- // The location the current exception was thrown from.
- ThrowLocation throw_location;
-
// Pointer to previous stack trace captured by sampling profiler.
std::vector<mirror::ArtMethod*>* stack_trace_sample;
diff --git a/runtime/trace.cc b/runtime/trace.cc
index 93b3877..a1296f4 100644
--- a/runtime/trace.cc
+++ b/runtime/trace.cc
@@ -619,11 +619,9 @@ void Trace::MethodUnwind(Thread* thread, mirror::Object* this_object ATTRIBUTE_U
thread_clock_diff, wall_clock_diff);
}
-void Trace::ExceptionCaught(Thread* thread, const ThrowLocation& throw_location,
- mirror::ArtMethod* catch_method, uint32_t catch_dex_pc,
- mirror::Throwable* exception_object)
+void Trace::ExceptionCaught(Thread* thread, mirror::Throwable* exception_object)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- UNUSED(thread, throw_location, catch_method, catch_dex_pc, exception_object);
+ UNUSED(thread, exception_object);
LOG(ERROR) << "Unexpected exception caught event in tracing";
}
diff --git a/runtime/trace.h b/runtime/trace.h
index 9ba30d5..dd8186a 100644
--- a/runtime/trace.h
+++ b/runtime/trace.h
@@ -95,9 +95,7 @@ class Trace FINAL : public instrumentation::InstrumentationListener {
mirror::ArtMethod* method, uint32_t dex_pc, mirror::ArtField* field,
const JValue& field_value)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) OVERRIDE;
- void ExceptionCaught(Thread* thread, const ThrowLocation& throw_location,
- mirror::ArtMethod* catch_method, uint32_t catch_dex_pc,
- mirror::Throwable* exception_object)
+ void ExceptionCaught(Thread* thread, mirror::Throwable* exception_object)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) OVERRIDE;
void BackwardBranch(Thread* thread, mirror::ArtMethod* method, int32_t dex_pc_offset)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) OVERRIDE;