From 14691c5e786e8c2c5734f687e4c96217340771be Mon Sep 17 00:00:00 2001 From: Nicolas Geoffray Date: Thu, 5 Mar 2015 10:40:17 +0000 Subject: [PATCH] Compute the right catch location for the debugger. Also remove tls ThrowLocation, it is not needed anymore. Change-Id: I78fddf09ce968ca475e39c17fa76d699c589c8d9 --- compiler/driver/compiler_driver.cc | 8 +- compiler/oat_writer.cc | 2 +- runtime/arch/stub_test.cc | 4 +- runtime/check_jni.cc | 9 +- runtime/class_linker.cc | 18 +-- runtime/class_linker_test.cc | 2 +- runtime/debugger.cc | 127 +++++++++++++++++---- runtime/debugger.h | 3 +- runtime/entrypoints/entrypoint_utils-inl.h | 7 +- runtime/entrypoints/entrypoint_utils.cc | 5 +- .../quick/quick_deoptimization_entrypoints.cc | 2 +- .../entrypoints/quick/quick_throw_entrypoints.cc | 4 +- runtime/entrypoints_order_test.cc | 3 +- runtime/instrumentation.cc | 11 +- runtime/instrumentation.h | 8 +- runtime/interpreter/interpreter_common.cc | 84 +------------- runtime/interpreter/interpreter_goto_table_impl.cc | 4 +- runtime/interpreter/interpreter_switch_impl.cc | 4 +- runtime/jit/jit_instrumentation.h | 3 +- runtime/jni_internal.cc | 42 +++---- runtime/mirror/art_method.cc | 7 +- runtime/mirror/class.cc | 12 +- runtime/mirror/object_test.cc | 18 +-- runtime/monitor.cc | 2 +- runtime/oat.h | 2 +- runtime/quick_exception_handler.cc | 10 +- runtime/quick_exception_handler.h | 3 +- runtime/reflection.cc | 2 +- runtime/runtime.cc | 11 +- runtime/thread.cc | 66 ++++------- runtime/thread.h | 15 +-- runtime/trace.cc | 6 +- runtime/trace.h | 4 +- 33 files changed, 220 insertions(+), 288 deletions(-) diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index 029fd4606..98abc1811 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 c32a99226..b3bb438ba 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 0d41a8fd2..076968771 100644 --- a/runtime/arch/stub_test.cc +++ b/runtime/arch/stub_test.cc @@ -1171,7 +1171,7 @@ TEST_F(StubTest, AllocObjectArray) { reinterpret_cast(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(nullptr), result); mirror::Object* obj = reinterpret_cast(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 7db1d7237..2b0167d41 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 2989b8c6c..f0c8819a5 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 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 klass) { PrettyDescriptor(klass.Get()).c_str(), PrettyDescriptor(super.Get()).c_str())); LOG(WARNING) << error_msg << " in " << klass->GetDexCache()->GetLocation()->ToModifiedUtf8(); - Handle cause(hs.NewHandle(self->GetException(nullptr))); + Handle 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 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 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 cause(hs.NewHandle(self->GetException(nullptr))); + Handle 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 64e129c38..1789ab12d 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 246125bd5..964e84c36 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& 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(nullptr)), + catch_method_(handle_scope_.NewHandle(nullptr)), + throw_method_(handle_scope_.NewHandle(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 exception_class(hs.NewHandle(exception_->GetClass())); + Handle 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& exception_; + StackHandleScope<3> handle_scope_; + MutableHandle this_at_throw_; + MutableHandle catch_method_; + MutableHandle 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 h_exception(handle_scope.NewHandle(exception_object)); + std::unique_ptr 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(nullptr); - auto old_throw_method = hs.NewHandle(nullptr); + StackHandleScope<2> hs(soa.Self()); auto old_exception = hs.NewHandle(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(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 0c22148c9..428ded7ff 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 9d84e4ac4..149c6b43b 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 5ea9f708a..af528b767 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(self->DecodeJObject(exc.get()))); + self->SetException(reinterpret_cast(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(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 14ab320b9..d88d26230 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 25df40b6c..127f9e04a 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 917335713..0fdfcb3af 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 c94dab988..085062c64 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> 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 b667a40fc..e3f18f15c 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 754602f94..3f09bd3e5 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* exception) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) - : StackVisitor(self, nullptr), self_(self), handle_scope_(self), exception_(exception), - catch_method_(handle_scope_.NewHandle(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 exception_class(hs.NewHandle((*exception_)->GetClass())); - Handle 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* exception_; - MutableHandle 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 exception(hs.NewHandle(self->GetException(&throw_location))); + Handle 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 37324eac8..f1ab7477e 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 2f8558760..dceed4716 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 9576f4b34..9d122e0ad 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 561302e33..213de6f1c 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 cause(hs2.NewHandle(soa.Self()->GetException(&throw_location))); + Handle 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(exception.get())); + soa.Self()->SetException(soa.Decode(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(nullptr)); - auto old_throw_method(hs.NewHandle(nullptr)); - auto old_exception(hs.NewHandle(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 old_exception( + hs.NewHandle(soa.Self()->GetException())); + soa.Self()->ClearException(); ScopedLocalRef exception(env, soa.AddLocalReference(old_exception.Get())); ScopedLocalRef 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(exception); } diff --git a/runtime/mirror/art_method.cc b/runtime/mirror/art_method.cc index 85fc5f3c9..bc5870980 100644 --- a/runtime/mirror/art_method.cc +++ b/runtime/mirror/art_method.cc @@ -271,9 +271,8 @@ uint32_t ArtMethod::FindCatchBlock(Handle h_this, Handle 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 exception(hs.NewHandle(self->GetException(&throw_location))); + Handle 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 h_this, Handle 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 96b15dd67..6f4ef60e8 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 old_exception(hs.NewHandle(self->GetException(&old_throw_location))); + StackHandleScope<1> hs(self); + Handle old_exception(hs.NewHandle(self->GetException())); CHECK(old_exception.Get() != nullptr); - Handle old_throw_this_object(hs.NewHandle(old_throw_location.GetThis())); - Handle 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 9b345a65d..21972a1cc 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(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 45a971d22..dce8bacb5 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 f973b2897..5540ade55 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 1ddb76114..0eb8eca7d 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 a0e6a7929..08619fa0d 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 2aeb92d49..4acd07fb1 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 383308cf9..2043672c8 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(self->GetException(NULL)); + pre_allocated_OutOfMemoryError_ = GcRoot(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(self->GetException(NULL)); + pre_allocated_NoClassDefFoundError_ = GcRoot(self->GetException()); self->ClearException(); // Look for a native bridge. diff --git a/runtime/thread.cc b/runtime/thread.cc index fdb1f9dd4..e31af1627 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 exc; - Handle throw_location_this_object; - Handle 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(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(this)->SetException(exc_location, exc.Get()); + const_cast(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 saved_throw_this(hs.NewHandle(throw_location.GetThis())); - Handle saved_throw_method(hs.NewHandle(throw_location.GetMethod())); - // Ignore the cause throw location. TODO: should we report this as a re-throw? - ScopedLocalRef cause(GetJniEnv(), soa.AddLocalReference(GetException(nullptr))); + StackHandleScope<3> hs(soa.Self()); + Handle class_loader( + hs.NewHandle(GetClassLoaderFromThrowLocation(throw_location))); + ScopedLocalRef cause(GetJniEnv(), soa.AddLocalReference(GetException())); ClearException(); Runtime* runtime = Runtime::Current(); - - mirror::ClassLoader* cl = nullptr; - if (saved_throw_method.Get() != nullptr) { - cl = saved_throw_method.Get()->GetDeclaringClass()->GetClassLoader(); - } - Handle class_loader(hs.NewHandle(cl)); Handle 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(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(&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 e4c91b72b..af02dc779 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* stack_trace_sample; diff --git a/runtime/trace.cc b/runtime/trace.cc index 93b3877bf..a1296f4a5 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 9ba30d5f8..dd8186a2c 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; -- 2.11.0