diff options
Diffstat (limited to 'runtime/runtime.cc')
| -rw-r--r-- | runtime/runtime.cc | 99 |
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); |
