8074546: Rename and clean up the ParGCAllocBuffer class
Summary: Rename ParGCAllocBuffer to PLAB and rename affected files.
Reviewed-by: tschatzl, kbarrett
--- a/hotspot/src/share/vm/gc_implementation/g1/g1Allocator.cpp Tue Apr 21 10:29:35 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1Allocator.cpp Wed Apr 15 11:42:20 2015 -0400
@@ -110,15 +110,15 @@
_retained_old_gc_alloc_region = NULL;
}
-G1ParGCAllocBuffer::G1ParGCAllocBuffer(size_t gclab_word_size) :
- ParGCAllocBuffer(gclab_word_size), _retired(true) { }
+G1PLAB::G1PLAB(size_t gclab_word_size) :
+ PLAB(gclab_word_size), _retired(true) { }
HeapWord* G1ParGCAllocator::allocate_direct_or_new_plab(InCSetState dest,
size_t word_sz,
AllocationContext_t context) {
size_t gclab_word_size = _g1h->desired_plab_sz(dest);
if (word_sz * 100 < gclab_word_size * ParallelGCBufferWastePct) {
- G1ParGCAllocBuffer* alloc_buf = alloc_buffer(dest, context);
+ G1PLAB* alloc_buf = alloc_buffer(dest, context);
add_to_alloc_buffer_waste(alloc_buf->words_remaining());
alloc_buf->retire();
@@ -151,7 +151,7 @@
void G1DefaultParGCAllocator::retire_alloc_buffers() {
for (uint state = 0; state < InCSetState::Num; state++) {
- G1ParGCAllocBuffer* const buf = _alloc_buffers[state];
+ G1PLAB* const buf = _alloc_buffers[state];
if (buf != NULL) {
add_to_alloc_buffer_waste(buf->words_remaining());
buf->flush_and_retire_stats(_g1h->alloc_buffer_stats(state));
--- a/hotspot/src/share/vm/gc_implementation/g1/g1Allocator.hpp Tue Apr 21 10:29:35 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1Allocator.hpp Wed Apr 15 11:42:20 2015 -0400
@@ -28,7 +28,7 @@
#include "gc_implementation/g1/g1AllocationContext.hpp"
#include "gc_implementation/g1/g1AllocRegion.hpp"
#include "gc_implementation/g1/g1InCSetState.hpp"
-#include "gc_implementation/shared/parGCAllocBuffer.hpp"
+#include "gc_implementation/shared/plab.hpp"
#include "gc_interface/collectedHeap.hpp"
class EvacuationInfo;
@@ -147,18 +147,18 @@
}
};
-class G1ParGCAllocBuffer: public ParGCAllocBuffer {
+class G1PLAB: public PLAB {
private:
bool _retired;
public:
- G1ParGCAllocBuffer(size_t gclab_word_size);
- virtual ~G1ParGCAllocBuffer() {
+ G1PLAB(size_t gclab_word_size);
+ virtual ~G1PLAB() {
guarantee(_retired, "Allocation buffer has not been retired");
}
virtual void set_buf(HeapWord* buf) {
- ParGCAllocBuffer::set_buf(buf);
+ PLAB::set_buf(buf);
_retired = false;
}
@@ -166,7 +166,7 @@
if (_retired) {
return;
}
- ParGCAllocBuffer::retire();
+ PLAB::retire();
_retired = true;
}
};
@@ -190,7 +190,7 @@
void add_to_undo_waste(size_t waste) { _undo_waste += waste; }
virtual void retire_alloc_buffers() = 0;
- virtual G1ParGCAllocBuffer* alloc_buffer(InCSetState dest, AllocationContext_t context) = 0;
+ virtual G1PLAB* alloc_buffer(InCSetState dest, AllocationContext_t context) = 0;
// Calculate the survivor space object alignment in bytes. Returns that or 0 if
// there are no restrictions on survivor alignment.
@@ -229,7 +229,7 @@
HeapWord* plab_allocate(InCSetState dest,
size_t word_sz,
AllocationContext_t context) {
- G1ParGCAllocBuffer* buffer = alloc_buffer(dest, context);
+ G1PLAB* buffer = alloc_buffer(dest, context);
if (_survivor_alignment_bytes == 0) {
return buffer->allocate(word_sz);
} else {
@@ -259,14 +259,14 @@
};
class G1DefaultParGCAllocator : public G1ParGCAllocator {
- G1ParGCAllocBuffer _surviving_alloc_buffer;
- G1ParGCAllocBuffer _tenured_alloc_buffer;
- G1ParGCAllocBuffer* _alloc_buffers[InCSetState::Num];
+ G1PLAB _surviving_alloc_buffer;
+ G1PLAB _tenured_alloc_buffer;
+ G1PLAB* _alloc_buffers[InCSetState::Num];
public:
G1DefaultParGCAllocator(G1CollectedHeap* g1h);
- virtual G1ParGCAllocBuffer* alloc_buffer(InCSetState dest, AllocationContext_t context) {
+ virtual G1PLAB* alloc_buffer(InCSetState dest, AllocationContext_t context) {
assert(dest.is_valid(),
err_msg("Allocation buffer index out-of-bounds: " CSETSTATE_FORMAT, dest.value()));
assert(_alloc_buffers[dest.value()] != NULL,
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Tue Apr 21 10:29:35 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Wed Apr 15 11:42:20 2015 -0400
@@ -39,7 +39,6 @@
#include "gc_implementation/g1/heapRegionManager.hpp"
#include "gc_implementation/g1/heapRegionSet.hpp"
#include "gc_implementation/shared/hSpaceCounters.hpp"
-#include "gc_implementation/shared/parGCAllocBuffer.hpp"
#include "gc_interface/collectedHeap.hpp"
#include "memory/barrierSet.hpp"
#include "memory/memRegion.hpp"
--- a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Tue Apr 21 10:29:35 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Wed Apr 15 11:42:20 2015 -0400
@@ -34,7 +34,7 @@
#include "gc_implementation/shared/gcTimer.hpp"
#include "gc_implementation/shared/gcTrace.hpp"
#include "gc_implementation/shared/gcTraceTime.hpp"
-#include "gc_implementation/shared/parGCAllocBuffer.inline.hpp"
+#include "gc_implementation/shared/plab.inline.hpp"
#include "gc_implementation/shared/spaceDecorator.hpp"
#include "memory/defNewGeneration.inline.hpp"
#include "memory/genCollectedHeap.hpp"
@@ -226,7 +226,7 @@
// buffer.
HeapWord* obj = NULL;
if (!_to_space_full) {
- ParGCAllocBuffer* const plab = to_space_alloc_buffer();
+ PLAB* const plab = to_space_alloc_buffer();
Space* const sp = to_space();
if (word_sz * 100 <
ParallelGCBufferWastePct * plab->word_sz()) {
@@ -236,7 +236,7 @@
HeapWord* buf_space = sp->par_allocate(buf_size);
if (buf_space == NULL) {
const size_t min_bytes =
- ParGCAllocBuffer::min_size() << LogHeapWordSize;
+ PLAB::min_size() << LogHeapWordSize;
size_t free_bytes = sp->free();
while(buf_space == NULL && free_bytes >= min_bytes) {
buf_size = free_bytes >> LogHeapWordSize;
@@ -252,7 +252,7 @@
record_survivor_plab(buf_space, buf_size);
obj = plab->allocate_aligned(word_sz, SurvivorAlignmentInBytes);
// Note that we cannot compare buf_size < word_sz below
- // because of AlignmentReserve (see ParGCAllocBuffer::allocate()).
+ // because of AlignmentReserve (see PLAB::allocate()).
assert(obj != NULL || plab->words_remaining() < word_sz,
"Else should have been able to allocate");
// It's conceivable that we may be able to use the
--- a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp Tue Apr 21 10:29:35 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp Wed Apr 15 11:42:20 2015 -0400
@@ -27,7 +27,7 @@
#include "gc_implementation/parNew/parOopClosures.hpp"
#include "gc_implementation/shared/gcTrace.hpp"
-#include "gc_implementation/shared/parGCAllocBuffer.hpp"
+#include "gc_implementation/shared/plab.hpp"
#include "gc_implementation/shared/copyFailedInfo.hpp"
#include "memory/defNewGeneration.hpp"
#include "memory/padded.hpp"
@@ -65,7 +65,7 @@
ObjToScanQueue *_work_queue;
Stack<oop, mtGC>* const _overflow_stack;
- ParGCAllocBuffer _to_space_alloc_buffer;
+ PLAB _to_space_alloc_buffer;
ParScanWithoutBarrierClosure _to_space_closure; // scan_without_gc_barrier
ParScanWithBarrierClosure _old_gen_closure; // scan_with_gc_barrier
@@ -140,7 +140,7 @@
ObjToScanQueue* work_queue() { return _work_queue; }
- ParGCAllocBuffer* to_space_alloc_buffer() {
+ PLAB* to_space_alloc_buffer() {
return &_to_space_alloc_buffer;
}
--- a/hotspot/src/share/vm/gc_implementation/shared/parGCAllocBuffer.cpp Tue Apr 21 10:29:35 2015 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,134 +0,0 @@
-/*
- * Copyright (c) 2001, 2015, 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.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#include "precompiled.hpp"
-#include "gc_implementation/shared/parGCAllocBuffer.hpp"
-#include "memory/threadLocalAllocBuffer.hpp"
-#include "oops/arrayOop.hpp"
-#include "oops/oop.inline.hpp"
-
-size_t ParGCAllocBuffer::min_size() {
- // Make sure that we return something that is larger than AlignmentReserve
- return align_object_size(MAX2(MinTLABSize / HeapWordSize, (uintx)oopDesc::header_size())) + AlignmentReserve;
-}
-
-size_t ParGCAllocBuffer::max_size() {
- return ThreadLocalAllocBuffer::max_size();
-}
-
-ParGCAllocBuffer::ParGCAllocBuffer(size_t desired_plab_sz_) :
- _word_sz(desired_plab_sz_), _bottom(NULL), _top(NULL),
- _end(NULL), _hard_end(NULL), _allocated(0), _wasted(0)
-{
- // ArrayOopDesc::header_size depends on command line initialization.
- AlignmentReserve = oopDesc::header_size() > MinObjAlignment ? align_object_size(arrayOopDesc::header_size(T_INT)) : 0;
- assert(min_size() > AlignmentReserve,
- err_msg("Minimum PLAB size " SIZE_FORMAT" must be larger than alignment reserve " SIZE_FORMAT" "
- "to be able to contain objects", min_size(), AlignmentReserve));
-}
-
-// If the minimum object size is greater than MinObjAlignment, we can
-// end up with a shard at the end of the buffer that's smaller than
-// the smallest object. We can't allow that because the buffer must
-// look like it's full of objects when we retire it, so we make
-// sure we have enough space for a filler int array object.
-size_t ParGCAllocBuffer::AlignmentReserve;
-
-void ParGCAllocBuffer::flush_and_retire_stats(PLABStats* stats) {
- // Retire the last allocation buffer.
- size_t unused = retire_internal();
-
- // Now flush the statistics.
- stats->add_allocated(_allocated);
- stats->add_wasted(_wasted);
- stats->add_unused(unused);
-
- // Since we have flushed the stats we need to clear the _allocated and _wasted
- // fields in case somebody retains an instance of this over GCs. Not doing so
- // will artifically inflate the values in the statistics.
- _allocated = 0;
- _wasted = 0;
-}
-
-void ParGCAllocBuffer::retire() {
- _wasted += retire_internal();
-}
-
-size_t ParGCAllocBuffer::retire_internal() {
- size_t result = 0;
- if (_top < _hard_end) {
- CollectedHeap::fill_with_object(_top, _hard_end);
- result += invalidate();
- }
- return result;
-}
-
-// Compute desired plab size and latch result for later
-// use. This should be called once at the end of parallel
-// scavenge; it clears the sensor accumulators.
-void PLABStats::adjust_desired_plab_sz(uint no_of_gc_workers) {
- assert(ResizePLAB, "Not set");
-
- assert(is_object_aligned(max_size()) && min_size() <= max_size(),
- "PLAB clipping computation may be incorrect");
-
- if (_allocated == 0) {
- assert(_unused == 0,
- err_msg("Inconsistency in PLAB stats: "
- "_allocated: "SIZE_FORMAT", "
- "_wasted: "SIZE_FORMAT", "
- "_unused: "SIZE_FORMAT,
- _allocated, _wasted, _unused));
-
- _allocated = 1;
- }
- double wasted_frac = (double)_unused / (double)_allocated;
- size_t target_refills = (size_t)((wasted_frac * TargetSurvivorRatio) / TargetPLABWastePct);
- if (target_refills == 0) {
- target_refills = 1;
- }
- size_t used = _allocated - _wasted - _unused;
- size_t recent_plab_sz = used / (target_refills * no_of_gc_workers);
- // Take historical weighted average
- _filter.sample(recent_plab_sz);
- // Clip from above and below, and align to object boundary
- size_t new_plab_sz = MAX2(min_size(), (size_t)_filter.average());
- new_plab_sz = MIN2(max_size(), new_plab_sz);
- new_plab_sz = align_object_size(new_plab_sz);
- // Latch the result
- if (PrintPLAB) {
- gclog_or_tty->print(" (plab_sz = " SIZE_FORMAT" desired_plab_sz = " SIZE_FORMAT") ", recent_plab_sz, new_plab_sz);
- }
- _desired_plab_sz = new_plab_sz;
-
- reset();
-}
-
-#ifndef PRODUCT
-void ParGCAllocBuffer::print() {
- gclog_or_tty->print_cr("parGCAllocBuffer: _bottom: " PTR_FORMAT " _top: " PTR_FORMAT
- " _end: " PTR_FORMAT " _hard_end: " PTR_FORMAT ")",
- p2i(_bottom), p2i(_top), p2i(_end), p2i(_hard_end));
-}
-#endif // !PRODUCT
--- a/hotspot/src/share/vm/gc_implementation/shared/parGCAllocBuffer.hpp Tue Apr 21 10:29:35 2015 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,197 +0,0 @@
-/*
- * Copyright (c) 2001, 2015, 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.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#ifndef SHARE_VM_GC_IMPLEMENTATION_PARNEW_PARGCALLOCBUFFER_HPP
-#define SHARE_VM_GC_IMPLEMENTATION_PARNEW_PARGCALLOCBUFFER_HPP
-
-#include "gc_implementation/shared/gcUtil.hpp"
-#include "memory/allocation.hpp"
-#include "runtime/atomic.hpp"
-#include "utilities/globalDefinitions.hpp"
-
-// Forward declarations.
-class PLABStats;
-
-// A per-thread allocation buffer used during GC.
-class ParGCAllocBuffer: public CHeapObj<mtGC> {
-protected:
- char head[32];
- size_t _word_sz; // In HeapWord units
- HeapWord* _bottom;
- HeapWord* _top;
- HeapWord* _end; // Last allocatable address + 1
- HeapWord* _hard_end; // _end + AlignmentReserve
- // In support of ergonomic sizing of PLAB's
- size_t _allocated; // in HeapWord units
- size_t _wasted; // in HeapWord units
- char tail[32];
- static size_t AlignmentReserve;
-
- // Force future allocations to fail and queries for contains()
- // to return false. Returns the amount of unused space in this PLAB.
- size_t invalidate() {
- _end = _hard_end;
- size_t remaining = pointer_delta(_end, _top); // Calculate remaining space.
- _top = _end; // Force future allocations to fail.
- _bottom = _end; // Force future contains() queries to return false.
- return remaining;
- }
-
- // Fill in remaining space with a dummy object and invalidate the PLAB. Returns
- // the amount of remaining space.
- size_t retire_internal();
-
-public:
- // Initializes the buffer to be empty, but with the given "word_sz".
- // Must get initialized with "set_buf" for an allocation to succeed.
- ParGCAllocBuffer(size_t word_sz);
- virtual ~ParGCAllocBuffer() {}
-
- // Minimum PLAB size.
- static size_t min_size();
- // Maximum PLAB size.
- static size_t max_size();
-
- // If an allocation of the given "word_sz" can be satisfied within the
- // buffer, do the allocation, returning a pointer to the start of the
- // allocated block. If the allocation request cannot be satisfied,
- // return NULL.
- HeapWord* allocate(size_t word_sz) {
- HeapWord* res = _top;
- if (pointer_delta(_end, _top) >= word_sz) {
- _top = _top + word_sz;
- return res;
- } else {
- return NULL;
- }
- }
-
- // Allocate the object aligned to "alignment_in_bytes".
- HeapWord* allocate_aligned(size_t word_sz, unsigned short alignment_in_bytes);
-
- // Undo the last allocation in the buffer, which is required to be of the
- // "obj" of the given "word_sz".
- void undo_allocation(HeapWord* obj, size_t word_sz) {
- assert(pointer_delta(_top, _bottom) >= word_sz, "Bad undo");
- assert(pointer_delta(_top, obj) == word_sz, "Bad undo");
- _top = obj;
- }
-
- // The total (word) size of the buffer, including both allocated and
- // unallocated space.
- size_t word_sz() { return _word_sz; }
-
- // Should only be done if we are about to reset with a new buffer of the
- // given size.
- void set_word_size(size_t new_word_sz) {
- assert(new_word_sz > AlignmentReserve, "Too small");
- _word_sz = new_word_sz;
- }
-
- // The number of words of unallocated space remaining in the buffer.
- size_t words_remaining() {
- assert(_end >= _top, "Negative buffer");
- return pointer_delta(_end, _top, HeapWordSize);
- }
-
- bool contains(void* addr) {
- return (void*)_bottom <= addr && addr < (void*)_hard_end;
- }
-
- // Sets the space of the buffer to be [buf, space+word_sz()).
- virtual void set_buf(HeapWord* buf) {
- _bottom = buf;
- _top = _bottom;
- _hard_end = _bottom + word_sz();
- _end = _hard_end - AlignmentReserve;
- assert(_end >= _top, "Negative buffer");
- // In support of ergonomic sizing
- _allocated += word_sz();
- }
-
- // Flush allocation statistics into the given PLABStats supporting ergonomic
- // sizing of PLAB's and retire the current buffer. To be called at the end of
- // GC.
- void flush_and_retire_stats(PLABStats* stats);
-
- // Fills in the unallocated portion of the buffer with a garbage object and updates
- // statistics. To be called during GC.
- virtual void retire();
-
- void print() PRODUCT_RETURN;
-};
-
-// PLAB book-keeping.
-class PLABStats VALUE_OBJ_CLASS_SPEC {
- size_t _allocated; // Total allocated
- size_t _wasted; // of which wasted (internal fragmentation)
- size_t _unused; // Unused in last buffer
- size_t _desired_plab_sz;// Output of filter (below), suitably trimmed and quantized
- AdaptiveWeightedAverage
- _filter; // Integrator with decay
-
- void reset() {
- _allocated = 0;
- _wasted = 0;
- _unused = 0;
- }
- public:
- PLABStats(size_t desired_plab_sz_, unsigned wt) :
- _allocated(0),
- _wasted(0),
- _unused(0),
- _desired_plab_sz(desired_plab_sz_),
- _filter(wt)
- { }
-
- static const size_t min_size() {
- return ParGCAllocBuffer::min_size();
- }
-
- static const size_t max_size() {
- return ParGCAllocBuffer::max_size();
- }
-
- size_t desired_plab_sz() {
- return _desired_plab_sz;
- }
-
- // Updates the current desired PLAB size. Computes the new desired PLAB size,
- // updates _desired_plab_sz and clears sensor accumulators.
- void adjust_desired_plab_sz(uint no_of_gc_workers);
-
- void add_allocated(size_t v) {
- Atomic::add_ptr(v, &_allocated);
- }
-
- void add_unused(size_t v) {
- Atomic::add_ptr(v, &_unused);
- }
-
- void add_wasted(size_t v) {
- Atomic::add_ptr(v, &_wasted);
- }
-};
-
-#endif // SHARE_VM_GC_IMPLEMENTATION_PARNEW_PARGCALLOCBUFFER_HPP
--- a/hotspot/src/share/vm/gc_implementation/shared/parGCAllocBuffer.inline.hpp Tue Apr 21 10:29:35 2015 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2014, 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.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_PARGCALLOCBUFFER_INLINE_HPP
-#define SHARE_VM_GC_IMPLEMENTATION_SHARED_PARGCALLOCBUFFER_INLINE_HPP
-
-#include "gc_implementation/shared/parGCAllocBuffer.hpp"
-#include "gc_interface/collectedHeap.inline.hpp"
-
-HeapWord* ParGCAllocBuffer::allocate_aligned(size_t word_sz, unsigned short alignment_in_bytes) {
-
- HeapWord* res = CollectedHeap::align_allocation_or_fail(_top, _end, alignment_in_bytes);
- if (res == NULL) {
- return NULL;
- }
-
- // Set _top so that allocate(), which expects _top to be correctly set,
- // can be used below.
- _top = res;
- return allocate(word_sz);
-}
-
-#endif // SHARE_VM_GC_IMPLEMENTATION_SHARED_PARGCALLOCBUFFER_INLINE_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc_implementation/shared/plab.cpp Wed Apr 15 11:42:20 2015 -0400
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2001, 2015, 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc_implementation/shared/plab.hpp"
+#include "memory/threadLocalAllocBuffer.hpp"
+#include "oops/arrayOop.hpp"
+#include "oops/oop.inline.hpp"
+
+size_t PLAB::min_size() {
+ // Make sure that we return something that is larger than AlignmentReserve
+ return align_object_size(MAX2(MinTLABSize / HeapWordSize, (uintx)oopDesc::header_size())) + AlignmentReserve;
+}
+
+size_t PLAB::max_size() {
+ return ThreadLocalAllocBuffer::max_size();
+}
+
+PLAB::PLAB(size_t desired_plab_sz_) :
+ _word_sz(desired_plab_sz_), _bottom(NULL), _top(NULL),
+ _end(NULL), _hard_end(NULL), _allocated(0), _wasted(0)
+{
+ // ArrayOopDesc::header_size depends on command line initialization.
+ AlignmentReserve = oopDesc::header_size() > MinObjAlignment ? align_object_size(arrayOopDesc::header_size(T_INT)) : 0;
+ assert(min_size() > AlignmentReserve,
+ err_msg("Minimum PLAB size " SIZE_FORMAT" must be larger than alignment reserve " SIZE_FORMAT" "
+ "to be able to contain objects", min_size(), AlignmentReserve));
+}
+
+// If the minimum object size is greater than MinObjAlignment, we can
+// end up with a shard at the end of the buffer that's smaller than
+// the smallest object. We can't allow that because the buffer must
+// look like it's full of objects when we retire it, so we make
+// sure we have enough space for a filler int array object.
+size_t PLAB::AlignmentReserve;
+
+void PLAB::flush_and_retire_stats(PLABStats* stats) {
+ // Retire the last allocation buffer.
+ size_t unused = retire_internal();
+
+ // Now flush the statistics.
+ stats->add_allocated(_allocated);
+ stats->add_wasted(_wasted);
+ stats->add_unused(unused);
+
+ // Since we have flushed the stats we need to clear the _allocated and _wasted
+ // fields in case somebody retains an instance of this over GCs. Not doing so
+ // will artifically inflate the values in the statistics.
+ _allocated = 0;
+ _wasted = 0;
+}
+
+void PLAB::retire() {
+ _wasted += retire_internal();
+}
+
+size_t PLAB::retire_internal() {
+ size_t result = 0;
+ if (_top < _hard_end) {
+ CollectedHeap::fill_with_object(_top, _hard_end);
+ result += invalidate();
+ }
+ return result;
+}
+
+// Compute desired plab size and latch result for later
+// use. This should be called once at the end of parallel
+// scavenge; it clears the sensor accumulators.
+void PLABStats::adjust_desired_plab_sz(uint no_of_gc_workers) {
+ assert(ResizePLAB, "Not set");
+
+ assert(is_object_aligned(max_size()) && min_size() <= max_size(),
+ "PLAB clipping computation may be incorrect");
+
+ if (_allocated == 0) {
+ assert(_unused == 0,
+ err_msg("Inconsistency in PLAB stats: "
+ "_allocated: "SIZE_FORMAT", "
+ "_wasted: "SIZE_FORMAT", "
+ "_unused: "SIZE_FORMAT,
+ _allocated, _wasted, _unused));
+
+ _allocated = 1;
+ }
+ double wasted_frac = (double)_unused / (double)_allocated;
+ size_t target_refills = (size_t)((wasted_frac * TargetSurvivorRatio) / TargetPLABWastePct);
+ if (target_refills == 0) {
+ target_refills = 1;
+ }
+ size_t used = _allocated - _wasted - _unused;
+ size_t recent_plab_sz = used / (target_refills * no_of_gc_workers);
+ // Take historical weighted average
+ _filter.sample(recent_plab_sz);
+ // Clip from above and below, and align to object boundary
+ size_t new_plab_sz = MAX2(min_size(), (size_t)_filter.average());
+ new_plab_sz = MIN2(max_size(), new_plab_sz);
+ new_plab_sz = align_object_size(new_plab_sz);
+ // Latch the result
+ if (PrintPLAB) {
+ gclog_or_tty->print(" (plab_sz = " SIZE_FORMAT" desired_plab_sz = " SIZE_FORMAT") ", recent_plab_sz, new_plab_sz);
+ }
+ _desired_plab_sz = new_plab_sz;
+
+ reset();
+}
+
+#ifndef PRODUCT
+void PLAB::print() {
+ gclog_or_tty->print_cr("PLAB: _bottom: " PTR_FORMAT " _top: " PTR_FORMAT
+ " _end: " PTR_FORMAT " _hard_end: " PTR_FORMAT ")",
+ p2i(_bottom), p2i(_top), p2i(_end), p2i(_hard_end));
+}
+#endif // !PRODUCT
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc_implementation/shared/plab.hpp Wed Apr 15 11:42:20 2015 -0400
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2001, 2015, 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_PLAB_HPP
+#define SHARE_VM_GC_IMPLEMENTATION_SHARED_PLAB_HPP
+
+#include "gc_implementation/shared/gcUtil.hpp"
+#include "memory/allocation.hpp"
+#include "runtime/atomic.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+// Forward declarations.
+class PLABStats;
+
+// A per-thread allocation buffer used during GC.
+class PLAB: public CHeapObj<mtGC> {
+protected:
+ char head[32];
+ size_t _word_sz; // In HeapWord units
+ HeapWord* _bottom;
+ HeapWord* _top;
+ HeapWord* _end; // Last allocatable address + 1
+ HeapWord* _hard_end; // _end + AlignmentReserve
+ // In support of ergonomic sizing of PLAB's
+ size_t _allocated; // in HeapWord units
+ size_t _wasted; // in HeapWord units
+ char tail[32];
+ static size_t AlignmentReserve;
+
+ // Force future allocations to fail and queries for contains()
+ // to return false. Returns the amount of unused space in this PLAB.
+ size_t invalidate() {
+ _end = _hard_end;
+ size_t remaining = pointer_delta(_end, _top); // Calculate remaining space.
+ _top = _end; // Force future allocations to fail.
+ _bottom = _end; // Force future contains() queries to return false.
+ return remaining;
+ }
+
+ // Fill in remaining space with a dummy object and invalidate the PLAB. Returns
+ // the amount of remaining space.
+ size_t retire_internal();
+
+public:
+ // Initializes the buffer to be empty, but with the given "word_sz".
+ // Must get initialized with "set_buf" for an allocation to succeed.
+ PLAB(size_t word_sz);
+ virtual ~PLAB() {}
+
+ // Minimum PLAB size.
+ static size_t min_size();
+ // Maximum PLAB size.
+ static size_t max_size();
+
+ // If an allocation of the given "word_sz" can be satisfied within the
+ // buffer, do the allocation, returning a pointer to the start of the
+ // allocated block. If the allocation request cannot be satisfied,
+ // return NULL.
+ HeapWord* allocate(size_t word_sz) {
+ HeapWord* res = _top;
+ if (pointer_delta(_end, _top) >= word_sz) {
+ _top = _top + word_sz;
+ return res;
+ } else {
+ return NULL;
+ }
+ }
+
+ // Allocate the object aligned to "alignment_in_bytes".
+ HeapWord* allocate_aligned(size_t word_sz, unsigned short alignment_in_bytes);
+
+ // Undo the last allocation in the buffer, which is required to be of the
+ // "obj" of the given "word_sz".
+ void undo_allocation(HeapWord* obj, size_t word_sz) {
+ assert(pointer_delta(_top, _bottom) >= word_sz, "Bad undo");
+ assert(pointer_delta(_top, obj) == word_sz, "Bad undo");
+ _top = obj;
+ }
+
+ // The total (word) size of the buffer, including both allocated and
+ // unallocated space.
+ size_t word_sz() { return _word_sz; }
+
+ // Should only be done if we are about to reset with a new buffer of the
+ // given size.
+ void set_word_size(size_t new_word_sz) {
+ assert(new_word_sz > AlignmentReserve, "Too small");
+ _word_sz = new_word_sz;
+ }
+
+ // The number of words of unallocated space remaining in the buffer.
+ size_t words_remaining() {
+ assert(_end >= _top, "Negative buffer");
+ return pointer_delta(_end, _top, HeapWordSize);
+ }
+
+ bool contains(void* addr) {
+ return (void*)_bottom <= addr && addr < (void*)_hard_end;
+ }
+
+ // Sets the space of the buffer to be [buf, space+word_sz()).
+ virtual void set_buf(HeapWord* buf) {
+ _bottom = buf;
+ _top = _bottom;
+ _hard_end = _bottom + word_sz();
+ _end = _hard_end - AlignmentReserve;
+ assert(_end >= _top, "Negative buffer");
+ // In support of ergonomic sizing
+ _allocated += word_sz();
+ }
+
+ // Flush allocation statistics into the given PLABStats supporting ergonomic
+ // sizing of PLAB's and retire the current buffer. To be called at the end of
+ // GC.
+ void flush_and_retire_stats(PLABStats* stats);
+
+ // Fills in the unallocated portion of the buffer with a garbage object and updates
+ // statistics. To be called during GC.
+ virtual void retire();
+
+ void print() PRODUCT_RETURN;
+};
+
+// PLAB book-keeping.
+class PLABStats VALUE_OBJ_CLASS_SPEC {
+ size_t _allocated; // Total allocated
+ size_t _wasted; // of which wasted (internal fragmentation)
+ size_t _unused; // Unused in last buffer
+ size_t _desired_plab_sz;// Output of filter (below), suitably trimmed and quantized
+ AdaptiveWeightedAverage
+ _filter; // Integrator with decay
+
+ void reset() {
+ _allocated = 0;
+ _wasted = 0;
+ _unused = 0;
+ }
+ public:
+ PLABStats(size_t desired_plab_sz_, unsigned wt) :
+ _allocated(0),
+ _wasted(0),
+ _unused(0),
+ _desired_plab_sz(desired_plab_sz_),
+ _filter(wt)
+ { }
+
+ static const size_t min_size() {
+ return PLAB::min_size();
+ }
+
+ static const size_t max_size() {
+ return PLAB::max_size();
+ }
+
+ size_t desired_plab_sz() {
+ return _desired_plab_sz;
+ }
+
+ // Updates the current desired PLAB size. Computes the new desired PLAB size,
+ // updates _desired_plab_sz and clears sensor accumulators.
+ void adjust_desired_plab_sz(uint no_of_gc_workers);
+
+ void add_allocated(size_t v) {
+ Atomic::add_ptr(v, &_allocated);
+ }
+
+ void add_unused(size_t v) {
+ Atomic::add_ptr(v, &_unused);
+ }
+
+ void add_wasted(size_t v) {
+ Atomic::add_ptr(v, &_wasted);
+ }
+};
+
+#endif // SHARE_VM_GC_IMPLEMENTATION_SHARED_PLAB_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc_implementation/shared/plab.inline.hpp Wed Apr 15 11:42:20 2015 -0400
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2014, 2015, 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_PLAB_INLINE_HPP
+#define SHARE_VM_GC_IMPLEMENTATION_SHARED_PLAB_INLINE_HPP
+
+#include "gc_implementation/shared/plab.hpp"
+#include "gc_interface/collectedHeap.inline.hpp"
+
+HeapWord* PLAB::allocate_aligned(size_t word_sz, unsigned short alignment_in_bytes) {
+
+ HeapWord* res = CollectedHeap::align_allocation_or_fail(_top, _end, alignment_in_bytes);
+ if (res == NULL) {
+ return NULL;
+ }
+
+ // Set _top so that allocate(), which expects _top to be correctly set,
+ // can be used below.
+ _top = res;
+ return allocate(word_sz);
+}
+
+#endif // SHARE_VM_GC_IMPLEMENTATION_SHARED_PLAB_INLINE_HPP
--- a/hotspot/src/share/vm/precompiled/precompiled.hpp Tue Apr 21 10:29:35 2015 -0400
+++ b/hotspot/src/share/vm/precompiled/precompiled.hpp Wed Apr 15 11:42:20 2015 -0400
@@ -315,7 +315,7 @@
# include "gc_implementation/parallelScavenge/psYoungGen.hpp"
# include "gc_implementation/shared/gcAdaptivePolicyCounters.hpp"
# include "gc_implementation/shared/gcPolicyCounters.hpp"
-# include "gc_implementation/shared/parGCAllocBuffer.hpp"
+# include "gc_implementation/shared/plab.hpp"
#endif // INCLUDE_ALL_GCS
#endif // !DONT_USE_PRECOMPILED_HEADER
--- a/hotspot/src/share/vm/runtime/globals.hpp Tue Apr 21 10:29:35 2015 -0400
+++ b/hotspot/src/share/vm/runtime/globals.hpp Wed Apr 15 11:42:20 2015 -0400
@@ -1960,7 +1960,7 @@
"collection") \
\
develop(uintx, PromotionFailureALotCount, 1000, \
- "Number of promotion failures occurring at ParGCAllocBuffer " \
+ "Number of promotion failures occurring at PLAB " \
"refill attempts (ParNew) or promotion attempts " \
"(other young collectors)") \
\