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