src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp
Print this page
@@ -588,15 +588,10 @@
// 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.
@@ -1744,20 +1739,29 @@
_retired = true;
}
};
class G1ParScanThreadState : public StackObj {
+private:
+ enum GCAllocPriority {
+ GCAllocPriority1,
+ GCAllocPriority2,
+ GCAllocPriorityCount
+ };
+
+ int buf_idx(int purpose, int priority) {
+ return purpose*GCAllocPriorityCount + priority;
+ }
+
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];
+ G1ParGCAllocBuffer* _alloc_buffers[GCAllocPurposeCount*GCAllocPriorityCount];
ageTable _age_table;
size_t _alloc_buffer_waste;
size_t _undo_waste;
@@ -1812,17 +1816,22 @@
public:
G1ParScanThreadState(G1CollectedHeap* g1h, uint queue_num);
~G1ParScanThreadState() {
FREE_C_HEAP_ARRAY(size_t, _surviving_young_words_base, mtGC);
+ for (int ap = 0; ap < GCAllocPurposeCount; ++ap) {
+ for (int pr = 0; pr < GCAllocPriorityCount; ++pr) {
+ delete alloc_buffer(GCAllocPurpose(ap), GCAllocPriority(pr));
+ }
+ }
}
RefToScanQueue* refs() { return _refs; }
ageTable* age_table() { return &_age_table; }
- G1ParGCAllocBuffer* alloc_buffer(GCAllocPurpose purpose) {
- return _alloc_buffers[purpose];
+ G1ParGCAllocBuffer* alloc_buffer(GCAllocPurpose purpose, GCAllocPriority priority) {
+ return _alloc_buffers[buf_idx(purpose, priority)];
}
size_t alloc_buffer_waste() const { return _alloc_buffer_waste; }
size_t undo_waste() const { return _undo_waste; }
@@ -1847,44 +1856,57 @@
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 */);
+ G1ParGCAllocBuffer* alloc_buf1 = alloc_buffer(purpose, GCAllocPriority1);
+ G1ParGCAllocBuffer* alloc_buf2 = alloc_buffer(purpose, GCAllocPriority2);
+
+ add_to_alloc_buffer_waste(alloc_buf1->words_remaining());
+ alloc_buf1->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);
+ alloc_buf1->set_word_size(gclab_word_size);
+ alloc_buf1->set_buf(buf);
- obj = alloc_buf->allocate(word_sz);
+ obj = alloc_buf1->allocate(word_sz);
assert(obj != NULL, "buffer was definitely big enough...");
+
+ // Swap buffers in order to preserve the priority order
+ _alloc_buffers[buf_idx(purpose, GCAllocPriority1)] = alloc_buf2;
+ _alloc_buffers[buf_idx(purpose, GCAllocPriority2)] = alloc_buf1;
} else {
obj = _g1h->par_allocate_during_gc(purpose, word_sz);
}
return obj;
}
HeapWord* allocate(GCAllocPurpose purpose, size_t word_sz) {
- HeapWord* obj = alloc_buffer(purpose)->allocate(word_sz);
+ HeapWord* obj;
+ for (int pr = 0; pr < GCAllocPriorityCount; ++pr) {
+ obj = alloc_buffer(purpose, (GCAllocPriority)pr)->allocate(word_sz);
if (obj != NULL) return obj;
+ }
+ // Otherwise.
return allocate_slow(purpose, word_sz);
}
void undo_allocation(GCAllocPurpose purpose, HeapWord* obj, size_t word_sz) {
- if (alloc_buffer(purpose)->contains(obj)) {
- assert(alloc_buffer(purpose)->contains(obj + word_sz - 1),
+ for (int pr = 0; pr < GCAllocPriorityCount; ++pr) {
+ if (alloc_buffer(purpose, (GCAllocPriority)pr)->contains(obj)) {
+ assert(alloc_buffer(purpose, (GCAllocPriority)pr)->contains(obj + word_sz - 1),
"should contain whole object");
- alloc_buffer(purpose)->undo_allocation(obj, word_sz);
- } else {
+ alloc_buffer(purpose, (GCAllocPriority)pr)->undo_allocation(obj, word_sz);
+ return;
+ }
+ }
+
CollectedHeap::fill_with_object(obj, word_sz);
add_to_undo_waste(word_sz);
}
- }
void set_evac_failure_closure(OopsInHeapRegionClosure* evac_failure_cl) {
_evac_failure_cl = evac_failure_cl;
}
OopsInHeapRegionClosure* evac_failure_closure() {
@@ -1937,17 +1959,20 @@
return _surviving_young_words;
}
void retire_alloc_buffers() {
for (int ap = 0; ap < GCAllocPurposeCount; ++ap) {
- size_t waste = _alloc_buffers[ap]->words_remaining();
+ for (int pr = 0; pr < GCAllocPriorityCount; ++pr) {
+ G1ParGCAllocBuffer* buffer = alloc_buffer((GCAllocPurpose)ap, (GCAllocPriority)pr);
+ size_t waste = buffer->words_remaining();
add_to_alloc_buffer_waste(waste);
- _alloc_buffers[ap]->flush_stats_and_retire(_g1h->stats_for_purpose((GCAllocPurpose)ap),
+ buffer->flush_stats_and_retire(_g1h->stats_for_purpose((GCAllocPurpose)ap),
true /* end_of_gc */,
false /* retain */);
}
}
+ }
template <class T> void deal_with_reference(T* ref_to_scan) {
if (has_partial_array_mask(ref_to_scan)) {
_partial_scan_cl->do_oop_nv(ref_to_scan);
} else {
@@ -1967,10 +1992,9 @@
} else {
deal_with_reference((oop*)ref);
}
}
-public:
void trim_queue();
};
#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1COLLECTEDHEAP_HPP