From f1c4d0e3a27e9b39916750147ecdea1418fcc231 Mon Sep 17 00:00:00 2001 From: Mathieu Chartier Date: Mon, 1 Dec 2014 15:00:27 -0800 Subject: [PATCH] Try normal allocation if large object allocation fails If a large object allocation fails, we now try the normal allocators. Bug: 18504942 Change-Id: I18b9759d6af885556941542c57fec584f18197f1 --- runtime/gc/heap-inl.h | 22 +++++++++++++++++----- runtime/gc/heap.h | 2 +- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/runtime/gc/heap-inl.h b/runtime/gc/heap-inl.h index d1fb60061..15d55d029 100644 --- a/runtime/gc/heap-inl.h +++ b/runtime/gc/heap-inl.h @@ -48,11 +48,20 @@ inline mirror::Object* Heap::AllocObjectWithAllocator(Thread* self, mirror::Clas } // Need to check that we arent the large object allocator since the large object allocation code // path this function. If we didn't check we would have an infinite loop. + mirror::Object* obj; if (kCheckLargeObject && UNLIKELY(ShouldAllocLargeObject(klass, byte_count))) { - return AllocLargeObject(self, klass, byte_count, - pre_fence_visitor); + obj = AllocLargeObject(self, &klass, byte_count, + pre_fence_visitor); + if (obj != nullptr) { + return obj; + } else { + // There should be an OOM exception, since we are retrying, clear it. + self->ClearException(); + } + // If the large object allocation failed, try to use the normal spaces (main space, + // non moving space). This can happen if there is significant virtual address space + // fragmentation. } - mirror::Object* obj; AllocationTimer alloc_timer(this, &obj); size_t bytes_allocated; size_t usable_size; @@ -171,10 +180,13 @@ inline void Heap::PushOnAllocationStack(Thread* self, mirror::Object** obj) { } template -inline mirror::Object* Heap::AllocLargeObject(Thread* self, mirror::Class* klass, +inline mirror::Object* Heap::AllocLargeObject(Thread* self, mirror::Class** klass, size_t byte_count, const PreFenceVisitor& pre_fence_visitor) { - return AllocObjectWithAllocator(self, klass, byte_count, + // Save and restore the class in case it moves. + StackHandleScope<1> hs(self); + auto klass_wrapper = hs.NewHandleWrapper(klass); + return AllocObjectWithAllocator(self, *klass, byte_count, kAllocatorTypeLOS, pre_fence_visitor); } diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h index 24f4f171b..530ec187e 100644 --- a/runtime/gc/heap.h +++ b/runtime/gc/heap.h @@ -643,7 +643,7 @@ class Heap { // We don't force this to be inlined since it is a slow path. template - mirror::Object* AllocLargeObject(Thread* self, mirror::Class* klass, size_t byte_count, + mirror::Object* AllocLargeObject(Thread* self, mirror::Class** klass, size_t byte_count, const PreFenceVisitor& pre_fence_visitor) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); -- 2.11.0