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 ----