diff -r f9884e190f2b -r d6b29ce07538 src/hotspot/share/gc/g1/g1CollectedHeap.cpp --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp Fri Feb 09 12:53:08 2018 +0100 +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp Tue Feb 13 22:10:03 2018 +0000 @@ -445,9 +445,7 @@ assert_heap_not_locked_and_not_at_safepoint(); assert(!is_humongous(word_size), "we do not allow humongous TLABs"); - uint dummy_gc_count_before; - uint dummy_gclocker_retry_count = 0; - return attempt_allocation(word_size, &dummy_gc_count_before, &dummy_gclocker_retry_count); + return attempt_allocation(word_size); } HeapWord* @@ -455,62 +453,16 @@ bool* gc_overhead_limit_was_exceeded) { assert_heap_not_locked_and_not_at_safepoint(); - // Loop until the allocation is satisfied, or unsatisfied after GC. - for (uint try_count = 1, gclocker_retry_count = 0; /* we'll return */; try_count += 1) { - uint gc_count_before; - - HeapWord* result = NULL; - if (!is_humongous(word_size)) { - result = attempt_allocation(word_size, &gc_count_before, &gclocker_retry_count); - } else { - result = attempt_allocation_humongous(word_size, &gc_count_before, &gclocker_retry_count); - } - if (result != NULL) { - return result; - } - - // Create the garbage collection operation... - VM_G1CollectForAllocation op(gc_count_before, word_size); - op.set_allocation_context(AllocationContext::current()); - - // ...and get the VM thread to execute it. - VMThread::execute(&op); - - if (op.prologue_succeeded() && op.pause_succeeded()) { - // If the operation was successful we'll return the result even - // if it is NULL. If the allocation attempt failed immediately - // after a Full GC, it's unlikely we'll be able to allocate now. - HeapWord* result = op.result(); - if (result != NULL && !is_humongous(word_size)) { - // Allocations that take place on VM operations do not do any - // card dirtying and we have to do it here. We only have to do - // this for non-humongous allocations, though. - dirty_young_block(result, word_size); - } - return result; - } else { - if (gclocker_retry_count > GCLockerRetryAllocationCount) { - return NULL; - } - assert(op.result() == NULL, - "the result should be NULL if the VM op did not succeed"); - } - - // Give a warning if we seem to be looping forever. - if ((QueuedAllocationWarningCount > 0) && - (try_count % QueuedAllocationWarningCount == 0)) { - log_warning(gc)("G1CollectedHeap::mem_allocate retries %d times", try_count); - } + if (is_humongous(word_size)) { + return attempt_allocation_humongous(word_size); } - - ShouldNotReachHere(); - return NULL; + return attempt_allocation(word_size); } HeapWord* G1CollectedHeap::attempt_allocation_slow(size_t word_size, - AllocationContext_t context, - uint* gc_count_before_ret, - uint* gclocker_retry_count_ret) { + AllocationContext_t context) { + ResourceMark rm; // For retrieving the thread names in log messages. + // Make sure you read the note in attempt_allocation_humongous(). assert_heap_not_locked_and_not_at_safepoint(); @@ -525,7 +477,7 @@ // fails to perform the allocation. b) is the only case when we'll // return NULL. HeapWord* result = NULL; - for (int try_count = 1; /* we'll return */; try_count += 1) { + for (uint try_count = 1, gclocker_retry_count = 0; /* we'll return */; try_count += 1) { bool should_try_gc; uint gc_count_before; @@ -536,30 +488,23 @@ return result; } - if (GCLocker::is_active_and_needs_gc()) { - if (g1_policy()->can_expand_young_list()) { - // No need for an ergo verbose message here, - // can_expand_young_list() does this when it returns true. - result = _allocator->attempt_allocation_force(word_size, context); - if (result != NULL) { - return result; - } - } - should_try_gc = false; - } else { - // The GCLocker may not be active but the GCLocker initiated - // GC may not yet have been performed (GCLocker::needs_gc() - // returns true). In this case we do not try this GC and - // wait until the GCLocker initiated GC is performed, and - // then retry the allocation. - if (GCLocker::needs_gc()) { - should_try_gc = false; - } else { - // Read the GC count while still holding the Heap_lock. - gc_count_before = total_collections(); - should_try_gc = true; + // If the GCLocker is active and we are bound for a GC, try expanding young gen. + // This is different to when only GCLocker::needs_gc() is set: try to avoid + // waiting because the GCLocker is active to not wait too long. + if (GCLocker::is_active_and_needs_gc() && g1_policy()->can_expand_young_list()) { + // No need for an ergo message here, can_expand_young_list() does this when + // it returns true. + result = _allocator->attempt_allocation_force(word_size, context); + if (result != NULL) { + return result; } } + // Only try a GC if the GCLocker does not signal the need for a GC. Wait until + // the GCLocker initiated GC has been performed and then retry. This includes + // the case when the GC Locker is not active but has not been performed. + should_try_gc = !GCLocker::needs_gc(); + // Read the GC count while still holding the Heap_lock. + gc_count_before = total_collections(); } if (should_try_gc) { @@ -568,28 +513,33 @@ GCCause::_g1_inc_collection_pause); if (result != NULL) { assert(succeeded, "only way to get back a non-NULL result"); + log_trace(gc, alloc)("%s: Successfully scheduled collection returning " PTR_FORMAT, + Thread::current()->name(), p2i(result)); return result; } if (succeeded) { - // If we get here we successfully scheduled a collection which - // failed to allocate. No point in trying to allocate - // further. We'll just return NULL. - MutexLockerEx x(Heap_lock); - *gc_count_before_ret = total_collections(); + // We successfully scheduled a collection which failed to allocate. No + // point in trying to allocate further. We'll just return NULL. + log_trace(gc, alloc)("%s: Successfully scheduled collection failing to allocate " + SIZE_FORMAT " words", Thread::current()->name(), word_size); return NULL; } + log_trace(gc, alloc)("%s: Unsuccessfully scheduled collection allocating " SIZE_FORMAT " words", + Thread::current()->name(), word_size); } else { - if (*gclocker_retry_count_ret > GCLockerRetryAllocationCount) { - MutexLockerEx x(Heap_lock); - *gc_count_before_ret = total_collections(); + // Failed to schedule a collection. + if (gclocker_retry_count > GCLockerRetryAllocationCount) { + log_warning(gc, alloc)("%s: Retried waiting for GCLocker too often allocating " + SIZE_FORMAT " words", Thread::current()->name(), word_size); return NULL; } + log_trace(gc, alloc)("%s: Stall until clear", Thread::current()->name()); // The GCLocker is either active or the GCLocker initiated // GC has not yet been performed. Stall until it is and // then retry the allocation. GCLocker::stall_until_clear(); - (*gclocker_retry_count_ret) += 1; + gclocker_retry_count += 1; } // We can reach here if we were unsuccessful in scheduling a @@ -600,6 +550,7 @@ // first attempt (without holding the Heap_lock) here and the // follow-on attempt will be at the start of the next loop // iteration (after taking the Heap_lock). + result = _allocator->attempt_allocation(word_size, context); if (result != NULL) { return result; @@ -608,8 +559,8 @@ // Give a warning if we seem to be looping forever. if ((QueuedAllocationWarningCount > 0) && (try_count % QueuedAllocationWarningCount == 0)) { - log_warning(gc)("G1CollectedHeap::attempt_allocation_slow() " - "retries %d times", try_count); + log_warning(gc, alloc)("%s: Retried allocation %u times for " SIZE_FORMAT " words", + Thread::current()->name(), try_count, word_size); } } @@ -830,9 +781,7 @@ } } -inline HeapWord* G1CollectedHeap::attempt_allocation(size_t word_size, - uint* gc_count_before_ret, - uint* gclocker_retry_count_ret) { +inline HeapWord* G1CollectedHeap::attempt_allocation(size_t word_size) { assert_heap_not_locked_and_not_at_safepoint(); assert(!is_humongous(word_size), "attempt_allocation() should not " "be called for humongous allocation requests"); @@ -841,10 +790,7 @@ HeapWord* result = _allocator->attempt_allocation(word_size, context); if (result == NULL) { - result = attempt_allocation_slow(word_size, - context, - gc_count_before_ret, - gclocker_retry_count_ret); + result = attempt_allocation_slow(word_size, context); } assert_heap_not_locked(); if (result != NULL) { @@ -925,9 +871,9 @@ decrease_used(size_used); } -HeapWord* G1CollectedHeap::attempt_allocation_humongous(size_t word_size, - uint* gc_count_before_ret, - uint* gclocker_retry_count_ret) { +HeapWord* G1CollectedHeap::attempt_allocation_humongous(size_t word_size) { + ResourceMark rm; // For retrieving the thread names in log messages. + // The structure of this method has a lot of similarities to // attempt_allocation_slow(). The reason these two were not merged // into a single one is that such a method would require several "if @@ -958,10 +904,11 @@ // fails to perform the allocation. b) is the only case when we'll // return NULL. HeapWord* result = NULL; - for (int try_count = 1; /* we'll return */; try_count += 1) { + for (uint try_count = 1, gclocker_retry_count = 0; /* we'll return */; try_count += 1) { bool should_try_gc; uint gc_count_before; + { MutexLockerEx x(Heap_lock); @@ -975,69 +922,63 @@ return result; } - if (GCLocker::is_active_and_needs_gc()) { - should_try_gc = false; - } else { - // The GCLocker may not be active but the GCLocker initiated - // GC may not yet have been performed (GCLocker::needs_gc() - // returns true). In this case we do not try this GC and - // wait until the GCLocker initiated GC is performed, and - // then retry the allocation. - if (GCLocker::needs_gc()) { - should_try_gc = false; - } else { - // Read the GC count while still holding the Heap_lock. - gc_count_before = total_collections(); - should_try_gc = true; - } - } + // Only try a GC if the GCLocker does not signal the need for a GC. Wait until + // the GCLocker initiated GC has been performed and then retry. This includes + // the case when the GC Locker is not active but has not been performed. + should_try_gc = !GCLocker::needs_gc(); + // Read the GC count while still holding the Heap_lock. + gc_count_before = total_collections(); } if (should_try_gc) { - // If we failed to allocate the humongous object, we should try to - // do a collection pause (if we're allowed) in case it reclaims - // enough space for the allocation to succeed after the pause. - bool succeeded; result = do_collection_pause(word_size, gc_count_before, &succeeded, GCCause::_g1_humongous_allocation); if (result != NULL) { assert(succeeded, "only way to get back a non-NULL result"); + log_trace(gc, alloc)("%s: Successfully scheduled collection returning " PTR_FORMAT, + Thread::current()->name(), p2i(result)); return result; } if (succeeded) { - // If we get here we successfully scheduled a collection which - // failed to allocate. No point in trying to allocate - // further. We'll just return NULL. - MutexLockerEx x(Heap_lock); - *gc_count_before_ret = total_collections(); + // We successfully scheduled a collection which failed to allocate. No + // point in trying to allocate further. We'll just return NULL. + log_trace(gc, alloc)("%s: Successfully scheduled collection failing to allocate " + SIZE_FORMAT " words", Thread::current()->name(), word_size); return NULL; } + log_trace(gc, alloc)("%s: Unsuccessfully scheduled collection allocating " SIZE_FORMAT "", + Thread::current()->name(), word_size); } else { - if (*gclocker_retry_count_ret > GCLockerRetryAllocationCount) { - MutexLockerEx x(Heap_lock); - *gc_count_before_ret = total_collections(); + // Failed to schedule a collection. + if (gclocker_retry_count > GCLockerRetryAllocationCount) { + log_warning(gc, alloc)("%s: Retried waiting for GCLocker too often allocating " + SIZE_FORMAT " words", Thread::current()->name(), word_size); return NULL; } + log_trace(gc, alloc)("%s: Stall until clear", Thread::current()->name()); // The GCLocker is either active or the GCLocker initiated // GC has not yet been performed. Stall until it is and // then retry the allocation. GCLocker::stall_until_clear(); - (*gclocker_retry_count_ret) += 1; + gclocker_retry_count += 1; } + // We can reach here if we were unsuccessful in scheduling a // collection (because another thread beat us to it) or if we were // stalled due to the GC locker. In either can we should retry the // allocation attempt in case another thread successfully - // performed a collection and reclaimed enough space. Give a - // warning if we seem to be looping forever. + // performed a collection and reclaimed enough space. + // Humongous object allocation always needs a lock, so we wait for the retry + // in the next iteration of the loop, unlike for the regular iteration case. + // Give a warning if we seem to be looping forever. if ((QueuedAllocationWarningCount > 0) && (try_count % QueuedAllocationWarningCount == 0)) { - log_warning(gc)("G1CollectedHeap::attempt_allocation_humongous() " - "retries %d times", try_count); + log_warning(gc, alloc)("%s: Retried allocation %u times for " SIZE_FORMAT " words", + Thread::current()->name(), try_count, word_size); } } @@ -1339,7 +1280,6 @@ context, expect_null_mutator_alloc_region); if (result != NULL) { - assert(*gc_succeeded, "sanity"); return result; } @@ -1349,7 +1289,6 @@ // do something smarter than full collection to satisfy a failed alloc.) result = expand_and_allocate(word_size, context); if (result != NULL) { - assert(*gc_succeeded, "sanity"); return result; } @@ -1401,7 +1340,6 @@ succeeded); if (result != NULL) { - assert(*succeeded, "sanity"); return result; } @@ -1412,7 +1350,6 @@ // space available is large enough for the allocation, then a more // complete compaction phase than we've tried so far might be // appropriate. - assert(*succeeded, "sanity"); return NULL; } @@ -2147,7 +2084,7 @@ // This notify_all() will ensure that a thread that called // System.gc() with (with ExplicitGCInvokesConcurrent set or not) // and it's waiting for a full GC to finish will be woken up. It is - // waiting in VM_G1IncCollectionPause::doit_epilogue(). + // waiting in VM_G1CollectForAllocation::doit_epilogue(). FullGCCount_lock->notify_all(); } @@ -2175,13 +2112,12 @@ // Schedule an initial-mark evacuation pause that will start a // concurrent cycle. We're setting word_size to 0 which means that // we are not requesting a post-GC allocation. - VM_G1IncCollectionPause op(gc_count_before, - 0, /* word_size */ - true, /* should_initiate_conc_mark */ - g1_policy()->max_pause_time_ms(), - cause); - op.set_allocation_context(AllocationContext::current()); - + VM_G1CollectForAllocation op(0, /* word_size */ + gc_count_before, + cause, + true, /* should_initiate_conc_mark */ + g1_policy()->max_pause_time_ms(), + AllocationContext::current()); VMThread::execute(&op); if (!op.pause_succeeded()) { if (old_marking_count_before == _old_marking_cycles_started) { @@ -2204,11 +2140,12 @@ // Schedule a standard evacuation pause. We're setting word_size // to 0 which means that we are not requesting a post-GC allocation. - VM_G1IncCollectionPause op(gc_count_before, - 0, /* word_size */ - false, /* should_initiate_conc_mark */ - g1_policy()->max_pause_time_ms(), - cause); + VM_G1CollectForAllocation op(0, /* word_size */ + gc_count_before, + cause, + false, /* should_initiate_conc_mark */ + g1_policy()->max_pause_time_ms(), + AllocationContext::current()); VMThread::execute(&op); } else { // Schedule a Full GC. @@ -2619,13 +2556,12 @@ bool* succeeded, GCCause::Cause gc_cause) { assert_heap_not_locked_and_not_at_safepoint(); - VM_G1IncCollectionPause op(gc_count_before, - word_size, - false, /* should_initiate_conc_mark */ - g1_policy()->max_pause_time_ms(), - gc_cause); - - op.set_allocation_context(AllocationContext::current()); + VM_G1CollectForAllocation op(word_size, + gc_count_before, + gc_cause, + false, /* should_initiate_conc_mark */ + g1_policy()->max_pause_time_ms(), + AllocationContext::current()); VMThread::execute(&op); HeapWord* result = op.result();