diff options
| author | 2012-04-14 10:39:17 -0700 | |
|---|---|---|
| committer | 2012-04-14 10:39:17 -0700 | |
| commit | 33687790adbb889abdd95bb22914acb57ce6e68c (patch) | |
| tree | 799bd49e3d9afd2f70fa82f427e78d938d0dc0da /src | |
| parent | bb48fbbca9e5d93e9c9ccfd62e64a6a6cb720c68 (diff) | |
| parent | 8a8b9cbe158ee13477f2381f164c519762a06fef (diff) | |
Merge "Improved OOME detail messages." into ics-mr1-plus-art
Diffstat (limited to 'src')
| -rw-r--r-- | src/heap.cc | 44 | ||||
| -rw-r--r-- | src/thread.cc | 6 | ||||
| -rw-r--r-- | src/thread.h | 2 |
3 files changed, 33 insertions, 19 deletions
diff --git a/src/heap.cc b/src/heap.cc index e244cf1a72..eb62807c23 100644 --- a/src/heap.cc +++ b/src/heap.cc @@ -267,24 +267,49 @@ Heap::~Heap() { delete lock_; } -Object* Heap::AllocObject(Class* klass, size_t byte_count) { +static void MSpaceChunkCallback(void* start, void* end, size_t used_bytes, void* arg) { + size_t& max_contiguous_allocation = *reinterpret_cast<size_t*>(arg); + + size_t chunk_size = static_cast<size_t>(reinterpret_cast<uint8_t*>(end) - reinterpret_cast<uint8_t*>(start)); + size_t chunk_free_bytes = 0; + if (used_bytes < chunk_size) { + chunk_free_bytes = chunk_size - used_bytes; + } + + if (chunk_free_bytes > max_contiguous_allocation) { + max_contiguous_allocation = chunk_free_bytes; + } +} + +Object* Heap::AllocObject(Class* c, size_t byte_count) { + // Used in the detail message if we throw an OOME. + int64_t total_bytes_free; + size_t max_contiguous_allocation; + { ScopedHeapLock heap_lock; - DCHECK(klass == NULL || (klass->IsClassClass() && byte_count >= sizeof(Class)) || - (klass->IsVariableSize() || klass->GetObjectSize() == byte_count) || - strlen(ClassHelper(klass).GetDescriptor()) == 0); + DCHECK(c == NULL || (c->IsClassClass() && byte_count >= sizeof(Class)) || + (c->IsVariableSize() || c->GetObjectSize() == byte_count) || + strlen(ClassHelper(c).GetDescriptor()) == 0); DCHECK_GE(byte_count, sizeof(Object)); Object* obj = AllocateLocked(byte_count); if (obj != NULL) { - obj->SetClass(klass); + obj->SetClass(c); if (Dbg::IsAllocTrackingEnabled()) { - Dbg::RecordAllocation(klass, byte_count); + Dbg::RecordAllocation(c, byte_count); } return obj; } + total_bytes_free = GetFreeMemory(); + max_contiguous_allocation = 0; + GetAllocSpace()->Walk(MSpaceChunkCallback, &max_contiguous_allocation); } - Thread::Current()->ThrowOutOfMemoryError(klass, byte_count); + std::string msg(StringPrintf("Failed to allocate a %zd-byte %s (%lld total bytes free; largest possible contiguous allocation %zd bytes)", + byte_count, + PrettyDescriptor(c).c_str(), + total_bytes_free, max_contiguous_allocation)); + Thread::Current()->ThrowOutOfMemoryError(msg.c_str()); return NULL; } @@ -491,11 +516,6 @@ Object* Heap::AllocateLocked(AllocSpace* space, size_t alloc_size) { return ptr; } - LOG(ERROR) << "Out of memory on a " << PrettySize(alloc_size) << " allocation"; - - // TODO: tell the HeapSource to dump its state - // TODO: dump stack traces for all threads - return NULL; } diff --git a/src/thread.cc b/src/thread.cc index 1a39d9989f..fbc718c7dc 100644 --- a/src/thread.cc +++ b/src/thread.cc @@ -1424,12 +1424,6 @@ void Thread::ThrowNewException(const char* exception_class_descriptor, const cha } } -void Thread::ThrowOutOfMemoryError(Class* c, size_t byte_count) { - std::string msg(StringPrintf("Failed to allocate a %zd-byte %s", byte_count, - PrettyDescriptor(c).c_str())); - ThrowOutOfMemoryError(msg.c_str()); -} - void Thread::ThrowOutOfMemoryError(const char* msg) { LOG(ERROR) << StringPrintf("Throwing OutOfMemoryError \"%s\"%s", msg, (throwing_OutOfMemoryError_ ? " (recursive case)" : "")); diff --git a/src/thread.h b/src/thread.h index a100c0329a..2cb59d5437 100644 --- a/src/thread.h +++ b/src/thread.h @@ -254,8 +254,8 @@ class PACKED Thread { void ThrowNewExceptionV(const char* exception_class_descriptor, const char* fmt, va_list ap); // OutOfMemoryError is special, because we need to pre-allocate an instance. + // Only the GC should call this. void ThrowOutOfMemoryError(const char* msg); - void ThrowOutOfMemoryError(Class* c, size_t byte_count); Frame FindExceptionHandler(void* throw_pc, void** handler_pc); |