summaryrefslogtreecommitdiff
path: root/runtime/runtime.cc
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/runtime.cc')
-rw-r--r--runtime/runtime.cc99
1 files changed, 69 insertions, 30 deletions
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 9f7f5cd7639..c8e7e67beb4 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -62,6 +62,8 @@
#include "base/dumpable.h"
#include "base/enums.h"
#include "base/file_utils.h"
+#include "base/malloc_arena_pool.h"
+#include "base/mem_map_arena_pool.h"
#include "base/memory_tool.h"
#include "base/mutex.h"
#include "base/os.h"
@@ -574,19 +576,7 @@ void Runtime::Abort(const char* msg) {
LOG(FATAL_WITHOUT_ABORT) << "Unexpectedly returned from abort hook!";
}
-#if defined(__GLIBC__)
- // TODO: we ought to be able to use pthread_kill(3) here (or abort(3),
- // which POSIX defines in terms of raise(3), which POSIX defines in terms
- // of pthread_kill(3)). On Linux, though, libcorkscrew can't unwind through
- // libpthread, which means the stacks we dump would be useless. Calling
- // tgkill(2) directly avoids that.
- syscall(__NR_tgkill, getpid(), GetTid(), SIGABRT);
- // TODO: LLVM installs it's own SIGABRT handler so exit to be safe... Can we disable that in LLVM?
- // If not, we could use sigaction(3) before calling tgkill(2) and lose this call to exit(3).
- exit(1);
-#else
abort();
-#endif
// notreached
}
@@ -841,7 +831,6 @@ bool Runtime::Start() {
if (trace_config_.get() != nullptr && trace_config_->trace_file != "") {
ScopedThreadStateChange tsc(self, kWaitingForMethodTracingStart);
Trace::Start(trace_config_->trace_file.c_str(),
- -1,
static_cast<int>(trace_config_->trace_file_size),
0,
trace_config_->trace_output_mode,
@@ -1334,13 +1323,17 @@ bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) {
// Use MemMap arena pool for jit, malloc otherwise. Malloc arenas are faster to allocate but
// can't be trimmed as easily.
const bool use_malloc = IsAotCompiler();
- arena_pool_.reset(new ArenaPool(use_malloc, /* low_4gb */ false));
- jit_arena_pool_.reset(
- new ArenaPool(/* use_malloc */ false, /* low_4gb */ false, "CompilerMetadata"));
+ if (use_malloc) {
+ arena_pool_.reset(new MallocArenaPool());
+ jit_arena_pool_.reset(new MallocArenaPool());
+ } else {
+ arena_pool_.reset(new MemMapArenaPool(/* low_4gb */ false));
+ jit_arena_pool_.reset(new MemMapArenaPool(/* low_4gb */ false, "CompilerMetadata"));
+ }
if (IsAotCompiler() && Is64BitInstructionSet(kRuntimeISA)) {
// 4gb, no malloc. Explanation in header.
- low_4gb_arena_pool_.reset(new ArenaPool(/* use_malloc */ false, /* low_4gb */ true));
+ low_4gb_arena_pool_.reset(new MemMapArenaPool(/* low_4gb */ true));
}
linear_alloc_.reset(CreateLinearAlloc());
@@ -1511,19 +1504,34 @@ bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) {
// TODO: move this to just be an Trace::Start argument
Trace::SetDefaultClockSource(runtime_options.GetOrDefault(Opt::ProfileClock));
+ // Pre-allocate an OutOfMemoryError for the case when we fail to
+ // allocate the exception to be thrown.
+ InitPreAllocatedException(self,
+ &Runtime::pre_allocated_OutOfMemoryError_when_throwing_exception_,
+ "Ljava/lang/OutOfMemoryError;",
+ "OutOfMemoryError thrown while trying to throw an exception; "
+ "no stack trace available");
// Pre-allocate an OutOfMemoryError for the double-OOME case.
- self->ThrowNewException("Ljava/lang/OutOfMemoryError;",
- "OutOfMemoryError thrown while trying to throw OutOfMemoryError; "
- "no stack trace available");
- pre_allocated_OutOfMemoryError_ = GcRoot<mirror::Throwable>(self->GetException());
- self->ClearException();
+ InitPreAllocatedException(self,
+ &Runtime::pre_allocated_OutOfMemoryError_when_throwing_oome_,
+ "Ljava/lang/OutOfMemoryError;",
+ "OutOfMemoryError thrown while trying to throw OutOfMemoryError; "
+ "no stack trace available");
+ // Pre-allocate an OutOfMemoryError for the case when we fail to
+ // allocate while handling a stack overflow.
+ InitPreAllocatedException(self,
+ &Runtime::pre_allocated_OutOfMemoryError_when_handling_stack_overflow_,
+ "Ljava/lang/OutOfMemoryError;",
+ "OutOfMemoryError thrown while trying to handle a stack overflow; "
+ "no stack trace available");
// 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("Ljava/lang/NoClassDefFoundError;",
- "Class not found using the boot class loader; no stack trace available");
- pre_allocated_NoClassDefFoundError_ = GcRoot<mirror::Throwable>(self->GetException());
- self->ClearException();
+ InitPreAllocatedException(self,
+ &Runtime::pre_allocated_NoClassDefFoundError_,
+ "Ljava/lang/NoClassDefFoundError;",
+ "Class not found using the boot class loader; "
+ "no stack trace available");
// Runtime initialization is largely done now.
// We load plugins first since that can modify the runtime state slightly.
@@ -1674,6 +1682,16 @@ void Runtime::AttachAgent(JNIEnv* env,
}
}
+void Runtime::InitPreAllocatedException(Thread* self,
+ GcRoot<mirror::Throwable> Runtime::* exception,
+ const char* exception_class_descriptor,
+ const char* msg) {
+ DCHECK_EQ(self, Thread::Current());
+ self->ThrowNewException(exception_class_descriptor, msg);
+ this->*exception = GcRoot<mirror::Throwable>(self->GetException());
+ self->ClearException();
+}
+
void Runtime::InitNativeMethods() {
VLOG(startup) << "Runtime::InitNativeMethods entering";
Thread* self = Thread::Current();
@@ -1925,10 +1943,26 @@ void Runtime::DetachCurrentThread() {
thread_list_->Unregister(self);
}
-mirror::Throwable* Runtime::GetPreAllocatedOutOfMemoryError() {
- mirror::Throwable* oome = pre_allocated_OutOfMemoryError_.Read();
+mirror::Throwable* Runtime::GetPreAllocatedOutOfMemoryErrorWhenThrowingException() {
+ mirror::Throwable* oome = pre_allocated_OutOfMemoryError_when_throwing_exception_.Read();
+ if (oome == nullptr) {
+ LOG(ERROR) << "Failed to return pre-allocated OOME-when-throwing-exception";
+ }
+ return oome;
+}
+
+mirror::Throwable* Runtime::GetPreAllocatedOutOfMemoryErrorWhenThrowingOOME() {
+ mirror::Throwable* oome = pre_allocated_OutOfMemoryError_when_throwing_oome_.Read();
+ if (oome == nullptr) {
+ LOG(ERROR) << "Failed to return pre-allocated OOME-when-throwing-OOME";
+ }
+ return oome;
+}
+
+mirror::Throwable* Runtime::GetPreAllocatedOutOfMemoryErrorWhenHandlingStackOverflow() {
+ mirror::Throwable* oome = pre_allocated_OutOfMemoryError_when_handling_stack_overflow_.Read();
if (oome == nullptr) {
- LOG(ERROR) << "Failed to return pre-allocated OOME";
+ LOG(ERROR) << "Failed to return pre-allocated OOME-when-handling-stack-overflow";
}
return oome;
}
@@ -2013,7 +2047,12 @@ void Runtime::VisitTransactionRoots(RootVisitor* visitor) {
void Runtime::VisitNonThreadRoots(RootVisitor* visitor) {
java_vm_->VisitRoots(visitor);
sentinel_.VisitRootIfNonNull(visitor, RootInfo(kRootVMInternal));
- pre_allocated_OutOfMemoryError_.VisitRootIfNonNull(visitor, RootInfo(kRootVMInternal));
+ pre_allocated_OutOfMemoryError_when_throwing_exception_
+ .VisitRootIfNonNull(visitor, RootInfo(kRootVMInternal));
+ pre_allocated_OutOfMemoryError_when_throwing_oome_
+ .VisitRootIfNonNull(visitor, RootInfo(kRootVMInternal));
+ pre_allocated_OutOfMemoryError_when_handling_stack_overflow_
+ .VisitRootIfNonNull(visitor, RootInfo(kRootVMInternal));
pre_allocated_NoClassDefFoundError_.VisitRootIfNonNull(visitor, RootInfo(kRootVMInternal));
verifier::MethodVerifier::VisitStaticRoots(visitor);
VisitTransactionRoots(visitor);