src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp
Print this page
*** 1,7 ****
/*
! * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
--- 1,7 ----
/*
! * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*** 68,80 ****
typedef int RegionIdx_t; // needs to hold [ 0..max_regions() )
typedef int CardIdx_t; // needs to hold [ 0..CardsPerRegion )
enum GCAllocPurpose {
! GCAllocForTenured,
! GCAllocForSurvived,
! GCAllocPurposeCount
};
class YoungList : public CHeapObj<mtGC> {
private:
G1CollectedHeap* _g1h;
--- 68,81 ----
typedef int RegionIdx_t; // needs to hold [ 0..max_regions() )
typedef int CardIdx_t; // needs to hold [ 0..CardsPerRegion )
enum GCAllocPurpose {
! GCAllocPurposeStart = 0,
! GCAllocForTenured = GCAllocPurposeStart,
! GCAllocForSurvived = GCAllocPurposeStart + 1,
! GCAllocPurposeCount = GCAllocPurposeStart + 2
};
class YoungList : public CHeapObj<mtGC> {
private:
G1CollectedHeap* _g1h;
*** 592,606 ****
// allocation region, either by picking one or expanding the
// heap, and then allocate a block of the given size. The block
// may not be a humongous - it must fit into a single heap region.
HeapWord* par_allocate_during_gc(GCAllocPurpose purpose, size_t word_size);
- HeapWord* allocate_during_gc_slow(GCAllocPurpose purpose,
- HeapRegion* alloc_region,
- bool par,
- size_t word_size);
-
// Ensure that no further allocations can happen in "r", bearing in mind
// that parallel threads might be attempting allocations.
void par_allocate_remaining_space(HeapRegion* r);
// Allocation attempt during GC for a survivor object / PLAB.
--- 593,602 ----
*** 1747,1767 ****
ParGCAllocBuffer::retire(end_of_gc, retain);
_retired = true;
}
};
class G1ParScanThreadState : public StackObj {
protected:
G1CollectedHeap* _g1h;
RefToScanQueue* _refs;
DirtyCardQueue _dcq;
CardTableModRefBS* _ct_bs;
G1RemSet* _g1_rem;
! G1ParGCAllocBuffer _surviving_alloc_buffer;
! G1ParGCAllocBuffer _tenured_alloc_buffer;
! G1ParGCAllocBuffer* _alloc_buffers[GCAllocPurposeCount];
ageTable _age_table;
size_t _alloc_buffer_waste;
size_t _undo_waste;
--- 1743,1852 ----
ParGCAllocBuffer::retire(end_of_gc, retain);
_retired = true;
}
};
+ class G1MultiParGCAllocBuffer {
+ protected:
+ enum GCAllocPriority {
+ GCAllocPriorityStart = 0,
+ GCAllocPriority1 = GCAllocPriorityStart,
+ GCAllocPriority2 = GCAllocPriorityStart + 1,
+ GCAllocPriorityCount = GCAllocPriorityStart + 2
+ };
+ G1ParGCAllocBuffer* _priority_buffer[GCAllocPriorityCount];
+
+ public:
+ G1MultiParGCAllocBuffer(size_t gclab_word_size) {
+ for (int pr = GCAllocPriorityStart; pr < GCAllocPriorityCount; ++pr) {
+ _priority_buffer[pr] = new G1ParGCAllocBuffer(gclab_word_size);
+ }
+ }
+
+ ~G1MultiParGCAllocBuffer() {
+ for (int pr = GCAllocPriorityStart; pr < GCAllocPriorityCount; ++pr) {
+ delete _priority_buffer[pr];
+ }
+ }
+
+ HeapWord* allocate(size_t word_sz) {
+ HeapWord* obj;
+ for (int pr = GCAllocPriorityStart; pr < GCAllocPriorityCount; ++pr) {
+ obj = _priority_buffer[pr]->allocate(word_sz);
+ if (obj != NULL) return obj;
+ }
+ return obj;
+ }
+
+ bool contains(void* addr) {
+ for (int pr = GCAllocPriorityStart; pr < GCAllocPriorityCount; ++pr) {
+ if (_priority_buffer[pr]->contains(addr)) return true;
+ }
+ return false;
+ }
+
+ void undo_allocation(HeapWord* obj, size_t word_sz) {
+ bool finish_undo;
+ for (int pr = GCAllocPriorityStart; pr < GCAllocPriorityCount; ++pr) {
+ if (_priority_buffer[pr]->contains(addr)) {
+ _priority_buffer[pr]->undo_allocation(obj, word_sz);
+ finish_undo = true;
+ }
+ }
+ if (finish_undo != true) ShouldNotReachHere();
+ }
+
+ size_t words_remaining() {
+ size_t result=0;
+ for (int pr = GCAllocPriorityStart; pr < GCAllocPriorityCount; ++pr) {
+ result += _priority_buffer[pr]->words_remaining();
+ }
+ return result;
+ }
+
+ size_t words_remaining_in_retired() {
+ G1ParGCAllocBuffer* retired = _priority_buffer[GCAllocPriority1];
+ return retired->words_remaining();
+ }
+
+ void flush_stats_and_retire(PLABStats* stats, bool end_of_gc, bool retain) {
+ for (int pr = GCAllocPriorityStart; pr < GCAllocPriorityCount; ++pr) {
+ _priority_buffer[pr]->flush_stats_and_retire(stats, end_of_gc, retain);
+ }
+ }
+
+ void retire_and_set_buf(bool end_of_gc, bool retain, HeapWord* buf, size_t word_sz) {
+ G1ParGCAllocBuffer* retired_and_set = _priority_buffer[GCAllocPriority1];
+ retired_and_set->retire(end_of_gc, retain);
+ retired_and_set->set_buf(buf);
+ retired_and_set->set_word_size(word_sz);
+ adjust_priority_order();
+ }
+
+ private:
+ void adjust_priority_order() {
+ G1ParGCAllocBuffer* retired_and_set = _priority_buffer[GCAllocPriority1];
+
+ int last = GCAllocPriorityCount - 1;
+ for (int pr = GCAllocPriorityStart; pr < last; ++pr) {
+ _priority_buffer[pr] = _priority_buffer[pr + 1];
+ }
+ _priority_buffer[last] = retired_and_set;
+ }
+ };
+
class G1ParScanThreadState : public StackObj {
protected:
G1CollectedHeap* _g1h;
RefToScanQueue* _refs;
DirtyCardQueue _dcq;
CardTableModRefBS* _ct_bs;
G1RemSet* _g1_rem;
! G1MultiParGCAllocBuffer _surviving_alloc_buffer;
! G1MultiParGCAllocBuffer _tenured_alloc_buffer;
! G1MultiParGCAllocBuffer* _alloc_buffers[GCAllocPurposeCount];
ageTable _age_table;
size_t _alloc_buffer_waste;
size_t _undo_waste;
*** 1821,1831 ****
}
RefToScanQueue* refs() { return _refs; }
ageTable* age_table() { return &_age_table; }
! G1ParGCAllocBuffer* alloc_buffer(GCAllocPurpose purpose) {
return _alloc_buffers[purpose];
}
size_t alloc_buffer_waste() const { return _alloc_buffer_waste; }
size_t undo_waste() const { return _undo_waste; }
--- 1906,1916 ----
}
RefToScanQueue* refs() { return _refs; }
ageTable* age_table() { return &_age_table; }
! G1MultiParGCAllocBuffer* alloc_buffer(GCAllocPurpose purpose) {
return _alloc_buffers[purpose];
}
size_t alloc_buffer_waste() const { return _alloc_buffer_waste; }
size_t undo_waste() const { return _undo_waste; }
*** 1851,1869 ****
HeapWord* allocate_slow(GCAllocPurpose purpose, size_t word_sz) {
HeapWord* obj = NULL;
size_t gclab_word_size = _g1h->desired_plab_sz(purpose);
if (word_sz * 100 < gclab_word_size * ParallelGCBufferWastePct) {
! G1ParGCAllocBuffer* alloc_buf = alloc_buffer(purpose);
! add_to_alloc_buffer_waste(alloc_buf->words_remaining());
! alloc_buf->retire(false /* end_of_gc */, false /* retain */);
HeapWord* buf = _g1h->par_allocate_during_gc(purpose, gclab_word_size);
if (buf == NULL) return NULL; // Let caller handle allocation failure.
! // Otherwise.
! alloc_buf->set_word_size(gclab_word_size);
! alloc_buf->set_buf(buf);
obj = alloc_buf->allocate(word_sz);
assert(obj != NULL, "buffer was definitely big enough...");
} else {
obj = _g1h->par_allocate_during_gc(purpose, word_sz);
--- 1936,1952 ----
HeapWord* allocate_slow(GCAllocPurpose purpose, size_t word_sz) {
HeapWord* obj = NULL;
size_t gclab_word_size = _g1h->desired_plab_sz(purpose);
if (word_sz * 100 < gclab_word_size * ParallelGCBufferWastePct) {
! G1MultiParGCAllocBuffer* alloc_buf = alloc_buffer(purpose);
! add_to_alloc_buffer_waste(alloc_buf->words_remaining_in_retired());
HeapWord* buf = _g1h->par_allocate_during_gc(purpose, gclab_word_size);
if (buf == NULL) return NULL; // Let caller handle allocation failure.
! alloc_buf->retire_and_set_buf(false /* end_of_gc */, false /* retain */,
! buf, gclab_word_size);
obj = alloc_buf->allocate(word_sz);
assert(obj != NULL, "buffer was definitely big enough...");
} else {
obj = _g1h->par_allocate_during_gc(purpose, word_sz);
*** 1971,1980 ****
} else {
deal_with_reference((oop*)ref);
}
}
- public:
void trim_queue();
};
#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1COLLECTEDHEAP_HPP
--- 2054,2062 ----