6330863: vm/gc/InfiniteList.java fails intermittently due to timeout
In some cases, allocate from the old gen before doing a full gc Reviewed-by: stefank, jmasa
This commit is contained in:
parent
6827f384c9
commit
5f0143a774
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -418,25 +418,17 @@ HeapWord* ParallelScavengeHeap::mem_allocate(
|
|||||||
gc_count = Universe::heap()->total_collections();
|
gc_count = Universe::heap()->total_collections();
|
||||||
|
|
||||||
result = young_gen()->allocate(size);
|
result = young_gen()->allocate(size);
|
||||||
|
|
||||||
// (1) If the requested object is too large to easily fit in the
|
|
||||||
// young_gen, or
|
|
||||||
// (2) If GC is locked out via GCLocker, young gen is full and
|
|
||||||
// the need for a GC already signalled to GCLocker (done
|
|
||||||
// at a safepoint),
|
|
||||||
// ... then, rather than force a safepoint and (a potentially futile)
|
|
||||||
// collection (attempt) for each allocation, try allocation directly
|
|
||||||
// in old_gen. For case (2) above, we may in the future allow
|
|
||||||
// TLAB allocation directly in the old gen.
|
|
||||||
if (result != NULL) {
|
if (result != NULL) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
if (size >= (young_gen()->eden_space()->capacity_in_words(Thread::current()) / 2)) {
|
|
||||||
result = old_gen()->allocate(size);
|
// If certain conditions hold, try allocating from the old gen.
|
||||||
if (result != NULL) {
|
result = mem_allocate_old_gen(size);
|
||||||
return result;
|
if (result != NULL) {
|
||||||
}
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Failed to allocate without a gc.
|
||||||
if (GC_locker::is_active_and_needs_gc()) {
|
if (GC_locker::is_active_and_needs_gc()) {
|
||||||
// If this thread is not in a jni critical section, we stall
|
// If this thread is not in a jni critical section, we stall
|
||||||
// the requestor until the critical section has cleared and
|
// the requestor until the critical section has cleared and
|
||||||
@ -460,7 +452,6 @@ HeapWord* ParallelScavengeHeap::mem_allocate(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (result == NULL) {
|
if (result == NULL) {
|
||||||
|
|
||||||
// Generate a VM operation
|
// Generate a VM operation
|
||||||
VM_ParallelGCFailedAllocation op(size, gc_count);
|
VM_ParallelGCFailedAllocation op(size, gc_count);
|
||||||
VMThread::execute(&op);
|
VMThread::execute(&op);
|
||||||
@ -523,6 +514,42 @@ HeapWord* ParallelScavengeHeap::mem_allocate(
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A "death march" is a series of ultra-slow allocations in which a full gc is
|
||||||
|
// done before each allocation, and after the full gc the allocation still
|
||||||
|
// cannot be satisfied from the young gen. This routine detects that condition;
|
||||||
|
// it should be called after a full gc has been done and the allocation
|
||||||
|
// attempted from the young gen. The parameter 'addr' should be the result of
|
||||||
|
// that young gen allocation attempt.
|
||||||
|
void
|
||||||
|
ParallelScavengeHeap::death_march_check(HeapWord* const addr, size_t size) {
|
||||||
|
if (addr != NULL) {
|
||||||
|
_death_march_count = 0; // death march has ended
|
||||||
|
} else if (_death_march_count == 0) {
|
||||||
|
if (should_alloc_in_eden(size)) {
|
||||||
|
_death_march_count = 1; // death march has started
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HeapWord* ParallelScavengeHeap::mem_allocate_old_gen(size_t size) {
|
||||||
|
if (!should_alloc_in_eden(size) || GC_locker::is_active_and_needs_gc()) {
|
||||||
|
// Size is too big for eden, or gc is locked out.
|
||||||
|
return old_gen()->allocate(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If a "death march" is in progress, allocate from the old gen a limited
|
||||||
|
// number of times before doing a GC.
|
||||||
|
if (_death_march_count > 0) {
|
||||||
|
if (_death_march_count < 64) {
|
||||||
|
++_death_march_count;
|
||||||
|
return old_gen()->allocate(size);
|
||||||
|
} else {
|
||||||
|
_death_march_count = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// Failed allocation policy. Must be called from the VM thread, and
|
// Failed allocation policy. Must be called from the VM thread, and
|
||||||
// only at a safepoint! Note that this method has policy for allocation
|
// only at a safepoint! Note that this method has policy for allocation
|
||||||
// flow, and NOT collection policy. So we do not check for gc collection
|
// flow, and NOT collection policy. So we do not check for gc collection
|
||||||
@ -535,27 +562,22 @@ HeapWord* ParallelScavengeHeap::failed_mem_allocate(size_t size) {
|
|||||||
assert(!Universe::heap()->is_gc_active(), "not reentrant");
|
assert(!Universe::heap()->is_gc_active(), "not reentrant");
|
||||||
assert(!Heap_lock->owned_by_self(), "this thread should not own the Heap_lock");
|
assert(!Heap_lock->owned_by_self(), "this thread should not own the Heap_lock");
|
||||||
|
|
||||||
size_t mark_sweep_invocation_count = total_invocations();
|
// We assume that allocation in eden will fail unless we collect.
|
||||||
|
|
||||||
// We assume (and assert!) that an allocation at this point will fail
|
|
||||||
// unless we collect.
|
|
||||||
|
|
||||||
// First level allocation failure, scavenge and allocate in young gen.
|
// First level allocation failure, scavenge and allocate in young gen.
|
||||||
GCCauseSetter gccs(this, GCCause::_allocation_failure);
|
GCCauseSetter gccs(this, GCCause::_allocation_failure);
|
||||||
PSScavenge::invoke();
|
const bool invoked_full_gc = PSScavenge::invoke();
|
||||||
HeapWord* result = young_gen()->allocate(size);
|
HeapWord* result = young_gen()->allocate(size);
|
||||||
|
|
||||||
// Second level allocation failure.
|
// Second level allocation failure.
|
||||||
// Mark sweep and allocate in young generation.
|
// Mark sweep and allocate in young generation.
|
||||||
if (result == NULL) {
|
if (result == NULL && !invoked_full_gc) {
|
||||||
// There is some chance the scavenge method decided to invoke mark_sweep.
|
invoke_full_gc(false);
|
||||||
// Don't mark sweep twice if so.
|
result = young_gen()->allocate(size);
|
||||||
if (mark_sweep_invocation_count == total_invocations()) {
|
|
||||||
invoke_full_gc(false);
|
|
||||||
result = young_gen()->allocate(size);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
death_march_check(result, size);
|
||||||
|
|
||||||
// Third level allocation failure.
|
// Third level allocation failure.
|
||||||
// After mark sweep and young generation allocation failure,
|
// After mark sweep and young generation allocation failure,
|
||||||
// allocate in old generation.
|
// allocate in old generation.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -64,6 +64,7 @@ class ParallelScavengeHeap : public CollectedHeap {
|
|||||||
// Collection of generations that are adjacent in the
|
// Collection of generations that are adjacent in the
|
||||||
// space reserved for the heap.
|
// space reserved for the heap.
|
||||||
AdjoiningGenerations* _gens;
|
AdjoiningGenerations* _gens;
|
||||||
|
unsigned int _death_march_count;
|
||||||
|
|
||||||
static GCTaskManager* _gc_task_manager; // The task manager.
|
static GCTaskManager* _gc_task_manager; // The task manager.
|
||||||
|
|
||||||
@ -71,8 +72,13 @@ class ParallelScavengeHeap : public CollectedHeap {
|
|||||||
static inline size_t total_invocations();
|
static inline size_t total_invocations();
|
||||||
HeapWord* allocate_new_tlab(size_t size);
|
HeapWord* allocate_new_tlab(size_t size);
|
||||||
|
|
||||||
|
inline bool should_alloc_in_eden(size_t size) const;
|
||||||
|
inline void death_march_check(HeapWord* const result, size_t size);
|
||||||
|
HeapWord* mem_allocate_old_gen(size_t size);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ParallelScavengeHeap() : CollectedHeap() {
|
ParallelScavengeHeap() : CollectedHeap() {
|
||||||
|
_death_march_count = 0;
|
||||||
set_alignment(_perm_gen_alignment, intra_heap_alignment());
|
set_alignment(_perm_gen_alignment, intra_heap_alignment());
|
||||||
set_alignment(_young_gen_alignment, intra_heap_alignment());
|
set_alignment(_young_gen_alignment, intra_heap_alignment());
|
||||||
set_alignment(_old_gen_alignment, intra_heap_alignment());
|
set_alignment(_old_gen_alignment, intra_heap_alignment());
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -36,6 +36,12 @@ inline size_t ParallelScavengeHeap::total_invocations()
|
|||||||
PSMarkSweep::total_invocations();
|
PSMarkSweep::total_invocations();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool ParallelScavengeHeap::should_alloc_in_eden(const size_t size) const
|
||||||
|
{
|
||||||
|
const size_t eden_size = young_gen()->eden_space()->capacity_in_words();
|
||||||
|
return size < eden_size / 2;
|
||||||
|
}
|
||||||
|
|
||||||
inline void ParallelScavengeHeap::invoke_scavenge()
|
inline void ParallelScavengeHeap::invoke_scavenge()
|
||||||
{
|
{
|
||||||
PSScavenge::invoke();
|
PSScavenge::invoke();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user