Merge "ART: Move ThrowStackOverflowError to common_throws"
diff --git a/runtime/art_method.cc b/runtime/art_method.cc
index effa1c5..6f36016 100644
--- a/runtime/art_method.cc
+++ b/runtime/art_method.cc
@@ -24,7 +24,6 @@
#include "debugger.h"
#include "dex_file-inl.h"
#include "dex_instruction.h"
-#include "entrypoints/entrypoint_utils.h"
#include "entrypoints/runtime_asm_entrypoints.h"
#include "gc/accounting/card_table-inl.h"
#include "interpreter/interpreter.h"
diff --git a/runtime/common_throws.cc b/runtime/common_throws.cc
index d68b463..40e2b15 100644
--- a/runtime/common_throws.cc
+++ b/runtime/common_throws.cc
@@ -18,6 +18,8 @@
#include <sstream>
+#include "ScopedLocalRef.h"
+
#include "art_field-inl.h"
#include "art_method-inl.h"
#include "base/logging.h"
@@ -522,6 +524,104 @@
va_end(args);
}
+// Stack overflow.
+
+void ThrowStackOverflowError(Thread* self) {
+ if (self->IsHandlingStackOverflow()) {
+ LOG(ERROR) << "Recursive stack overflow.";
+ // We don't fail here because SetStackEndForStackOverflow will print better diagnostics.
+ }
+
+ 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.
+
+ std::string error_msg;
+
+ // Allocate an uninitialized object.
+ ScopedLocalRef<jobject> exc(env,
+ env->AllocObject(WellKnownClasses::java_lang_StackOverflowError));
+ if (exc.get() != nullptr) {
+ // "Initialize".
+ // StackOverflowError -> VirtualMachineError -> Error -> Throwable -> Object.
+ // Only Throwable has "custom" fields:
+ // String detailMessage.
+ // Throwable cause (= this).
+ // List<Throwable> suppressedExceptions (= Collections.emptyList()).
+ // Object stackState;
+ // StackTraceElement[] stackTrace;
+ // Only Throwable has a non-empty constructor:
+ // this.stackTrace = EmptyArray.STACK_TRACE_ELEMENT;
+ // fillInStackTrace();
+
+ // detailMessage.
+ // TODO: Use String::FromModifiedUTF...?
+ ScopedLocalRef<jstring> s(env, env->NewStringUTF(msg.c_str()));
+ if (s.get() != nullptr) {
+ env->SetObjectField(exc.get(), WellKnownClasses::java_lang_Throwable_detailMessage, s.get());
+
+ // cause.
+ env->SetObjectField(exc.get(), WellKnownClasses::java_lang_Throwable_cause, exc.get());
+
+ // suppressedExceptions.
+ ScopedLocalRef<jobject> emptylist(env, env->GetStaticObjectField(
+ WellKnownClasses::java_util_Collections,
+ WellKnownClasses::java_util_Collections_EMPTY_LIST));
+ CHECK(emptylist.get() != nullptr);
+ env->SetObjectField(exc.get(),
+ WellKnownClasses::java_lang_Throwable_suppressedExceptions,
+ emptylist.get());
+
+ // stackState is set as result of fillInStackTrace. fillInStackTrace calls
+ // nativeFillInStackTrace.
+ ScopedLocalRef<jobject> stack_state_val(env, nullptr);
+ {
+ ScopedObjectAccessUnchecked soa(env);
+ stack_state_val.reset(soa.Self()->CreateInternalStackTrace<false>(soa));
+ }
+ if (stack_state_val.get() != nullptr) {
+ env->SetObjectField(exc.get(),
+ WellKnownClasses::java_lang_Throwable_stackState,
+ stack_state_val.get());
+
+ // 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());
+ } else {
+ error_msg = "Could not create stack trace.";
+ }
+ // Throw the exception.
+ 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.";
+ }
+ } else {
+ error_msg = "Could not allocate StackOverflowError object.";
+ }
+
+ if (!error_msg.empty()) {
+ LOG(WARNING) << error_msg;
+ CHECK(self->IsExceptionPending());
+ }
+
+ bool explicit_overflow_check = Runtime::Current()->ExplicitStackOverflowChecks();
+ self->ResetDefaultStackEnd(); // Return to default stack size.
+
+ // And restore protection if implicit checks are on.
+ if (!explicit_overflow_check) {
+ self->ProtectStack();
+ }
+}
+
// VerifyError
void ThrowVerifyError(mirror::Class* referrer, const char* fmt, ...) {
diff --git a/runtime/common_throws.h b/runtime/common_throws.h
index 2a0934f..85fe2b3 100644
--- a/runtime/common_throws.h
+++ b/runtime/common_throws.h
@@ -154,10 +154,10 @@
void ThrowNoSuchFieldError(const StringPiece& scope, mirror::Class* c,
const StringPiece& type, const StringPiece& name)
- SHARED_REQUIRES(Locks::mutator_lock_);
+ SHARED_REQUIRES(Locks::mutator_lock_) COLD_ATTR;
void ThrowNoSuchFieldException(mirror::Class* c, const StringPiece& name)
- SHARED_REQUIRES(Locks::mutator_lock_);
+ SHARED_REQUIRES(Locks::mutator_lock_) COLD_ATTR;
// NoSuchMethodError
@@ -194,6 +194,10 @@
__attribute__((__format__(__printf__, 1, 2)))
SHARED_REQUIRES(Locks::mutator_lock_) COLD_ATTR;
+// Stack overflow.
+
+void ThrowStackOverflowError(Thread* self) SHARED_REQUIRES(Locks::mutator_lock_) COLD_ATTR;
+
// VerifyError
void ThrowVerifyError(mirror::Class* referrer, const char* fmt, ...)
diff --git a/runtime/entrypoints/entrypoint_utils.cc b/runtime/entrypoints/entrypoint_utils.cc
index 915d9ab..b5a55bf 100644
--- a/runtime/entrypoints/entrypoint_utils.cc
+++ b/runtime/entrypoints/entrypoint_utils.cc
@@ -33,7 +33,6 @@
#include "oat_quick_method_header.h"
#include "reflection.h"
#include "scoped_thread_state_change.h"
-#include "ScopedLocalRef.h"
#include "well_known_classes.h"
namespace art {
@@ -120,102 +119,6 @@
heap->GetCurrentAllocator());
}
-void ThrowStackOverflowError(Thread* self) {
- if (self->IsHandlingStackOverflow()) {
- LOG(ERROR) << "Recursive stack overflow.";
- // We don't fail here because SetStackEndForStackOverflow will print better diagnostics.
- }
-
- 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.
-
- std::string error_msg;
-
- // Allocate an uninitialized object.
- ScopedLocalRef<jobject> exc(env,
- env->AllocObject(WellKnownClasses::java_lang_StackOverflowError));
- if (exc.get() != nullptr) {
- // "Initialize".
- // StackOverflowError -> VirtualMachineError -> Error -> Throwable -> Object.
- // Only Throwable has "custom" fields:
- // String detailMessage.
- // Throwable cause (= this).
- // List<Throwable> suppressedExceptions (= Collections.emptyList()).
- // Object stackState;
- // StackTraceElement[] stackTrace;
- // Only Throwable has a non-empty constructor:
- // this.stackTrace = EmptyArray.STACK_TRACE_ELEMENT;
- // fillInStackTrace();
-
- // detailMessage.
- // TODO: Use String::FromModifiedUTF...?
- ScopedLocalRef<jstring> s(env, env->NewStringUTF(msg.c_str()));
- if (s.get() != nullptr) {
- env->SetObjectField(exc.get(), WellKnownClasses::java_lang_Throwable_detailMessage, s.get());
-
- // cause.
- env->SetObjectField(exc.get(), WellKnownClasses::java_lang_Throwable_cause, exc.get());
-
- // suppressedExceptions.
- ScopedLocalRef<jobject> emptylist(env, env->GetStaticObjectField(
- WellKnownClasses::java_util_Collections,
- WellKnownClasses::java_util_Collections_EMPTY_LIST));
- CHECK(emptylist.get() != nullptr);
- env->SetObjectField(exc.get(),
- WellKnownClasses::java_lang_Throwable_suppressedExceptions,
- emptylist.get());
-
- // stackState is set as result of fillInStackTrace. fillInStackTrace calls
- // nativeFillInStackTrace.
- ScopedLocalRef<jobject> stack_state_val(env, nullptr);
- {
- ScopedObjectAccessUnchecked soa(env);
- stack_state_val.reset(soa.Self()->CreateInternalStackTrace<false>(soa));
- }
- if (stack_state_val.get() != nullptr) {
- env->SetObjectField(exc.get(),
- WellKnownClasses::java_lang_Throwable_stackState,
- stack_state_val.get());
-
- // 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());
- } else {
- error_msg = "Could not create stack trace.";
- }
- // Throw the exception.
- 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.";
- }
- } else {
- error_msg = "Could not allocate StackOverflowError object.";
- }
-
- if (!error_msg.empty()) {
- LOG(WARNING) << error_msg;
- CHECK(self->IsExceptionPending());
- }
-
- bool explicit_overflow_check = Runtime::Current()->ExplicitStackOverflowChecks();
- self->ResetDefaultStackEnd(); // Return to default stack size.
-
- // And restore protection if implicit checks are on.
- if (!explicit_overflow_check) {
- self->ProtectStack();
- }
-}
-
void CheckReferenceResult(mirror::Object* o, Thread* self) {
if (o == nullptr) {
return;
diff --git a/runtime/entrypoints/entrypoint_utils.h b/runtime/entrypoints/entrypoint_utils.h
index 0469ee6..a28376f 100644
--- a/runtime/entrypoints/entrypoint_utils.h
+++ b/runtime/entrypoints/entrypoint_utils.h
@@ -158,8 +158,6 @@
uint32_t type_idx, ArtMethod* referrer, Thread* self, bool can_run_clinit, bool verify_access)
SHARED_REQUIRES(Locks::mutator_lock_);
-extern void ThrowStackOverflowError(Thread* self) SHARED_REQUIRES(Locks::mutator_lock_);
-
inline mirror::String* ResolveStringFromCode(ArtMethod* referrer, uint32_t string_idx)
SHARED_REQUIRES(Locks::mutator_lock_);
diff --git a/runtime/entrypoints/quick/quick_throw_entrypoints.cc b/runtime/entrypoints/quick/quick_throw_entrypoints.cc
index 5a82b3a..5256fea 100644
--- a/runtime/entrypoints/quick/quick_throw_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_throw_entrypoints.cc
@@ -16,7 +16,6 @@
#include "callee_save_frame.h"
#include "common_throws.h"
-#include "entrypoints/entrypoint_utils-inl.h"
#include "mirror/object-inl.h"
#include "thread.h"
#include "well_known_classes.h"
diff --git a/runtime/interpreter/interpreter.cc b/runtime/interpreter/interpreter.cc
index 871fad7..8d5a61a 100644
--- a/runtime/interpreter/interpreter.cc
+++ b/runtime/interpreter/interpreter.cc
@@ -18,6 +18,7 @@
#include <limits>
+#include "common_throws.h"
#include "interpreter_common.h"
#include "mirror/string-inl.h"
#include "scoped_thread_state_change.h"
diff --git a/runtime/reflection.cc b/runtime/reflection.cc
index 324bd9f..28c27cd 100644
--- a/runtime/reflection.cc
+++ b/runtime/reflection.cc
@@ -21,7 +21,6 @@
#include "class_linker.h"
#include "common_throws.h"
#include "dex_file-inl.h"
-#include "entrypoints/entrypoint_utils.h"
#include "indirect_reference_table-inl.h"
#include "jni_internal.h"
#include "mirror/abstract_method.h"