diff options
Diffstat (limited to 'runtime/common_throws.cc')
| -rw-r--r-- | runtime/common_throws.cc | 109 |
1 files changed, 63 insertions, 46 deletions
diff --git a/runtime/common_throws.cc b/runtime/common_throws.cc index 17a0a8a714..5182689d86 100644 --- a/runtime/common_throws.cc +++ b/runtime/common_throws.cc @@ -29,14 +29,14 @@ #include "dex/dex_file-inl.h" #include "dex/dex_instruction-inl.h" #include "dex/invoke_type.h" -#include "mirror/class-inl.h" +#include "mirror/class-alloc-inl.h" #include "mirror/method_type.h" #include "mirror/object-inl.h" #include "mirror/object_array-inl.h" #include "nativehelper/scoped_local_ref.h" #include "obj_ptr-inl.h" #include "thread.h" -#include "well_known_classes.h" +#include "well_known_classes-inl.h" namespace art { @@ -152,7 +152,6 @@ void ThrowWrappedBootstrapMethodError(const char* fmt, ...) { // ClassCastException void ThrowClassCastException(ObjPtr<mirror::Class> dest_type, ObjPtr<mirror::Class> src_type) { - DumpB77342775DebugData(dest_type, src_type); ThrowException("Ljava/lang/ClassCastException;", nullptr, StringPrintf("%s cannot be cast to %s", mirror::Class::PrettyDescriptor(src_type).c_str(), @@ -238,6 +237,19 @@ void ThrowIllegalAccessError(ObjPtr<mirror::Class> referrer, const char* fmt, .. va_end(args); } +void ThrowIllegalAccessErrorForImplementingMethod(ObjPtr<mirror::Class> klass, + ArtMethod* implementation_method, + ArtMethod* interface_method) + REQUIRES_SHARED(Locks::mutator_lock_) { + DCHECK(!implementation_method->IsAbstract()); + DCHECK(!implementation_method->IsPublic()); + ThrowIllegalAccessError( + klass, + "Method '%s' implementing interface method '%s' is not public", + implementation_method->PrettyMethod().c_str(), + interface_method->PrettyMethod().c_str()); +} + // IllegalAccessException void ThrowIllegalAccessException(const char* msg) { @@ -281,7 +293,6 @@ void ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(ArtMethod* inter << "' does not implement interface '" << mirror::Class::PrettyDescriptor(interface_method->GetDeclaringClass()) << "' in call to '" << ArtMethod::PrettyMethod(interface_method) << "'"; - DumpB77342775DebugData(interface_method->GetDeclaringClass(), this_object->GetClass()); ThrowException("Ljava/lang/IncompatibleClassChangeError;", referrer != nullptr ? referrer->GetDeclaringClass() : nullptr, msg.str().c_str()); @@ -437,7 +448,7 @@ void ThrowNullPointerExceptionForMethodAccess(ArtMethod* method, InvokeType type } static bool IsValidReadBarrierImplicitCheck(uintptr_t addr) { - DCHECK(kEmitCompilerReadBarrier); + DCHECK(gUseReadBarrier); uint32_t monitor_offset = mirror::Object::MonitorOffset().Uint32Value(); if (kUseBakerReadBarrier && (kRuntimeISA == InstructionSet::kX86 || kRuntimeISA == InstructionSet::kX86_64)) { @@ -472,7 +483,7 @@ static bool IsValidImplicitCheck(uintptr_t addr, const Instruction& instr) } case Instruction::IGET_OBJECT: - if (kEmitCompilerReadBarrier && IsValidReadBarrierImplicitCheck(addr)) { + if (gUseReadBarrier && IsValidReadBarrierImplicitCheck(addr)) { return true; } FALLTHROUGH_INTENDED; @@ -496,7 +507,7 @@ static bool IsValidImplicitCheck(uintptr_t addr, const Instruction& instr) } case Instruction::AGET_OBJECT: - if (kEmitCompilerReadBarrier && IsValidReadBarrierImplicitCheck(addr)) { + if (gUseReadBarrier && IsValidReadBarrierImplicitCheck(addr)) { return true; } FALLTHROUGH_INTENDED; @@ -690,20 +701,25 @@ void ThrowStackOverflowError(Thread* self) { } self->SetStackEndForStackOverflow(); // Allow space on the stack for constructor to execute. - JNIEnvExt* env = self->GetJniEnv(); - std::string msg("stack size "); - msg += PrettySize(self->GetStackSize()); // Avoid running Java code for exception initialization. // TODO: Checks to make this a bit less brittle. // - // Note: this lambda ensures that the destruction of the ScopedLocalRefs will run in the extended - // stack, which is important for modes with larger stack sizes (e.g., ASAN). Using a lambda - // instead of a block simplifies the control flow. - auto create_and_throw = [&]() REQUIRES_SHARED(Locks::mutator_lock_) { + // Note: This lambda is used to make sure the `StackOverflowError` intitialization code + // does not increase the frame size of `ThrowStackOverflowError()` itself. It runs + // with its own frame in the extended stack, which is especially important for modes + // with larger stack sizes (e.g., ASAN). + auto create_and_throw = [self]() REQUIRES_SHARED(Locks::mutator_lock_) NO_INLINE { + std::string msg("stack size "); + msg += PrettySize(self->GetStackSize()); + + ScopedObjectAccessUnchecked soa(self); + StackHandleScope<1u> hs(self); + // Allocate an uninitialized object. - ScopedLocalRef<jobject> exc(env, - env->AllocObject(WellKnownClasses::java_lang_StackOverflowError)); + DCHECK(WellKnownClasses::java_lang_StackOverflowError->IsInitialized()); + Handle<mirror::Object> exc = hs.NewHandle( + WellKnownClasses::java_lang_StackOverflowError->AllocObject(self)); if (exc == nullptr) { LOG(WARNING) << "Could not allocate StackOverflowError object."; return; @@ -722,53 +738,54 @@ void ThrowStackOverflowError(Thread* self) { // fillInStackTrace(); // detailMessage. - // TODO: Use String::FromModifiedUTF...? - ScopedLocalRef<jstring> s(env, env->NewStringUTF(msg.c_str())); - if (s == nullptr) { - LOG(WARNING) << "Could not throw new StackOverflowError because JNI NewStringUTF failed."; - return; + { + ObjPtr<mirror::String> s = mirror::String::AllocFromModifiedUtf8(self, msg.c_str()); + if (s == nullptr) { + LOG(WARNING) << "Could not throw new StackOverflowError because message allocation failed."; + return; + } + WellKnownClasses::java_lang_Throwable_detailMessage + ->SetObject</*kTransactionActive=*/ false>(exc.Get(), s); } - env->SetObjectField(exc.get(), WellKnownClasses::java_lang_Throwable_detailMessage, s.get()); - // cause. - env->SetObjectField(exc.get(), WellKnownClasses::java_lang_Throwable_cause, exc.get()); + WellKnownClasses::java_lang_Throwable_cause + ->SetObject</*kTransactionActive=*/ false>(exc.Get(), exc.Get()); // suppressedExceptions. - ScopedLocalRef<jobject> emptylist(env, env->GetStaticObjectField( - WellKnownClasses::java_util_Collections, - WellKnownClasses::java_util_Collections_EMPTY_LIST)); - CHECK(emptylist != nullptr); - env->SetObjectField(exc.get(), - WellKnownClasses::java_lang_Throwable_suppressedExceptions, - emptylist.get()); + { + ObjPtr<mirror::Class> j_u_c = WellKnownClasses::java_util_Collections.Get(); + DCHECK(j_u_c->IsInitialized()); + ObjPtr<mirror::Object> empty_list = + WellKnownClasses::java_util_Collections_EMPTY_LIST->GetObject(j_u_c); + CHECK(empty_list != nullptr); + WellKnownClasses::java_lang_Throwable_suppressedExceptions + ->SetObject</*kTransactionActive=*/ false>(exc.Get(), empty_list); + } // stackState is set as result of fillInStackTrace. fillInStackTrace calls // nativeFillInStackTrace. - ScopedLocalRef<jobject> stack_state_val(env, nullptr); - { - ScopedObjectAccessUnchecked soa(env); // TODO: Is this necessary? - stack_state_val.reset(soa.Self()->CreateInternalStackTrace(soa)); - } + ObjPtr<mirror::Object> stack_state_val = + soa.Decode<mirror::Object>(self->CreateInternalStackTrace(soa)); if (stack_state_val != nullptr) { - env->SetObjectField(exc.get(), - WellKnownClasses::java_lang_Throwable_stackState, - stack_state_val.get()); + WellKnownClasses::java_lang_Throwable_stackState + ->SetObject</*kTransactionActive=*/ false>(exc.Get(), stack_state_val); // stackTrace. - ScopedLocalRef<jobject> stack_trace_elem(env, env->GetStaticObjectField( - WellKnownClasses::libcore_util_EmptyArray, - WellKnownClasses::libcore_util_EmptyArray_STACK_TRACE_ELEMENT)); - env->SetObjectField(exc.get(), - WellKnownClasses::java_lang_Throwable_stackTrace, - stack_trace_elem.get()); + ObjPtr<mirror::Class> l_u_ea = WellKnownClasses::libcore_util_EmptyArray.Get(); + DCHECK(l_u_ea->IsInitialized()); + ObjPtr<mirror::Object> empty_ste = + WellKnownClasses::libcore_util_EmptyArray_STACK_TRACE_ELEMENT->GetObject(l_u_ea); + CHECK(empty_ste != nullptr); + WellKnownClasses::java_lang_Throwable_stackTrace + ->SetObject</*kTransactionActive=*/ false>(exc.Get(), empty_ste); } else { LOG(WARNING) << "Could not create stack trace."; // Note: we'll create an exception without stack state, which is valid. } // Throw the exception. - self->SetException(self->DecodeJObject(exc.get())->AsThrowable()); + self->SetException(exc->AsThrowable()); }; create_and_throw(); CHECK(self->IsExceptionPending()); |