Wed, 01 Dec 2010 15:04:06 +0100
7003125: precompiled.hpp is included when precompiled headers are not used
Summary: Added an ifndef DONT_USE_PRECOMPILED_HEADER to precompiled.hpp. Set up DONT_USE_PRECOMPILED_HEADER when compiling with Sun Studio or when the user specifies USE_PRECOMPILED_HEADER=0. Fixed broken include dependencies.
Reviewed-by: coleenp, kvn
duke@435 | 1 | /* |
stefank@2314 | 2 | * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. |
duke@435 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
duke@435 | 4 | * |
duke@435 | 5 | * This code is free software; you can redistribute it and/or modify it |
duke@435 | 6 | * under the terms of the GNU General Public License version 2 only, as |
duke@435 | 7 | * published by the Free Software Foundation. |
duke@435 | 8 | * |
duke@435 | 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
duke@435 | 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
duke@435 | 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
duke@435 | 12 | * version 2 for more details (a copy is included in the LICENSE file that |
duke@435 | 13 | * accompanied this code). |
duke@435 | 14 | * |
duke@435 | 15 | * You should have received a copy of the GNU General Public License version |
duke@435 | 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
duke@435 | 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
duke@435 | 18 | * |
trims@1907 | 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
trims@1907 | 20 | * or visit www.oracle.com if you need additional information or have any |
trims@1907 | 21 | * questions. |
duke@435 | 22 | * |
duke@435 | 23 | */ |
duke@435 | 24 | |
stefank@2314 | 25 | #ifndef SHARE_VM_GC_IMPLEMENTATION_PARNEW_PARGCALLOCBUFFER_HPP |
stefank@2314 | 26 | #define SHARE_VM_GC_IMPLEMENTATION_PARNEW_PARGCALLOCBUFFER_HPP |
stefank@2314 | 27 | |
stefank@2314 | 28 | #include "memory/allocation.hpp" |
stefank@2325 | 29 | #include "memory/blockOffsetTable.hpp" |
stefank@2314 | 30 | #include "memory/threadLocalAllocBuffer.hpp" |
stefank@2314 | 31 | #include "utilities/globalDefinitions.hpp" |
stefank@2314 | 32 | |
duke@435 | 33 | // Forward decl. |
duke@435 | 34 | |
duke@435 | 35 | class PLABStats; |
duke@435 | 36 | |
duke@435 | 37 | // A per-thread allocation buffer used during GC. |
duke@435 | 38 | class ParGCAllocBuffer: public CHeapObj { |
duke@435 | 39 | protected: |
duke@435 | 40 | char head[32]; |
duke@435 | 41 | size_t _word_sz; // in HeapWord units |
duke@435 | 42 | HeapWord* _bottom; |
duke@435 | 43 | HeapWord* _top; |
duke@435 | 44 | HeapWord* _end; // last allocatable address + 1 |
duke@435 | 45 | HeapWord* _hard_end; // _end + AlignmentReserve |
duke@435 | 46 | bool _retained; // whether we hold a _retained_filler |
duke@435 | 47 | MemRegion _retained_filler; |
duke@435 | 48 | // In support of ergonomic sizing of PLAB's |
duke@435 | 49 | size_t _allocated; // in HeapWord units |
duke@435 | 50 | size_t _wasted; // in HeapWord units |
duke@435 | 51 | char tail[32]; |
coleenp@548 | 52 | static size_t FillerHeaderSize; |
coleenp@548 | 53 | static size_t AlignmentReserve; |
duke@435 | 54 | |
duke@435 | 55 | public: |
duke@435 | 56 | // Initializes the buffer to be empty, but with the given "word_sz". |
duke@435 | 57 | // Must get initialized with "set_buf" for an allocation to succeed. |
duke@435 | 58 | ParGCAllocBuffer(size_t word_sz); |
duke@435 | 59 | |
duke@435 | 60 | static const size_t min_size() { |
duke@435 | 61 | return ThreadLocalAllocBuffer::min_size(); |
duke@435 | 62 | } |
duke@435 | 63 | |
duke@435 | 64 | static const size_t max_size() { |
duke@435 | 65 | return ThreadLocalAllocBuffer::max_size(); |
duke@435 | 66 | } |
duke@435 | 67 | |
duke@435 | 68 | // If an allocation of the given "word_sz" can be satisfied within the |
duke@435 | 69 | // buffer, do the allocation, returning a pointer to the start of the |
duke@435 | 70 | // allocated block. If the allocation request cannot be satisfied, |
duke@435 | 71 | // return NULL. |
duke@435 | 72 | HeapWord* allocate(size_t word_sz) { |
duke@435 | 73 | HeapWord* res = _top; |
ysr@1069 | 74 | if (pointer_delta(_end, _top) >= word_sz) { |
ysr@1069 | 75 | _top = _top + word_sz; |
duke@435 | 76 | return res; |
duke@435 | 77 | } else { |
duke@435 | 78 | return NULL; |
duke@435 | 79 | } |
duke@435 | 80 | } |
duke@435 | 81 | |
duke@435 | 82 | // Undo the last allocation in the buffer, which is required to be of the |
duke@435 | 83 | // "obj" of the given "word_sz". |
duke@435 | 84 | void undo_allocation(HeapWord* obj, size_t word_sz) { |
ysr@1069 | 85 | assert(pointer_delta(_top, _bottom) >= word_sz, "Bad undo"); |
ysr@1069 | 86 | assert(pointer_delta(_top, obj) == word_sz, "Bad undo"); |
ysr@1069 | 87 | _top = obj; |
duke@435 | 88 | } |
duke@435 | 89 | |
duke@435 | 90 | // The total (word) size of the buffer, including both allocated and |
duke@435 | 91 | // unallocted space. |
duke@435 | 92 | size_t word_sz() { return _word_sz; } |
duke@435 | 93 | |
duke@435 | 94 | // Should only be done if we are about to reset with a new buffer of the |
duke@435 | 95 | // given size. |
duke@435 | 96 | void set_word_size(size_t new_word_sz) { |
duke@435 | 97 | assert(new_word_sz > AlignmentReserve, "Too small"); |
duke@435 | 98 | _word_sz = new_word_sz; |
duke@435 | 99 | } |
duke@435 | 100 | |
duke@435 | 101 | // The number of words of unallocated space remaining in the buffer. |
duke@435 | 102 | size_t words_remaining() { |
duke@435 | 103 | assert(_end >= _top, "Negative buffer"); |
duke@435 | 104 | return pointer_delta(_end, _top, HeapWordSize); |
duke@435 | 105 | } |
duke@435 | 106 | |
duke@435 | 107 | bool contains(void* addr) { |
duke@435 | 108 | return (void*)_bottom <= addr && addr < (void*)_hard_end; |
duke@435 | 109 | } |
duke@435 | 110 | |
duke@435 | 111 | // Sets the space of the buffer to be [buf, space+word_sz()). |
duke@435 | 112 | void set_buf(HeapWord* buf) { |
duke@435 | 113 | _bottom = buf; |
duke@435 | 114 | _top = _bottom; |
duke@435 | 115 | _hard_end = _bottom + word_sz(); |
duke@435 | 116 | _end = _hard_end - AlignmentReserve; |
duke@435 | 117 | assert(_end >= _top, "Negative buffer"); |
duke@435 | 118 | // In support of ergonomic sizing |
duke@435 | 119 | _allocated += word_sz(); |
duke@435 | 120 | } |
duke@435 | 121 | |
duke@435 | 122 | // Flush the stats supporting ergonomic sizing of PLAB's |
duke@435 | 123 | void flush_stats(PLABStats* stats); |
duke@435 | 124 | void flush_stats_and_retire(PLABStats* stats, bool retain) { |
duke@435 | 125 | // We flush the stats first in order to get a reading of |
duke@435 | 126 | // unused space in the last buffer. |
duke@435 | 127 | if (ResizePLAB) { |
duke@435 | 128 | flush_stats(stats); |
duke@435 | 129 | } |
duke@435 | 130 | // Retire the last allocation buffer. |
duke@435 | 131 | retire(true, retain); |
duke@435 | 132 | } |
duke@435 | 133 | |
duke@435 | 134 | // Force future allocations to fail and queries for contains() |
duke@435 | 135 | // to return false |
duke@435 | 136 | void invalidate() { |
duke@435 | 137 | assert(!_retained, "Shouldn't retain an invalidated buffer."); |
duke@435 | 138 | _end = _hard_end; |
duke@435 | 139 | _wasted += pointer_delta(_end, _top); // unused space |
duke@435 | 140 | _top = _end; // force future allocations to fail |
duke@435 | 141 | _bottom = _end; // force future contains() queries to return false |
duke@435 | 142 | } |
duke@435 | 143 | |
duke@435 | 144 | // Fills in the unallocated portion of the buffer with a garbage object. |
duke@435 | 145 | // If "end_of_gc" is TRUE, is after the last use in the GC. IF "retain" |
duke@435 | 146 | // is true, attempt to re-use the unused portion in the next GC. |
duke@435 | 147 | void retire(bool end_of_gc, bool retain); |
duke@435 | 148 | |
duke@435 | 149 | void print() PRODUCT_RETURN; |
duke@435 | 150 | }; |
duke@435 | 151 | |
duke@435 | 152 | // PLAB stats book-keeping |
duke@435 | 153 | class PLABStats VALUE_OBJ_CLASS_SPEC { |
duke@435 | 154 | size_t _allocated; // total allocated |
duke@435 | 155 | size_t _wasted; // of which wasted (internal fragmentation) |
duke@435 | 156 | size_t _unused; // Unused in last buffer |
duke@435 | 157 | size_t _used; // derived = allocated - wasted - unused |
duke@435 | 158 | size_t _desired_plab_sz;// output of filter (below), suitably trimmed and quantized |
duke@435 | 159 | AdaptiveWeightedAverage |
duke@435 | 160 | _filter; // integrator with decay |
duke@435 | 161 | |
duke@435 | 162 | public: |
duke@435 | 163 | PLABStats(size_t desired_plab_sz_, unsigned wt) : |
duke@435 | 164 | _allocated(0), |
duke@435 | 165 | _wasted(0), |
duke@435 | 166 | _unused(0), |
duke@435 | 167 | _used(0), |
duke@435 | 168 | _desired_plab_sz(desired_plab_sz_), |
duke@435 | 169 | _filter(wt) |
duke@435 | 170 | { |
duke@435 | 171 | size_t min_sz = min_size(); |
duke@435 | 172 | size_t max_sz = max_size(); |
duke@435 | 173 | size_t aligned_min_sz = align_object_size(min_sz); |
duke@435 | 174 | size_t aligned_max_sz = align_object_size(max_sz); |
duke@435 | 175 | assert(min_sz <= aligned_min_sz && max_sz >= aligned_max_sz && |
duke@435 | 176 | min_sz <= max_sz, |
duke@435 | 177 | "PLAB clipping computation in adjust_desired_plab_sz()" |
duke@435 | 178 | " may be incorrect"); |
duke@435 | 179 | } |
duke@435 | 180 | |
duke@435 | 181 | static const size_t min_size() { |
duke@435 | 182 | return ParGCAllocBuffer::min_size(); |
duke@435 | 183 | } |
duke@435 | 184 | |
duke@435 | 185 | static const size_t max_size() { |
duke@435 | 186 | return ParGCAllocBuffer::max_size(); |
duke@435 | 187 | } |
duke@435 | 188 | |
duke@435 | 189 | size_t desired_plab_sz() { |
duke@435 | 190 | return _desired_plab_sz; |
duke@435 | 191 | } |
duke@435 | 192 | |
duke@435 | 193 | void adjust_desired_plab_sz(); // filter computation, latches output to |
duke@435 | 194 | // _desired_plab_sz, clears sensor accumulators |
duke@435 | 195 | |
duke@435 | 196 | void add_allocated(size_t v) { |
duke@435 | 197 | Atomic::add_ptr(v, &_allocated); |
duke@435 | 198 | } |
duke@435 | 199 | |
duke@435 | 200 | void add_unused(size_t v) { |
duke@435 | 201 | Atomic::add_ptr(v, &_unused); |
duke@435 | 202 | } |
duke@435 | 203 | |
duke@435 | 204 | void add_wasted(size_t v) { |
duke@435 | 205 | Atomic::add_ptr(v, &_wasted); |
duke@435 | 206 | } |
duke@435 | 207 | }; |
duke@435 | 208 | |
duke@435 | 209 | class ParGCAllocBufferWithBOT: public ParGCAllocBuffer { |
duke@435 | 210 | BlockOffsetArrayContigSpace _bt; |
duke@435 | 211 | BlockOffsetSharedArray* _bsa; |
duke@435 | 212 | HeapWord* _true_end; // end of the whole ParGCAllocBuffer |
duke@435 | 213 | |
duke@435 | 214 | static const size_t ChunkSizeInWords; |
duke@435 | 215 | static const size_t ChunkSizeInBytes; |
duke@435 | 216 | HeapWord* allocate_slow(size_t word_sz); |
duke@435 | 217 | |
duke@435 | 218 | void fill_region_with_block(MemRegion mr, bool contig); |
duke@435 | 219 | |
duke@435 | 220 | public: |
duke@435 | 221 | ParGCAllocBufferWithBOT(size_t word_sz, BlockOffsetSharedArray* bsa); |
duke@435 | 222 | |
duke@435 | 223 | HeapWord* allocate(size_t word_sz) { |
duke@435 | 224 | HeapWord* res = ParGCAllocBuffer::allocate(word_sz); |
duke@435 | 225 | if (res != NULL) { |
duke@435 | 226 | _bt.alloc_block(res, word_sz); |
duke@435 | 227 | } else { |
duke@435 | 228 | res = allocate_slow(word_sz); |
duke@435 | 229 | } |
duke@435 | 230 | return res; |
duke@435 | 231 | } |
duke@435 | 232 | |
duke@435 | 233 | void undo_allocation(HeapWord* obj, size_t word_sz); |
duke@435 | 234 | |
duke@435 | 235 | void set_buf(HeapWord* buf_start) { |
duke@435 | 236 | ParGCAllocBuffer::set_buf(buf_start); |
duke@435 | 237 | _true_end = _hard_end; |
duke@435 | 238 | _bt.set_region(MemRegion(buf_start, word_sz())); |
duke@435 | 239 | _bt.initialize_threshold(); |
duke@435 | 240 | } |
duke@435 | 241 | |
duke@435 | 242 | void retire(bool end_of_gc, bool retain); |
duke@435 | 243 | |
duke@435 | 244 | MemRegion range() { |
duke@435 | 245 | return MemRegion(_top, _true_end); |
duke@435 | 246 | } |
duke@435 | 247 | }; |
stefank@2314 | 248 | |
stefank@2314 | 249 | #endif // SHARE_VM_GC_IMPLEMENTATION_PARNEW_PARGCALLOCBUFFER_HPP |