annotate src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp @ 452:00b023ae2d78

6722113: CMS: Incorrect overflow handling during precleaning of Reference lists Summary: When we encounter marking stack overflow during precleaning of Reference lists, we were using the overflow list mechanism, which can cause problems on account of mutating the mark word of the header because of conflicts with mutator accesses and updates of that field. Instead we should use the usual mechanism for overflow handling in concurrent phases, namely dirtying of the card on which the overflowed object lies. Since precleaning effectively does a form of discovered list processing, albeit with discovery enabled, we needed to adjust some code to be correct in the face of interleaved processing and discovery. Reviewed-by: apetrusenko, jcoomes
author ysr
date Thu, 20 Nov 2008 12:27:41 -0800
parents 5d254928c888
children e9be0e04635a
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1 /*
196
d1605aabd0a1 6719955: Update copyright year
xdono
parents: 187
diff changeset
2 * Copyright 2001-2008 Sun Microsystems, Inc. All Rights Reserved.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
a61af66fc99e Initial load
duke
parents:
diff changeset
4 *
a61af66fc99e Initial load
duke
parents:
diff changeset
5 * This code is free software; you can redistribute it and/or modify it
a61af66fc99e Initial load
duke
parents:
diff changeset
6 * under the terms of the GNU General Public License version 2 only, as
a61af66fc99e Initial load
duke
parents:
diff changeset
7 * published by the Free Software Foundation.
a61af66fc99e Initial load
duke
parents:
diff changeset
8 *
a61af66fc99e Initial load
duke
parents:
diff changeset
9 * This code is distributed in the hope that it will be useful, but WITHOUT
a61af66fc99e Initial load
duke
parents:
diff changeset
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
a61af66fc99e Initial load
duke
parents:
diff changeset
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
a61af66fc99e Initial load
duke
parents:
diff changeset
12 * version 2 for more details (a copy is included in the LICENSE file that
a61af66fc99e Initial load
duke
parents:
diff changeset
13 * accompanied this code).
a61af66fc99e Initial load
duke
parents:
diff changeset
14 *
a61af66fc99e Initial load
duke
parents:
diff changeset
15 * You should have received a copy of the GNU General Public License version
a61af66fc99e Initial load
duke
parents:
diff changeset
16 * 2 along with this work; if not, write to the Free Software Foundation,
a61af66fc99e Initial load
duke
parents:
diff changeset
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
a61af66fc99e Initial load
duke
parents:
diff changeset
18 *
a61af66fc99e Initial load
duke
parents:
diff changeset
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
a61af66fc99e Initial load
duke
parents:
diff changeset
20 * CA 95054 USA or visit www.sun.com if you need additional information or
a61af66fc99e Initial load
duke
parents:
diff changeset
21 * have any questions.
a61af66fc99e Initial load
duke
parents:
diff changeset
22 *
a61af66fc99e Initial load
duke
parents:
diff changeset
23 */
a61af66fc99e Initial load
duke
parents:
diff changeset
24
a61af66fc99e Initial load
duke
parents:
diff changeset
25 # include "incls/_precompiled.incl"
a61af66fc99e Initial load
duke
parents:
diff changeset
26 # include "incls/_compactibleFreeListSpace.cpp.incl"
a61af66fc99e Initial load
duke
parents:
diff changeset
27
a61af66fc99e Initial load
duke
parents:
diff changeset
28 /////////////////////////////////////////////////////////////////////////
a61af66fc99e Initial load
duke
parents:
diff changeset
29 //// CompactibleFreeListSpace
a61af66fc99e Initial load
duke
parents:
diff changeset
30 /////////////////////////////////////////////////////////////////////////
a61af66fc99e Initial load
duke
parents:
diff changeset
31
a61af66fc99e Initial load
duke
parents:
diff changeset
32 // highest ranked free list lock rank
a61af66fc99e Initial load
duke
parents:
diff changeset
33 int CompactibleFreeListSpace::_lockRank = Mutex::leaf + 3;
a61af66fc99e Initial load
duke
parents:
diff changeset
34
a61af66fc99e Initial load
duke
parents:
diff changeset
35 // Constructor
a61af66fc99e Initial load
duke
parents:
diff changeset
36 CompactibleFreeListSpace::CompactibleFreeListSpace(BlockOffsetSharedArray* bs,
a61af66fc99e Initial load
duke
parents:
diff changeset
37 MemRegion mr, bool use_adaptive_freelists,
a61af66fc99e Initial load
duke
parents:
diff changeset
38 FreeBlockDictionary::DictionaryChoice dictionaryChoice) :
a61af66fc99e Initial load
duke
parents:
diff changeset
39 _dictionaryChoice(dictionaryChoice),
a61af66fc99e Initial load
duke
parents:
diff changeset
40 _adaptive_freelists(use_adaptive_freelists),
a61af66fc99e Initial load
duke
parents:
diff changeset
41 _bt(bs, mr),
a61af66fc99e Initial load
duke
parents:
diff changeset
42 // free list locks are in the range of values taken by _lockRank
a61af66fc99e Initial load
duke
parents:
diff changeset
43 // This range currently is [_leaf+2, _leaf+3]
a61af66fc99e Initial load
duke
parents:
diff changeset
44 // Note: this requires that CFLspace c'tors
a61af66fc99e Initial load
duke
parents:
diff changeset
45 // are called serially in the order in which the locks are
a61af66fc99e Initial load
duke
parents:
diff changeset
46 // are acquired in the program text. This is true today.
a61af66fc99e Initial load
duke
parents:
diff changeset
47 _freelistLock(_lockRank--, "CompactibleFreeListSpace._lock", true),
a61af66fc99e Initial load
duke
parents:
diff changeset
48 _parDictionaryAllocLock(Mutex::leaf - 1, // == rank(ExpandHeap_lock) - 1
a61af66fc99e Initial load
duke
parents:
diff changeset
49 "CompactibleFreeListSpace._dict_par_lock", true),
a61af66fc99e Initial load
duke
parents:
diff changeset
50 _rescan_task_size(CardTableModRefBS::card_size_in_words * BitsPerWord *
a61af66fc99e Initial load
duke
parents:
diff changeset
51 CMSRescanMultiple),
a61af66fc99e Initial load
duke
parents:
diff changeset
52 _marking_task_size(CardTableModRefBS::card_size_in_words * BitsPerWord *
a61af66fc99e Initial load
duke
parents:
diff changeset
53 CMSConcMarkMultiple),
a61af66fc99e Initial load
duke
parents:
diff changeset
54 _collector(NULL)
a61af66fc99e Initial load
duke
parents:
diff changeset
55 {
a61af66fc99e Initial load
duke
parents:
diff changeset
56 _bt.set_space(this);
263
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 187
diff changeset
57 initialize(mr, SpaceDecorator::Clear, SpaceDecorator::Mangle);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
58 // We have all of "mr", all of which we place in the dictionary
a61af66fc99e Initial load
duke
parents:
diff changeset
59 // as one big chunk. We'll need to decide here which of several
a61af66fc99e Initial load
duke
parents:
diff changeset
60 // possible alternative dictionary implementations to use. For
a61af66fc99e Initial load
duke
parents:
diff changeset
61 // now the choice is easy, since we have only one working
a61af66fc99e Initial load
duke
parents:
diff changeset
62 // implementation, namely, the simple binary tree (splaying
a61af66fc99e Initial load
duke
parents:
diff changeset
63 // temporarily disabled).
a61af66fc99e Initial load
duke
parents:
diff changeset
64 switch (dictionaryChoice) {
a61af66fc99e Initial load
duke
parents:
diff changeset
65 case FreeBlockDictionary::dictionaryBinaryTree:
a61af66fc99e Initial load
duke
parents:
diff changeset
66 _dictionary = new BinaryTreeDictionary(mr);
a61af66fc99e Initial load
duke
parents:
diff changeset
67 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
68 case FreeBlockDictionary::dictionarySplayTree:
a61af66fc99e Initial load
duke
parents:
diff changeset
69 case FreeBlockDictionary::dictionarySkipList:
a61af66fc99e Initial load
duke
parents:
diff changeset
70 default:
a61af66fc99e Initial load
duke
parents:
diff changeset
71 warning("dictionaryChoice: selected option not understood; using"
a61af66fc99e Initial load
duke
parents:
diff changeset
72 " default BinaryTreeDictionary implementation instead.");
a61af66fc99e Initial load
duke
parents:
diff changeset
73 _dictionary = new BinaryTreeDictionary(mr);
a61af66fc99e Initial load
duke
parents:
diff changeset
74 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
75 }
a61af66fc99e Initial load
duke
parents:
diff changeset
76 splitBirth(mr.word_size());
a61af66fc99e Initial load
duke
parents:
diff changeset
77 assert(_dictionary != NULL, "CMS dictionary initialization");
a61af66fc99e Initial load
duke
parents:
diff changeset
78 // The indexed free lists are initially all empty and are lazily
a61af66fc99e Initial load
duke
parents:
diff changeset
79 // filled in on demand. Initialize the array elements to NULL.
a61af66fc99e Initial load
duke
parents:
diff changeset
80 initializeIndexedFreeListArray();
a61af66fc99e Initial load
duke
parents:
diff changeset
81
a61af66fc99e Initial load
duke
parents:
diff changeset
82 // Not using adaptive free lists assumes that allocation is first
a61af66fc99e Initial load
duke
parents:
diff changeset
83 // from the linAB's. Also a cms perm gen which can be compacted
a61af66fc99e Initial load
duke
parents:
diff changeset
84 // has to have the klass's klassKlass allocated at a lower
a61af66fc99e Initial load
duke
parents:
diff changeset
85 // address in the heap than the klass so that the klassKlass is
a61af66fc99e Initial load
duke
parents:
diff changeset
86 // moved to its new location before the klass is moved.
a61af66fc99e Initial load
duke
parents:
diff changeset
87 // Set the _refillSize for the linear allocation blocks
a61af66fc99e Initial load
duke
parents:
diff changeset
88 if (!use_adaptive_freelists) {
a61af66fc99e Initial load
duke
parents:
diff changeset
89 FreeChunk* fc = _dictionary->getChunk(mr.word_size());
a61af66fc99e Initial load
duke
parents:
diff changeset
90 // The small linAB initially has all the space and will allocate
a61af66fc99e Initial load
duke
parents:
diff changeset
91 // a chunk of any size.
a61af66fc99e Initial load
duke
parents:
diff changeset
92 HeapWord* addr = (HeapWord*) fc;
a61af66fc99e Initial load
duke
parents:
diff changeset
93 _smallLinearAllocBlock.set(addr, fc->size() ,
a61af66fc99e Initial load
duke
parents:
diff changeset
94 1024*SmallForLinearAlloc, fc->size());
a61af66fc99e Initial load
duke
parents:
diff changeset
95 // Note that _unallocated_block is not updated here.
a61af66fc99e Initial load
duke
parents:
diff changeset
96 // Allocations from the linear allocation block should
a61af66fc99e Initial load
duke
parents:
diff changeset
97 // update it.
a61af66fc99e Initial load
duke
parents:
diff changeset
98 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
99 _smallLinearAllocBlock.set(0, 0, 1024*SmallForLinearAlloc,
a61af66fc99e Initial load
duke
parents:
diff changeset
100 SmallForLinearAlloc);
a61af66fc99e Initial load
duke
parents:
diff changeset
101 }
a61af66fc99e Initial load
duke
parents:
diff changeset
102 // CMSIndexedFreeListReplenish should be at least 1
a61af66fc99e Initial load
duke
parents:
diff changeset
103 CMSIndexedFreeListReplenish = MAX2((uintx)1, CMSIndexedFreeListReplenish);
a61af66fc99e Initial load
duke
parents:
diff changeset
104 _promoInfo.setSpace(this);
a61af66fc99e Initial load
duke
parents:
diff changeset
105 if (UseCMSBestFit) {
a61af66fc99e Initial load
duke
parents:
diff changeset
106 _fitStrategy = FreeBlockBestFitFirst;
a61af66fc99e Initial load
duke
parents:
diff changeset
107 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
108 _fitStrategy = FreeBlockStrategyNone;
a61af66fc99e Initial load
duke
parents:
diff changeset
109 }
a61af66fc99e Initial load
duke
parents:
diff changeset
110 checkFreeListConsistency();
a61af66fc99e Initial load
duke
parents:
diff changeset
111
a61af66fc99e Initial load
duke
parents:
diff changeset
112 // Initialize locks for parallel case.
a61af66fc99e Initial load
duke
parents:
diff changeset
113 if (ParallelGCThreads > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
114 for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
a61af66fc99e Initial load
duke
parents:
diff changeset
115 _indexedFreeListParLocks[i] = new Mutex(Mutex::leaf - 1, // == ExpandHeap_lock - 1
a61af66fc99e Initial load
duke
parents:
diff changeset
116 "a freelist par lock",
a61af66fc99e Initial load
duke
parents:
diff changeset
117 true);
a61af66fc99e Initial load
duke
parents:
diff changeset
118 if (_indexedFreeListParLocks[i] == NULL)
a61af66fc99e Initial load
duke
parents:
diff changeset
119 vm_exit_during_initialization("Could not allocate a par lock");
a61af66fc99e Initial load
duke
parents:
diff changeset
120 DEBUG_ONLY(
a61af66fc99e Initial load
duke
parents:
diff changeset
121 _indexedFreeList[i].set_protecting_lock(_indexedFreeListParLocks[i]);
a61af66fc99e Initial load
duke
parents:
diff changeset
122 )
a61af66fc99e Initial load
duke
parents:
diff changeset
123 }
a61af66fc99e Initial load
duke
parents:
diff changeset
124 _dictionary->set_par_lock(&_parDictionaryAllocLock);
a61af66fc99e Initial load
duke
parents:
diff changeset
125 }
a61af66fc99e Initial load
duke
parents:
diff changeset
126 }
a61af66fc99e Initial load
duke
parents:
diff changeset
127
a61af66fc99e Initial load
duke
parents:
diff changeset
128 // Like CompactibleSpace forward() but always calls cross_threshold() to
a61af66fc99e Initial load
duke
parents:
diff changeset
129 // update the block offset table. Removed initialize_threshold call because
a61af66fc99e Initial load
duke
parents:
diff changeset
130 // CFLS does not use a block offset array for contiguous spaces.
a61af66fc99e Initial load
duke
parents:
diff changeset
131 HeapWord* CompactibleFreeListSpace::forward(oop q, size_t size,
a61af66fc99e Initial load
duke
parents:
diff changeset
132 CompactPoint* cp, HeapWord* compact_top) {
a61af66fc99e Initial load
duke
parents:
diff changeset
133 // q is alive
a61af66fc99e Initial load
duke
parents:
diff changeset
134 // First check if we should switch compaction space
a61af66fc99e Initial load
duke
parents:
diff changeset
135 assert(this == cp->space, "'this' should be current compaction space.");
a61af66fc99e Initial load
duke
parents:
diff changeset
136 size_t compaction_max_size = pointer_delta(end(), compact_top);
a61af66fc99e Initial load
duke
parents:
diff changeset
137 assert(adjustObjectSize(size) == cp->space->adjust_object_size_v(size),
a61af66fc99e Initial load
duke
parents:
diff changeset
138 "virtual adjustObjectSize_v() method is not correct");
a61af66fc99e Initial load
duke
parents:
diff changeset
139 size_t adjusted_size = adjustObjectSize(size);
a61af66fc99e Initial load
duke
parents:
diff changeset
140 assert(compaction_max_size >= MinChunkSize || compaction_max_size == 0,
a61af66fc99e Initial load
duke
parents:
diff changeset
141 "no small fragments allowed");
a61af66fc99e Initial load
duke
parents:
diff changeset
142 assert(minimum_free_block_size() == MinChunkSize,
a61af66fc99e Initial load
duke
parents:
diff changeset
143 "for de-virtualized reference below");
a61af66fc99e Initial load
duke
parents:
diff changeset
144 // Can't leave a nonzero size, residual fragment smaller than MinChunkSize
a61af66fc99e Initial load
duke
parents:
diff changeset
145 if (adjusted_size + MinChunkSize > compaction_max_size &&
a61af66fc99e Initial load
duke
parents:
diff changeset
146 adjusted_size != compaction_max_size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
147 do {
a61af66fc99e Initial load
duke
parents:
diff changeset
148 // switch to next compaction space
a61af66fc99e Initial load
duke
parents:
diff changeset
149 cp->space->set_compaction_top(compact_top);
a61af66fc99e Initial load
duke
parents:
diff changeset
150 cp->space = cp->space->next_compaction_space();
a61af66fc99e Initial load
duke
parents:
diff changeset
151 if (cp->space == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
152 cp->gen = GenCollectedHeap::heap()->prev_gen(cp->gen);
a61af66fc99e Initial load
duke
parents:
diff changeset
153 assert(cp->gen != NULL, "compaction must succeed");
a61af66fc99e Initial load
duke
parents:
diff changeset
154 cp->space = cp->gen->first_compaction_space();
a61af66fc99e Initial load
duke
parents:
diff changeset
155 assert(cp->space != NULL, "generation must have a first compaction space");
a61af66fc99e Initial load
duke
parents:
diff changeset
156 }
a61af66fc99e Initial load
duke
parents:
diff changeset
157 compact_top = cp->space->bottom();
a61af66fc99e Initial load
duke
parents:
diff changeset
158 cp->space->set_compaction_top(compact_top);
a61af66fc99e Initial load
duke
parents:
diff changeset
159 // The correct adjusted_size may not be the same as that for this method
a61af66fc99e Initial load
duke
parents:
diff changeset
160 // (i.e., cp->space may no longer be "this" so adjust the size again.
a61af66fc99e Initial load
duke
parents:
diff changeset
161 // Use the virtual method which is not used above to save the virtual
a61af66fc99e Initial load
duke
parents:
diff changeset
162 // dispatch.
a61af66fc99e Initial load
duke
parents:
diff changeset
163 adjusted_size = cp->space->adjust_object_size_v(size);
a61af66fc99e Initial load
duke
parents:
diff changeset
164 compaction_max_size = pointer_delta(cp->space->end(), compact_top);
a61af66fc99e Initial load
duke
parents:
diff changeset
165 assert(cp->space->minimum_free_block_size() == 0, "just checking");
a61af66fc99e Initial load
duke
parents:
diff changeset
166 } while (adjusted_size > compaction_max_size);
a61af66fc99e Initial load
duke
parents:
diff changeset
167 }
a61af66fc99e Initial load
duke
parents:
diff changeset
168
a61af66fc99e Initial load
duke
parents:
diff changeset
169 // store the forwarding pointer into the mark word
a61af66fc99e Initial load
duke
parents:
diff changeset
170 if ((HeapWord*)q != compact_top) {
a61af66fc99e Initial load
duke
parents:
diff changeset
171 q->forward_to(oop(compact_top));
a61af66fc99e Initial load
duke
parents:
diff changeset
172 assert(q->is_gc_marked(), "encoding the pointer should preserve the mark");
a61af66fc99e Initial load
duke
parents:
diff changeset
173 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
174 // if the object isn't moving we can just set the mark to the default
a61af66fc99e Initial load
duke
parents:
diff changeset
175 // mark and handle it specially later on.
a61af66fc99e Initial load
duke
parents:
diff changeset
176 q->init_mark();
a61af66fc99e Initial load
duke
parents:
diff changeset
177 assert(q->forwardee() == NULL, "should be forwarded to NULL");
a61af66fc99e Initial load
duke
parents:
diff changeset
178 }
a61af66fc99e Initial load
duke
parents:
diff changeset
179
113
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 12
diff changeset
180 VALIDATE_MARK_SWEEP_ONLY(MarkSweep::register_live_oop(q, adjusted_size));
0
a61af66fc99e Initial load
duke
parents:
diff changeset
181 compact_top += adjusted_size;
a61af66fc99e Initial load
duke
parents:
diff changeset
182
a61af66fc99e Initial load
duke
parents:
diff changeset
183 // we need to update the offset table so that the beginnings of objects can be
a61af66fc99e Initial load
duke
parents:
diff changeset
184 // found during scavenge. Note that we are updating the offset table based on
a61af66fc99e Initial load
duke
parents:
diff changeset
185 // where the object will be once the compaction phase finishes.
a61af66fc99e Initial load
duke
parents:
diff changeset
186
a61af66fc99e Initial load
duke
parents:
diff changeset
187 // Always call cross_threshold(). A contiguous space can only call it when
a61af66fc99e Initial load
duke
parents:
diff changeset
188 // the compaction_top exceeds the current threshold but not for an
a61af66fc99e Initial load
duke
parents:
diff changeset
189 // non-contiguous space.
a61af66fc99e Initial load
duke
parents:
diff changeset
190 cp->threshold =
a61af66fc99e Initial load
duke
parents:
diff changeset
191 cp->space->cross_threshold(compact_top - adjusted_size, compact_top);
a61af66fc99e Initial load
duke
parents:
diff changeset
192 return compact_top;
a61af66fc99e Initial load
duke
parents:
diff changeset
193 }
a61af66fc99e Initial load
duke
parents:
diff changeset
194
a61af66fc99e Initial load
duke
parents:
diff changeset
195 // A modified copy of OffsetTableContigSpace::cross_threshold() with _offsets -> _bt
a61af66fc99e Initial load
duke
parents:
diff changeset
196 // and use of single_block instead of alloc_block. The name here is not really
a61af66fc99e Initial load
duke
parents:
diff changeset
197 // appropriate - maybe a more general name could be invented for both the
a61af66fc99e Initial load
duke
parents:
diff changeset
198 // contiguous and noncontiguous spaces.
a61af66fc99e Initial load
duke
parents:
diff changeset
199
a61af66fc99e Initial load
duke
parents:
diff changeset
200 HeapWord* CompactibleFreeListSpace::cross_threshold(HeapWord* start, HeapWord* the_end) {
a61af66fc99e Initial load
duke
parents:
diff changeset
201 _bt.single_block(start, the_end);
a61af66fc99e Initial load
duke
parents:
diff changeset
202 return end();
a61af66fc99e Initial load
duke
parents:
diff changeset
203 }
a61af66fc99e Initial load
duke
parents:
diff changeset
204
a61af66fc99e Initial load
duke
parents:
diff changeset
205 // Initialize them to NULL.
a61af66fc99e Initial load
duke
parents:
diff changeset
206 void CompactibleFreeListSpace::initializeIndexedFreeListArray() {
a61af66fc99e Initial load
duke
parents:
diff changeset
207 for (size_t i = 0; i < IndexSetSize; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
208 // Note that on platforms where objects are double word aligned,
a61af66fc99e Initial load
duke
parents:
diff changeset
209 // the odd array elements are not used. It is convenient, however,
a61af66fc99e Initial load
duke
parents:
diff changeset
210 // to map directly from the object size to the array element.
a61af66fc99e Initial load
duke
parents:
diff changeset
211 _indexedFreeList[i].reset(IndexSetSize);
a61af66fc99e Initial load
duke
parents:
diff changeset
212 _indexedFreeList[i].set_size(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
213 assert(_indexedFreeList[i].count() == 0, "reset check failed");
a61af66fc99e Initial load
duke
parents:
diff changeset
214 assert(_indexedFreeList[i].head() == NULL, "reset check failed");
a61af66fc99e Initial load
duke
parents:
diff changeset
215 assert(_indexedFreeList[i].tail() == NULL, "reset check failed");
a61af66fc99e Initial load
duke
parents:
diff changeset
216 assert(_indexedFreeList[i].hint() == IndexSetSize, "reset check failed");
a61af66fc99e Initial load
duke
parents:
diff changeset
217 }
a61af66fc99e Initial load
duke
parents:
diff changeset
218 }
a61af66fc99e Initial load
duke
parents:
diff changeset
219
a61af66fc99e Initial load
duke
parents:
diff changeset
220 void CompactibleFreeListSpace::resetIndexedFreeListArray() {
a61af66fc99e Initial load
duke
parents:
diff changeset
221 for (int i = 1; i < IndexSetSize; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
222 assert(_indexedFreeList[i].size() == (size_t) i,
a61af66fc99e Initial load
duke
parents:
diff changeset
223 "Indexed free list sizes are incorrect");
a61af66fc99e Initial load
duke
parents:
diff changeset
224 _indexedFreeList[i].reset(IndexSetSize);
a61af66fc99e Initial load
duke
parents:
diff changeset
225 assert(_indexedFreeList[i].count() == 0, "reset check failed");
a61af66fc99e Initial load
duke
parents:
diff changeset
226 assert(_indexedFreeList[i].head() == NULL, "reset check failed");
a61af66fc99e Initial load
duke
parents:
diff changeset
227 assert(_indexedFreeList[i].tail() == NULL, "reset check failed");
a61af66fc99e Initial load
duke
parents:
diff changeset
228 assert(_indexedFreeList[i].hint() == IndexSetSize, "reset check failed");
a61af66fc99e Initial load
duke
parents:
diff changeset
229 }
a61af66fc99e Initial load
duke
parents:
diff changeset
230 }
a61af66fc99e Initial load
duke
parents:
diff changeset
231
a61af66fc99e Initial load
duke
parents:
diff changeset
232 void CompactibleFreeListSpace::reset(MemRegion mr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
233 resetIndexedFreeListArray();
a61af66fc99e Initial load
duke
parents:
diff changeset
234 dictionary()->reset();
a61af66fc99e Initial load
duke
parents:
diff changeset
235 if (BlockOffsetArrayUseUnallocatedBlock) {
a61af66fc99e Initial load
duke
parents:
diff changeset
236 assert(end() == mr.end(), "We are compacting to the bottom of CMS gen");
a61af66fc99e Initial load
duke
parents:
diff changeset
237 // Everything's allocated until proven otherwise.
a61af66fc99e Initial load
duke
parents:
diff changeset
238 _bt.set_unallocated_block(end());
a61af66fc99e Initial load
duke
parents:
diff changeset
239 }
a61af66fc99e Initial load
duke
parents:
diff changeset
240 if (!mr.is_empty()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
241 assert(mr.word_size() >= MinChunkSize, "Chunk size is too small");
a61af66fc99e Initial load
duke
parents:
diff changeset
242 _bt.single_block(mr.start(), mr.word_size());
a61af66fc99e Initial load
duke
parents:
diff changeset
243 FreeChunk* fc = (FreeChunk*) mr.start();
a61af66fc99e Initial load
duke
parents:
diff changeset
244 fc->setSize(mr.word_size());
a61af66fc99e Initial load
duke
parents:
diff changeset
245 if (mr.word_size() >= IndexSetSize ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
246 returnChunkToDictionary(fc);
a61af66fc99e Initial load
duke
parents:
diff changeset
247 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
248 _bt.verify_not_unallocated((HeapWord*)fc, fc->size());
a61af66fc99e Initial load
duke
parents:
diff changeset
249 _indexedFreeList[mr.word_size()].returnChunkAtHead(fc);
a61af66fc99e Initial load
duke
parents:
diff changeset
250 }
a61af66fc99e Initial load
duke
parents:
diff changeset
251 }
a61af66fc99e Initial load
duke
parents:
diff changeset
252 _promoInfo.reset();
a61af66fc99e Initial load
duke
parents:
diff changeset
253 _smallLinearAllocBlock._ptr = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
254 _smallLinearAllocBlock._word_size = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
255 }
a61af66fc99e Initial load
duke
parents:
diff changeset
256
a61af66fc99e Initial load
duke
parents:
diff changeset
257 void CompactibleFreeListSpace::reset_after_compaction() {
a61af66fc99e Initial load
duke
parents:
diff changeset
258 // Reset the space to the new reality - one free chunk.
a61af66fc99e Initial load
duke
parents:
diff changeset
259 MemRegion mr(compaction_top(), end());
a61af66fc99e Initial load
duke
parents:
diff changeset
260 reset(mr);
a61af66fc99e Initial load
duke
parents:
diff changeset
261 // Now refill the linear allocation block(s) if possible.
a61af66fc99e Initial load
duke
parents:
diff changeset
262 if (_adaptive_freelists) {
a61af66fc99e Initial load
duke
parents:
diff changeset
263 refillLinearAllocBlocksIfNeeded();
a61af66fc99e Initial load
duke
parents:
diff changeset
264 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
265 // Place as much of mr in the linAB as we can get,
a61af66fc99e Initial load
duke
parents:
diff changeset
266 // provided it was big enough to go into the dictionary.
a61af66fc99e Initial load
duke
parents:
diff changeset
267 FreeChunk* fc = dictionary()->findLargestDict();
a61af66fc99e Initial load
duke
parents:
diff changeset
268 if (fc != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
269 assert(fc->size() == mr.word_size(),
a61af66fc99e Initial load
duke
parents:
diff changeset
270 "Why was the chunk broken up?");
a61af66fc99e Initial load
duke
parents:
diff changeset
271 removeChunkFromDictionary(fc);
a61af66fc99e Initial load
duke
parents:
diff changeset
272 HeapWord* addr = (HeapWord*) fc;
a61af66fc99e Initial load
duke
parents:
diff changeset
273 _smallLinearAllocBlock.set(addr, fc->size() ,
a61af66fc99e Initial load
duke
parents:
diff changeset
274 1024*SmallForLinearAlloc, fc->size());
a61af66fc99e Initial load
duke
parents:
diff changeset
275 // Note that _unallocated_block is not updated here.
a61af66fc99e Initial load
duke
parents:
diff changeset
276 }
a61af66fc99e Initial load
duke
parents:
diff changeset
277 }
a61af66fc99e Initial load
duke
parents:
diff changeset
278 }
a61af66fc99e Initial load
duke
parents:
diff changeset
279
a61af66fc99e Initial load
duke
parents:
diff changeset
280 // Walks the entire dictionary, returning a coterminal
a61af66fc99e Initial load
duke
parents:
diff changeset
281 // chunk, if it exists. Use with caution since it involves
a61af66fc99e Initial load
duke
parents:
diff changeset
282 // a potentially complete walk of a potentially large tree.
a61af66fc99e Initial load
duke
parents:
diff changeset
283 FreeChunk* CompactibleFreeListSpace::find_chunk_at_end() {
a61af66fc99e Initial load
duke
parents:
diff changeset
284
a61af66fc99e Initial load
duke
parents:
diff changeset
285 assert_lock_strong(&_freelistLock);
a61af66fc99e Initial load
duke
parents:
diff changeset
286
a61af66fc99e Initial load
duke
parents:
diff changeset
287 return dictionary()->find_chunk_ends_at(end());
a61af66fc99e Initial load
duke
parents:
diff changeset
288 }
a61af66fc99e Initial load
duke
parents:
diff changeset
289
a61af66fc99e Initial load
duke
parents:
diff changeset
290
a61af66fc99e Initial load
duke
parents:
diff changeset
291 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
292 void CompactibleFreeListSpace::initializeIndexedFreeListArrayReturnedBytes() {
a61af66fc99e Initial load
duke
parents:
diff changeset
293 for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
a61af66fc99e Initial load
duke
parents:
diff changeset
294 _indexedFreeList[i].allocation_stats()->set_returnedBytes(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
295 }
a61af66fc99e Initial load
duke
parents:
diff changeset
296 }
a61af66fc99e Initial load
duke
parents:
diff changeset
297
a61af66fc99e Initial load
duke
parents:
diff changeset
298 size_t CompactibleFreeListSpace::sumIndexedFreeListArrayReturnedBytes() {
a61af66fc99e Initial load
duke
parents:
diff changeset
299 size_t sum = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
300 for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
a61af66fc99e Initial load
duke
parents:
diff changeset
301 sum += _indexedFreeList[i].allocation_stats()->returnedBytes();
a61af66fc99e Initial load
duke
parents:
diff changeset
302 }
a61af66fc99e Initial load
duke
parents:
diff changeset
303 return sum;
a61af66fc99e Initial load
duke
parents:
diff changeset
304 }
a61af66fc99e Initial load
duke
parents:
diff changeset
305
a61af66fc99e Initial load
duke
parents:
diff changeset
306 size_t CompactibleFreeListSpace::totalCountInIndexedFreeLists() const {
a61af66fc99e Initial load
duke
parents:
diff changeset
307 size_t count = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
308 for (int i = MinChunkSize; i < IndexSetSize; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
309 debug_only(
a61af66fc99e Initial load
duke
parents:
diff changeset
310 ssize_t total_list_count = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
311 for (FreeChunk* fc = _indexedFreeList[i].head(); fc != NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
312 fc = fc->next()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
313 total_list_count++;
a61af66fc99e Initial load
duke
parents:
diff changeset
314 }
a61af66fc99e Initial load
duke
parents:
diff changeset
315 assert(total_list_count == _indexedFreeList[i].count(),
a61af66fc99e Initial load
duke
parents:
diff changeset
316 "Count in list is incorrect");
a61af66fc99e Initial load
duke
parents:
diff changeset
317 )
a61af66fc99e Initial load
duke
parents:
diff changeset
318 count += _indexedFreeList[i].count();
a61af66fc99e Initial load
duke
parents:
diff changeset
319 }
a61af66fc99e Initial load
duke
parents:
diff changeset
320 return count;
a61af66fc99e Initial load
duke
parents:
diff changeset
321 }
a61af66fc99e Initial load
duke
parents:
diff changeset
322
a61af66fc99e Initial load
duke
parents:
diff changeset
323 size_t CompactibleFreeListSpace::totalCount() {
a61af66fc99e Initial load
duke
parents:
diff changeset
324 size_t num = totalCountInIndexedFreeLists();
a61af66fc99e Initial load
duke
parents:
diff changeset
325 num += dictionary()->totalCount();
a61af66fc99e Initial load
duke
parents:
diff changeset
326 if (_smallLinearAllocBlock._word_size != 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
327 num++;
a61af66fc99e Initial load
duke
parents:
diff changeset
328 }
a61af66fc99e Initial load
duke
parents:
diff changeset
329 return num;
a61af66fc99e Initial load
duke
parents:
diff changeset
330 }
a61af66fc99e Initial load
duke
parents:
diff changeset
331 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
332
a61af66fc99e Initial load
duke
parents:
diff changeset
333 bool CompactibleFreeListSpace::is_free_block(const HeapWord* p) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
334 FreeChunk* fc = (FreeChunk*) p;
a61af66fc99e Initial load
duke
parents:
diff changeset
335 return fc->isFree();
a61af66fc99e Initial load
duke
parents:
diff changeset
336 }
a61af66fc99e Initial load
duke
parents:
diff changeset
337
a61af66fc99e Initial load
duke
parents:
diff changeset
338 size_t CompactibleFreeListSpace::used() const {
a61af66fc99e Initial load
duke
parents:
diff changeset
339 return capacity() - free();
a61af66fc99e Initial load
duke
parents:
diff changeset
340 }
a61af66fc99e Initial load
duke
parents:
diff changeset
341
a61af66fc99e Initial load
duke
parents:
diff changeset
342 size_t CompactibleFreeListSpace::free() const {
a61af66fc99e Initial load
duke
parents:
diff changeset
343 // "MT-safe, but not MT-precise"(TM), if you will: i.e.
a61af66fc99e Initial load
duke
parents:
diff changeset
344 // if you do this while the structures are in flux you
a61af66fc99e Initial load
duke
parents:
diff changeset
345 // may get an approximate answer only; for instance
a61af66fc99e Initial load
duke
parents:
diff changeset
346 // because there is concurrent allocation either
a61af66fc99e Initial load
duke
parents:
diff changeset
347 // directly by mutators or for promotion during a GC.
a61af66fc99e Initial load
duke
parents:
diff changeset
348 // It's "MT-safe", however, in the sense that you are guaranteed
a61af66fc99e Initial load
duke
parents:
diff changeset
349 // not to crash and burn, for instance, because of walking
a61af66fc99e Initial load
duke
parents:
diff changeset
350 // pointers that could disappear as you were walking them.
a61af66fc99e Initial load
duke
parents:
diff changeset
351 // The approximation is because the various components
a61af66fc99e Initial load
duke
parents:
diff changeset
352 // that are read below are not read atomically (and
a61af66fc99e Initial load
duke
parents:
diff changeset
353 // further the computation of totalSizeInIndexedFreeLists()
a61af66fc99e Initial load
duke
parents:
diff changeset
354 // is itself a non-atomic computation. The normal use of
a61af66fc99e Initial load
duke
parents:
diff changeset
355 // this is during a resize operation at the end of GC
a61af66fc99e Initial load
duke
parents:
diff changeset
356 // and at that time you are guaranteed to get the
a61af66fc99e Initial load
duke
parents:
diff changeset
357 // correct actual value. However, for instance, this is
a61af66fc99e Initial load
duke
parents:
diff changeset
358 // also read completely asynchronously by the "perf-sampler"
a61af66fc99e Initial load
duke
parents:
diff changeset
359 // that supports jvmstat, and you are apt to see the values
a61af66fc99e Initial load
duke
parents:
diff changeset
360 // flicker in such cases.
a61af66fc99e Initial load
duke
parents:
diff changeset
361 assert(_dictionary != NULL, "No _dictionary?");
a61af66fc99e Initial load
duke
parents:
diff changeset
362 return (_dictionary->totalChunkSize(DEBUG_ONLY(freelistLock())) +
a61af66fc99e Initial load
duke
parents:
diff changeset
363 totalSizeInIndexedFreeLists() +
a61af66fc99e Initial load
duke
parents:
diff changeset
364 _smallLinearAllocBlock._word_size) * HeapWordSize;
a61af66fc99e Initial load
duke
parents:
diff changeset
365 }
a61af66fc99e Initial load
duke
parents:
diff changeset
366
a61af66fc99e Initial load
duke
parents:
diff changeset
367 size_t CompactibleFreeListSpace::max_alloc_in_words() const {
a61af66fc99e Initial load
duke
parents:
diff changeset
368 assert(_dictionary != NULL, "No _dictionary?");
a61af66fc99e Initial load
duke
parents:
diff changeset
369 assert_locked();
a61af66fc99e Initial load
duke
parents:
diff changeset
370 size_t res = _dictionary->maxChunkSize();
a61af66fc99e Initial load
duke
parents:
diff changeset
371 res = MAX2(res, MIN2(_smallLinearAllocBlock._word_size,
a61af66fc99e Initial load
duke
parents:
diff changeset
372 (size_t) SmallForLinearAlloc - 1));
a61af66fc99e Initial load
duke
parents:
diff changeset
373 // XXX the following could potentially be pretty slow;
a61af66fc99e Initial load
duke
parents:
diff changeset
374 // should one, pesimally for the rare cases when res
a61af66fc99e Initial load
duke
parents:
diff changeset
375 // caclulated above is less than IndexSetSize,
a61af66fc99e Initial load
duke
parents:
diff changeset
376 // just return res calculated above? My reasoning was that
a61af66fc99e Initial load
duke
parents:
diff changeset
377 // those cases will be so rare that the extra time spent doesn't
a61af66fc99e Initial load
duke
parents:
diff changeset
378 // really matter....
a61af66fc99e Initial load
duke
parents:
diff changeset
379 // Note: do not change the loop test i >= res + IndexSetStride
a61af66fc99e Initial load
duke
parents:
diff changeset
380 // to i > res below, because i is unsigned and res may be zero.
a61af66fc99e Initial load
duke
parents:
diff changeset
381 for (size_t i = IndexSetSize - 1; i >= res + IndexSetStride;
a61af66fc99e Initial load
duke
parents:
diff changeset
382 i -= IndexSetStride) {
a61af66fc99e Initial load
duke
parents:
diff changeset
383 if (_indexedFreeList[i].head() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
384 assert(_indexedFreeList[i].count() != 0, "Inconsistent FreeList");
a61af66fc99e Initial load
duke
parents:
diff changeset
385 return i;
a61af66fc99e Initial load
duke
parents:
diff changeset
386 }
a61af66fc99e Initial load
duke
parents:
diff changeset
387 }
a61af66fc99e Initial load
duke
parents:
diff changeset
388 return res;
a61af66fc99e Initial load
duke
parents:
diff changeset
389 }
a61af66fc99e Initial load
duke
parents:
diff changeset
390
a61af66fc99e Initial load
duke
parents:
diff changeset
391 void CompactibleFreeListSpace::reportFreeListStatistics() const {
a61af66fc99e Initial load
duke
parents:
diff changeset
392 assert_lock_strong(&_freelistLock);
a61af66fc99e Initial load
duke
parents:
diff changeset
393 assert(PrintFLSStatistics != 0, "Reporting error");
a61af66fc99e Initial load
duke
parents:
diff changeset
394 _dictionary->reportStatistics();
a61af66fc99e Initial load
duke
parents:
diff changeset
395 if (PrintFLSStatistics > 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
396 reportIndexedFreeListStatistics();
a61af66fc99e Initial load
duke
parents:
diff changeset
397 size_t totalSize = totalSizeInIndexedFreeLists() +
a61af66fc99e Initial load
duke
parents:
diff changeset
398 _dictionary->totalChunkSize(DEBUG_ONLY(freelistLock()));
a61af66fc99e Initial load
duke
parents:
diff changeset
399 gclog_or_tty->print(" free=%ld frag=%1.4f\n", totalSize, flsFrag());
a61af66fc99e Initial load
duke
parents:
diff changeset
400 }
a61af66fc99e Initial load
duke
parents:
diff changeset
401 }
a61af66fc99e Initial load
duke
parents:
diff changeset
402
a61af66fc99e Initial load
duke
parents:
diff changeset
403 void CompactibleFreeListSpace::reportIndexedFreeListStatistics() const {
a61af66fc99e Initial load
duke
parents:
diff changeset
404 assert_lock_strong(&_freelistLock);
a61af66fc99e Initial load
duke
parents:
diff changeset
405 gclog_or_tty->print("Statistics for IndexedFreeLists:\n"
a61af66fc99e Initial load
duke
parents:
diff changeset
406 "--------------------------------\n");
a61af66fc99e Initial load
duke
parents:
diff changeset
407 size_t totalSize = totalSizeInIndexedFreeLists();
a61af66fc99e Initial load
duke
parents:
diff changeset
408 size_t freeBlocks = numFreeBlocksInIndexedFreeLists();
a61af66fc99e Initial load
duke
parents:
diff changeset
409 gclog_or_tty->print("Total Free Space: %d\n", totalSize);
a61af66fc99e Initial load
duke
parents:
diff changeset
410 gclog_or_tty->print("Max Chunk Size: %d\n", maxChunkSizeInIndexedFreeLists());
a61af66fc99e Initial load
duke
parents:
diff changeset
411 gclog_or_tty->print("Number of Blocks: %d\n", freeBlocks);
a61af66fc99e Initial load
duke
parents:
diff changeset
412 if (freeBlocks != 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
413 gclog_or_tty->print("Av. Block Size: %d\n", totalSize/freeBlocks);
a61af66fc99e Initial load
duke
parents:
diff changeset
414 }
a61af66fc99e Initial load
duke
parents:
diff changeset
415 }
a61af66fc99e Initial load
duke
parents:
diff changeset
416
a61af66fc99e Initial load
duke
parents:
diff changeset
417 size_t CompactibleFreeListSpace::numFreeBlocksInIndexedFreeLists() const {
a61af66fc99e Initial load
duke
parents:
diff changeset
418 size_t res = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
419 for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
a61af66fc99e Initial load
duke
parents:
diff changeset
420 debug_only(
a61af66fc99e Initial load
duke
parents:
diff changeset
421 ssize_t recount = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
422 for (FreeChunk* fc = _indexedFreeList[i].head(); fc != NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
423 fc = fc->next()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
424 recount += 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
425 }
a61af66fc99e Initial load
duke
parents:
diff changeset
426 assert(recount == _indexedFreeList[i].count(),
a61af66fc99e Initial load
duke
parents:
diff changeset
427 "Incorrect count in list");
a61af66fc99e Initial load
duke
parents:
diff changeset
428 )
a61af66fc99e Initial load
duke
parents:
diff changeset
429 res += _indexedFreeList[i].count();
a61af66fc99e Initial load
duke
parents:
diff changeset
430 }
a61af66fc99e Initial load
duke
parents:
diff changeset
431 return res;
a61af66fc99e Initial load
duke
parents:
diff changeset
432 }
a61af66fc99e Initial load
duke
parents:
diff changeset
433
a61af66fc99e Initial load
duke
parents:
diff changeset
434 size_t CompactibleFreeListSpace::maxChunkSizeInIndexedFreeLists() const {
a61af66fc99e Initial load
duke
parents:
diff changeset
435 for (size_t i = IndexSetSize - 1; i != 0; i -= IndexSetStride) {
a61af66fc99e Initial load
duke
parents:
diff changeset
436 if (_indexedFreeList[i].head() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
437 assert(_indexedFreeList[i].count() != 0, "Inconsistent FreeList");
a61af66fc99e Initial load
duke
parents:
diff changeset
438 return (size_t)i;
a61af66fc99e Initial load
duke
parents:
diff changeset
439 }
a61af66fc99e Initial load
duke
parents:
diff changeset
440 }
a61af66fc99e Initial load
duke
parents:
diff changeset
441 return 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
442 }
a61af66fc99e Initial load
duke
parents:
diff changeset
443
a61af66fc99e Initial load
duke
parents:
diff changeset
444 void CompactibleFreeListSpace::set_end(HeapWord* value) {
a61af66fc99e Initial load
duke
parents:
diff changeset
445 HeapWord* prevEnd = end();
a61af66fc99e Initial load
duke
parents:
diff changeset
446 assert(prevEnd != value, "unnecessary set_end call");
a61af66fc99e Initial load
duke
parents:
diff changeset
447 assert(prevEnd == NULL || value >= unallocated_block(), "New end is below unallocated block");
a61af66fc99e Initial load
duke
parents:
diff changeset
448 _end = value;
a61af66fc99e Initial load
duke
parents:
diff changeset
449 if (prevEnd != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
450 // Resize the underlying block offset table.
a61af66fc99e Initial load
duke
parents:
diff changeset
451 _bt.resize(pointer_delta(value, bottom()));
a61af66fc99e Initial load
duke
parents:
diff changeset
452 if (value <= prevEnd) {
a61af66fc99e Initial load
duke
parents:
diff changeset
453 assert(value >= unallocated_block(), "New end is below unallocated block");
a61af66fc99e Initial load
duke
parents:
diff changeset
454 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
455 // Now, take this new chunk and add it to the free blocks.
a61af66fc99e Initial load
duke
parents:
diff changeset
456 // Note that the BOT has not yet been updated for this block.
a61af66fc99e Initial load
duke
parents:
diff changeset
457 size_t newFcSize = pointer_delta(value, prevEnd);
a61af66fc99e Initial load
duke
parents:
diff changeset
458 // XXX This is REALLY UGLY and should be fixed up. XXX
a61af66fc99e Initial load
duke
parents:
diff changeset
459 if (!_adaptive_freelists && _smallLinearAllocBlock._ptr == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
460 // Mark the boundary of the new block in BOT
a61af66fc99e Initial load
duke
parents:
diff changeset
461 _bt.mark_block(prevEnd, value);
a61af66fc99e Initial load
duke
parents:
diff changeset
462 // put it all in the linAB
a61af66fc99e Initial load
duke
parents:
diff changeset
463 if (ParallelGCThreads == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
464 _smallLinearAllocBlock._ptr = prevEnd;
a61af66fc99e Initial load
duke
parents:
diff changeset
465 _smallLinearAllocBlock._word_size = newFcSize;
a61af66fc99e Initial load
duke
parents:
diff changeset
466 repairLinearAllocBlock(&_smallLinearAllocBlock);
a61af66fc99e Initial load
duke
parents:
diff changeset
467 } else { // ParallelGCThreads > 0
a61af66fc99e Initial load
duke
parents:
diff changeset
468 MutexLockerEx x(parDictionaryAllocLock(),
a61af66fc99e Initial load
duke
parents:
diff changeset
469 Mutex::_no_safepoint_check_flag);
a61af66fc99e Initial load
duke
parents:
diff changeset
470 _smallLinearAllocBlock._ptr = prevEnd;
a61af66fc99e Initial load
duke
parents:
diff changeset
471 _smallLinearAllocBlock._word_size = newFcSize;
a61af66fc99e Initial load
duke
parents:
diff changeset
472 repairLinearAllocBlock(&_smallLinearAllocBlock);
a61af66fc99e Initial load
duke
parents:
diff changeset
473 }
a61af66fc99e Initial load
duke
parents:
diff changeset
474 // Births of chunks put into a LinAB are not recorded. Births
a61af66fc99e Initial load
duke
parents:
diff changeset
475 // of chunks as they are allocated out of a LinAB are.
a61af66fc99e Initial load
duke
parents:
diff changeset
476 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
477 // Add the block to the free lists, if possible coalescing it
a61af66fc99e Initial load
duke
parents:
diff changeset
478 // with the last free block, and update the BOT and census data.
a61af66fc99e Initial load
duke
parents:
diff changeset
479 addChunkToFreeListsAtEndRecordingStats(prevEnd, newFcSize);
a61af66fc99e Initial load
duke
parents:
diff changeset
480 }
a61af66fc99e Initial load
duke
parents:
diff changeset
481 }
a61af66fc99e Initial load
duke
parents:
diff changeset
482 }
a61af66fc99e Initial load
duke
parents:
diff changeset
483 }
a61af66fc99e Initial load
duke
parents:
diff changeset
484
a61af66fc99e Initial load
duke
parents:
diff changeset
485 class FreeListSpace_DCTOC : public Filtering_DCTOC {
a61af66fc99e Initial load
duke
parents:
diff changeset
486 CompactibleFreeListSpace* _cfls;
a61af66fc99e Initial load
duke
parents:
diff changeset
487 CMSCollector* _collector;
a61af66fc99e Initial load
duke
parents:
diff changeset
488 protected:
a61af66fc99e Initial load
duke
parents:
diff changeset
489 // Override.
a61af66fc99e Initial load
duke
parents:
diff changeset
490 #define walk_mem_region_with_cl_DECL(ClosureType) \
a61af66fc99e Initial load
duke
parents:
diff changeset
491 virtual void walk_mem_region_with_cl(MemRegion mr, \
a61af66fc99e Initial load
duke
parents:
diff changeset
492 HeapWord* bottom, HeapWord* top, \
a61af66fc99e Initial load
duke
parents:
diff changeset
493 ClosureType* cl); \
a61af66fc99e Initial load
duke
parents:
diff changeset
494 void walk_mem_region_with_cl_par(MemRegion mr, \
a61af66fc99e Initial load
duke
parents:
diff changeset
495 HeapWord* bottom, HeapWord* top, \
a61af66fc99e Initial load
duke
parents:
diff changeset
496 ClosureType* cl); \
a61af66fc99e Initial load
duke
parents:
diff changeset
497 void walk_mem_region_with_cl_nopar(MemRegion mr, \
a61af66fc99e Initial load
duke
parents:
diff changeset
498 HeapWord* bottom, HeapWord* top, \
a61af66fc99e Initial load
duke
parents:
diff changeset
499 ClosureType* cl)
a61af66fc99e Initial load
duke
parents:
diff changeset
500 walk_mem_region_with_cl_DECL(OopClosure);
a61af66fc99e Initial load
duke
parents:
diff changeset
501 walk_mem_region_with_cl_DECL(FilteringClosure);
a61af66fc99e Initial load
duke
parents:
diff changeset
502
a61af66fc99e Initial load
duke
parents:
diff changeset
503 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
504 FreeListSpace_DCTOC(CompactibleFreeListSpace* sp,
a61af66fc99e Initial load
duke
parents:
diff changeset
505 CMSCollector* collector,
a61af66fc99e Initial load
duke
parents:
diff changeset
506 OopClosure* cl,
a61af66fc99e Initial load
duke
parents:
diff changeset
507 CardTableModRefBS::PrecisionStyle precision,
a61af66fc99e Initial load
duke
parents:
diff changeset
508 HeapWord* boundary) :
a61af66fc99e Initial load
duke
parents:
diff changeset
509 Filtering_DCTOC(sp, cl, precision, boundary),
a61af66fc99e Initial load
duke
parents:
diff changeset
510 _cfls(sp), _collector(collector) {}
a61af66fc99e Initial load
duke
parents:
diff changeset
511 };
a61af66fc99e Initial load
duke
parents:
diff changeset
512
a61af66fc99e Initial load
duke
parents:
diff changeset
513 // We de-virtualize the block-related calls below, since we know that our
a61af66fc99e Initial load
duke
parents:
diff changeset
514 // space is a CompactibleFreeListSpace.
a61af66fc99e Initial load
duke
parents:
diff changeset
515 #define FreeListSpace_DCTOC__walk_mem_region_with_cl_DEFN(ClosureType) \
a61af66fc99e Initial load
duke
parents:
diff changeset
516 void FreeListSpace_DCTOC::walk_mem_region_with_cl(MemRegion mr, \
a61af66fc99e Initial load
duke
parents:
diff changeset
517 HeapWord* bottom, \
a61af66fc99e Initial load
duke
parents:
diff changeset
518 HeapWord* top, \
a61af66fc99e Initial load
duke
parents:
diff changeset
519 ClosureType* cl) { \
a61af66fc99e Initial load
duke
parents:
diff changeset
520 if (SharedHeap::heap()->n_par_threads() > 0) { \
a61af66fc99e Initial load
duke
parents:
diff changeset
521 walk_mem_region_with_cl_par(mr, bottom, top, cl); \
a61af66fc99e Initial load
duke
parents:
diff changeset
522 } else { \
a61af66fc99e Initial load
duke
parents:
diff changeset
523 walk_mem_region_with_cl_nopar(mr, bottom, top, cl); \
a61af66fc99e Initial load
duke
parents:
diff changeset
524 } \
a61af66fc99e Initial load
duke
parents:
diff changeset
525 } \
a61af66fc99e Initial load
duke
parents:
diff changeset
526 void FreeListSpace_DCTOC::walk_mem_region_with_cl_par(MemRegion mr, \
a61af66fc99e Initial load
duke
parents:
diff changeset
527 HeapWord* bottom, \
a61af66fc99e Initial load
duke
parents:
diff changeset
528 HeapWord* top, \
a61af66fc99e Initial load
duke
parents:
diff changeset
529 ClosureType* cl) { \
a61af66fc99e Initial load
duke
parents:
diff changeset
530 /* Skip parts that are before "mr", in case "block_start" sent us \
a61af66fc99e Initial load
duke
parents:
diff changeset
531 back too far. */ \
a61af66fc99e Initial load
duke
parents:
diff changeset
532 HeapWord* mr_start = mr.start(); \
a61af66fc99e Initial load
duke
parents:
diff changeset
533 size_t bot_size = _cfls->CompactibleFreeListSpace::block_size(bottom); \
a61af66fc99e Initial load
duke
parents:
diff changeset
534 HeapWord* next = bottom + bot_size; \
a61af66fc99e Initial load
duke
parents:
diff changeset
535 while (next < mr_start) { \
a61af66fc99e Initial load
duke
parents:
diff changeset
536 bottom = next; \
a61af66fc99e Initial load
duke
parents:
diff changeset
537 bot_size = _cfls->CompactibleFreeListSpace::block_size(bottom); \
a61af66fc99e Initial load
duke
parents:
diff changeset
538 next = bottom + bot_size; \
a61af66fc99e Initial load
duke
parents:
diff changeset
539 } \
a61af66fc99e Initial load
duke
parents:
diff changeset
540 \
a61af66fc99e Initial load
duke
parents:
diff changeset
541 while (bottom < top) { \
a61af66fc99e Initial load
duke
parents:
diff changeset
542 if (_cfls->CompactibleFreeListSpace::block_is_obj(bottom) && \
a61af66fc99e Initial load
duke
parents:
diff changeset
543 !_cfls->CompactibleFreeListSpace::obj_allocated_since_save_marks( \
a61af66fc99e Initial load
duke
parents:
diff changeset
544 oop(bottom)) && \
a61af66fc99e Initial load
duke
parents:
diff changeset
545 !_collector->CMSCollector::is_dead_obj(oop(bottom))) { \
a61af66fc99e Initial load
duke
parents:
diff changeset
546 size_t word_sz = oop(bottom)->oop_iterate(cl, mr); \
a61af66fc99e Initial load
duke
parents:
diff changeset
547 bottom += _cfls->adjustObjectSize(word_sz); \
a61af66fc99e Initial load
duke
parents:
diff changeset
548 } else { \
a61af66fc99e Initial load
duke
parents:
diff changeset
549 bottom += _cfls->CompactibleFreeListSpace::block_size(bottom); \
a61af66fc99e Initial load
duke
parents:
diff changeset
550 } \
a61af66fc99e Initial load
duke
parents:
diff changeset
551 } \
a61af66fc99e Initial load
duke
parents:
diff changeset
552 } \
a61af66fc99e Initial load
duke
parents:
diff changeset
553 void FreeListSpace_DCTOC::walk_mem_region_with_cl_nopar(MemRegion mr, \
a61af66fc99e Initial load
duke
parents:
diff changeset
554 HeapWord* bottom, \
a61af66fc99e Initial load
duke
parents:
diff changeset
555 HeapWord* top, \
a61af66fc99e Initial load
duke
parents:
diff changeset
556 ClosureType* cl) { \
a61af66fc99e Initial load
duke
parents:
diff changeset
557 /* Skip parts that are before "mr", in case "block_start" sent us \
a61af66fc99e Initial load
duke
parents:
diff changeset
558 back too far. */ \
a61af66fc99e Initial load
duke
parents:
diff changeset
559 HeapWord* mr_start = mr.start(); \
a61af66fc99e Initial load
duke
parents:
diff changeset
560 size_t bot_size = _cfls->CompactibleFreeListSpace::block_size_nopar(bottom); \
a61af66fc99e Initial load
duke
parents:
diff changeset
561 HeapWord* next = bottom + bot_size; \
a61af66fc99e Initial load
duke
parents:
diff changeset
562 while (next < mr_start) { \
a61af66fc99e Initial load
duke
parents:
diff changeset
563 bottom = next; \
a61af66fc99e Initial load
duke
parents:
diff changeset
564 bot_size = _cfls->CompactibleFreeListSpace::block_size_nopar(bottom); \
a61af66fc99e Initial load
duke
parents:
diff changeset
565 next = bottom + bot_size; \
a61af66fc99e Initial load
duke
parents:
diff changeset
566 } \
a61af66fc99e Initial load
duke
parents:
diff changeset
567 \
a61af66fc99e Initial load
duke
parents:
diff changeset
568 while (bottom < top) { \
a61af66fc99e Initial load
duke
parents:
diff changeset
569 if (_cfls->CompactibleFreeListSpace::block_is_obj_nopar(bottom) && \
a61af66fc99e Initial load
duke
parents:
diff changeset
570 !_cfls->CompactibleFreeListSpace::obj_allocated_since_save_marks( \
a61af66fc99e Initial load
duke
parents:
diff changeset
571 oop(bottom)) && \
a61af66fc99e Initial load
duke
parents:
diff changeset
572 !_collector->CMSCollector::is_dead_obj(oop(bottom))) { \
a61af66fc99e Initial load
duke
parents:
diff changeset
573 size_t word_sz = oop(bottom)->oop_iterate(cl, mr); \
a61af66fc99e Initial load
duke
parents:
diff changeset
574 bottom += _cfls->adjustObjectSize(word_sz); \
a61af66fc99e Initial load
duke
parents:
diff changeset
575 } else { \
a61af66fc99e Initial load
duke
parents:
diff changeset
576 bottom += _cfls->CompactibleFreeListSpace::block_size_nopar(bottom); \
a61af66fc99e Initial load
duke
parents:
diff changeset
577 } \
a61af66fc99e Initial load
duke
parents:
diff changeset
578 } \
a61af66fc99e Initial load
duke
parents:
diff changeset
579 }
a61af66fc99e Initial load
duke
parents:
diff changeset
580
a61af66fc99e Initial load
duke
parents:
diff changeset
581 // (There are only two of these, rather than N, because the split is due
a61af66fc99e Initial load
duke
parents:
diff changeset
582 // only to the introduction of the FilteringClosure, a local part of the
a61af66fc99e Initial load
duke
parents:
diff changeset
583 // impl of this abstraction.)
a61af66fc99e Initial load
duke
parents:
diff changeset
584 FreeListSpace_DCTOC__walk_mem_region_with_cl_DEFN(OopClosure)
a61af66fc99e Initial load
duke
parents:
diff changeset
585 FreeListSpace_DCTOC__walk_mem_region_with_cl_DEFN(FilteringClosure)
a61af66fc99e Initial load
duke
parents:
diff changeset
586
a61af66fc99e Initial load
duke
parents:
diff changeset
587 DirtyCardToOopClosure*
a61af66fc99e Initial load
duke
parents:
diff changeset
588 CompactibleFreeListSpace::new_dcto_cl(OopClosure* cl,
a61af66fc99e Initial load
duke
parents:
diff changeset
589 CardTableModRefBS::PrecisionStyle precision,
a61af66fc99e Initial load
duke
parents:
diff changeset
590 HeapWord* boundary) {
a61af66fc99e Initial load
duke
parents:
diff changeset
591 return new FreeListSpace_DCTOC(this, _collector, cl, precision, boundary);
a61af66fc99e Initial load
duke
parents:
diff changeset
592 }
a61af66fc99e Initial load
duke
parents:
diff changeset
593
a61af66fc99e Initial load
duke
parents:
diff changeset
594
a61af66fc99e Initial load
duke
parents:
diff changeset
595 // Note on locking for the space iteration functions:
a61af66fc99e Initial load
duke
parents:
diff changeset
596 // since the collector's iteration activities are concurrent with
a61af66fc99e Initial load
duke
parents:
diff changeset
597 // allocation activities by mutators, absent a suitable mutual exclusion
a61af66fc99e Initial load
duke
parents:
diff changeset
598 // mechanism the iterators may go awry. For instace a block being iterated
a61af66fc99e Initial load
duke
parents:
diff changeset
599 // may suddenly be allocated or divided up and part of it allocated and
a61af66fc99e Initial load
duke
parents:
diff changeset
600 // so on.
a61af66fc99e Initial load
duke
parents:
diff changeset
601
a61af66fc99e Initial load
duke
parents:
diff changeset
602 // Apply the given closure to each block in the space.
a61af66fc99e Initial load
duke
parents:
diff changeset
603 void CompactibleFreeListSpace::blk_iterate_careful(BlkClosureCareful* cl) {
a61af66fc99e Initial load
duke
parents:
diff changeset
604 assert_lock_strong(freelistLock());
a61af66fc99e Initial load
duke
parents:
diff changeset
605 HeapWord *cur, *limit;
a61af66fc99e Initial load
duke
parents:
diff changeset
606 for (cur = bottom(), limit = end(); cur < limit;
a61af66fc99e Initial load
duke
parents:
diff changeset
607 cur += cl->do_blk_careful(cur));
a61af66fc99e Initial load
duke
parents:
diff changeset
608 }
a61af66fc99e Initial load
duke
parents:
diff changeset
609
a61af66fc99e Initial load
duke
parents:
diff changeset
610 // Apply the given closure to each block in the space.
a61af66fc99e Initial load
duke
parents:
diff changeset
611 void CompactibleFreeListSpace::blk_iterate(BlkClosure* cl) {
a61af66fc99e Initial load
duke
parents:
diff changeset
612 assert_lock_strong(freelistLock());
a61af66fc99e Initial load
duke
parents:
diff changeset
613 HeapWord *cur, *limit;
a61af66fc99e Initial load
duke
parents:
diff changeset
614 for (cur = bottom(), limit = end(); cur < limit;
a61af66fc99e Initial load
duke
parents:
diff changeset
615 cur += cl->do_blk(cur));
a61af66fc99e Initial load
duke
parents:
diff changeset
616 }
a61af66fc99e Initial load
duke
parents:
diff changeset
617
a61af66fc99e Initial load
duke
parents:
diff changeset
618 // Apply the given closure to each oop in the space.
a61af66fc99e Initial load
duke
parents:
diff changeset
619 void CompactibleFreeListSpace::oop_iterate(OopClosure* cl) {
a61af66fc99e Initial load
duke
parents:
diff changeset
620 assert_lock_strong(freelistLock());
a61af66fc99e Initial load
duke
parents:
diff changeset
621 HeapWord *cur, *limit;
a61af66fc99e Initial load
duke
parents:
diff changeset
622 size_t curSize;
a61af66fc99e Initial load
duke
parents:
diff changeset
623 for (cur = bottom(), limit = end(); cur < limit;
a61af66fc99e Initial load
duke
parents:
diff changeset
624 cur += curSize) {
a61af66fc99e Initial load
duke
parents:
diff changeset
625 curSize = block_size(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
626 if (block_is_obj(cur)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
627 oop(cur)->oop_iterate(cl);
a61af66fc99e Initial load
duke
parents:
diff changeset
628 }
a61af66fc99e Initial load
duke
parents:
diff changeset
629 }
a61af66fc99e Initial load
duke
parents:
diff changeset
630 }
a61af66fc99e Initial load
duke
parents:
diff changeset
631
a61af66fc99e Initial load
duke
parents:
diff changeset
632 // Apply the given closure to each oop in the space \intersect memory region.
a61af66fc99e Initial load
duke
parents:
diff changeset
633 void CompactibleFreeListSpace::oop_iterate(MemRegion mr, OopClosure* cl) {
a61af66fc99e Initial load
duke
parents:
diff changeset
634 assert_lock_strong(freelistLock());
a61af66fc99e Initial load
duke
parents:
diff changeset
635 if (is_empty()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
636 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
637 }
a61af66fc99e Initial load
duke
parents:
diff changeset
638 MemRegion cur = MemRegion(bottom(), end());
a61af66fc99e Initial load
duke
parents:
diff changeset
639 mr = mr.intersection(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
640 if (mr.is_empty()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
641 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
642 }
a61af66fc99e Initial load
duke
parents:
diff changeset
643 if (mr.equals(cur)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
644 oop_iterate(cl);
a61af66fc99e Initial load
duke
parents:
diff changeset
645 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
646 }
a61af66fc99e Initial load
duke
parents:
diff changeset
647 assert(mr.end() <= end(), "just took an intersection above");
a61af66fc99e Initial load
duke
parents:
diff changeset
648 HeapWord* obj_addr = block_start(mr.start());
a61af66fc99e Initial load
duke
parents:
diff changeset
649 HeapWord* t = mr.end();
a61af66fc99e Initial load
duke
parents:
diff changeset
650
a61af66fc99e Initial load
duke
parents:
diff changeset
651 SpaceMemRegionOopsIterClosure smr_blk(cl, mr);
a61af66fc99e Initial load
duke
parents:
diff changeset
652 if (block_is_obj(obj_addr)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
653 // Handle first object specially.
a61af66fc99e Initial load
duke
parents:
diff changeset
654 oop obj = oop(obj_addr);
a61af66fc99e Initial load
duke
parents:
diff changeset
655 obj_addr += adjustObjectSize(obj->oop_iterate(&smr_blk));
a61af66fc99e Initial load
duke
parents:
diff changeset
656 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
657 FreeChunk* fc = (FreeChunk*)obj_addr;
a61af66fc99e Initial load
duke
parents:
diff changeset
658 obj_addr += fc->size();
a61af66fc99e Initial load
duke
parents:
diff changeset
659 }
a61af66fc99e Initial load
duke
parents:
diff changeset
660 while (obj_addr < t) {
a61af66fc99e Initial load
duke
parents:
diff changeset
661 HeapWord* obj = obj_addr;
a61af66fc99e Initial load
duke
parents:
diff changeset
662 obj_addr += block_size(obj_addr);
a61af66fc99e Initial load
duke
parents:
diff changeset
663 // If "obj_addr" is not greater than top, then the
a61af66fc99e Initial load
duke
parents:
diff changeset
664 // entire object "obj" is within the region.
a61af66fc99e Initial load
duke
parents:
diff changeset
665 if (obj_addr <= t) {
a61af66fc99e Initial load
duke
parents:
diff changeset
666 if (block_is_obj(obj)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
667 oop(obj)->oop_iterate(cl);
a61af66fc99e Initial load
duke
parents:
diff changeset
668 }
a61af66fc99e Initial load
duke
parents:
diff changeset
669 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
670 // "obj" extends beyond end of region
a61af66fc99e Initial load
duke
parents:
diff changeset
671 if (block_is_obj(obj)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
672 oop(obj)->oop_iterate(&smr_blk);
a61af66fc99e Initial load
duke
parents:
diff changeset
673 }
a61af66fc99e Initial load
duke
parents:
diff changeset
674 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
675 }
a61af66fc99e Initial load
duke
parents:
diff changeset
676 }
a61af66fc99e Initial load
duke
parents:
diff changeset
677 }
a61af66fc99e Initial load
duke
parents:
diff changeset
678
a61af66fc99e Initial load
duke
parents:
diff changeset
679 // NOTE: In the following methods, in order to safely be able to
a61af66fc99e Initial load
duke
parents:
diff changeset
680 // apply the closure to an object, we need to be sure that the
a61af66fc99e Initial load
duke
parents:
diff changeset
681 // object has been initialized. We are guaranteed that an object
a61af66fc99e Initial load
duke
parents:
diff changeset
682 // is initialized if we are holding the Heap_lock with the
a61af66fc99e Initial load
duke
parents:
diff changeset
683 // world stopped.
a61af66fc99e Initial load
duke
parents:
diff changeset
684 void CompactibleFreeListSpace::verify_objects_initialized() const {
a61af66fc99e Initial load
duke
parents:
diff changeset
685 if (is_init_completed()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
686 assert_locked_or_safepoint(Heap_lock);
a61af66fc99e Initial load
duke
parents:
diff changeset
687 if (Universe::is_fully_initialized()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
688 guarantee(SafepointSynchronize::is_at_safepoint(),
a61af66fc99e Initial load
duke
parents:
diff changeset
689 "Required for objects to be initialized");
a61af66fc99e Initial load
duke
parents:
diff changeset
690 }
a61af66fc99e Initial load
duke
parents:
diff changeset
691 } // else make a concession at vm start-up
a61af66fc99e Initial load
duke
parents:
diff changeset
692 }
a61af66fc99e Initial load
duke
parents:
diff changeset
693
a61af66fc99e Initial load
duke
parents:
diff changeset
694 // Apply the given closure to each object in the space
a61af66fc99e Initial load
duke
parents:
diff changeset
695 void CompactibleFreeListSpace::object_iterate(ObjectClosure* blk) {
a61af66fc99e Initial load
duke
parents:
diff changeset
696 assert_lock_strong(freelistLock());
a61af66fc99e Initial load
duke
parents:
diff changeset
697 NOT_PRODUCT(verify_objects_initialized());
a61af66fc99e Initial load
duke
parents:
diff changeset
698 HeapWord *cur, *limit;
a61af66fc99e Initial load
duke
parents:
diff changeset
699 size_t curSize;
a61af66fc99e Initial load
duke
parents:
diff changeset
700 for (cur = bottom(), limit = end(); cur < limit;
a61af66fc99e Initial load
duke
parents:
diff changeset
701 cur += curSize) {
a61af66fc99e Initial load
duke
parents:
diff changeset
702 curSize = block_size(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
703 if (block_is_obj(cur)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
704 blk->do_object(oop(cur));
a61af66fc99e Initial load
duke
parents:
diff changeset
705 }
a61af66fc99e Initial load
duke
parents:
diff changeset
706 }
a61af66fc99e Initial load
duke
parents:
diff changeset
707 }
a61af66fc99e Initial load
duke
parents:
diff changeset
708
a61af66fc99e Initial load
duke
parents:
diff changeset
709 void CompactibleFreeListSpace::object_iterate_mem(MemRegion mr,
a61af66fc99e Initial load
duke
parents:
diff changeset
710 UpwardsObjectClosure* cl) {
a61af66fc99e Initial load
duke
parents:
diff changeset
711 assert_locked();
a61af66fc99e Initial load
duke
parents:
diff changeset
712 NOT_PRODUCT(verify_objects_initialized());
a61af66fc99e Initial load
duke
parents:
diff changeset
713 Space::object_iterate_mem(mr, cl);
a61af66fc99e Initial load
duke
parents:
diff changeset
714 }
a61af66fc99e Initial load
duke
parents:
diff changeset
715
a61af66fc99e Initial load
duke
parents:
diff changeset
716 // Callers of this iterator beware: The closure application should
a61af66fc99e Initial load
duke
parents:
diff changeset
717 // be robust in the face of uninitialized objects and should (always)
a61af66fc99e Initial load
duke
parents:
diff changeset
718 // return a correct size so that the next addr + size below gives us a
a61af66fc99e Initial load
duke
parents:
diff changeset
719 // valid block boundary. [See for instance,
a61af66fc99e Initial load
duke
parents:
diff changeset
720 // ScanMarkedObjectsAgainCarefullyClosure::do_object_careful()
a61af66fc99e Initial load
duke
parents:
diff changeset
721 // in ConcurrentMarkSweepGeneration.cpp.]
a61af66fc99e Initial load
duke
parents:
diff changeset
722 HeapWord*
a61af66fc99e Initial load
duke
parents:
diff changeset
723 CompactibleFreeListSpace::object_iterate_careful(ObjectClosureCareful* cl) {
a61af66fc99e Initial load
duke
parents:
diff changeset
724 assert_lock_strong(freelistLock());
a61af66fc99e Initial load
duke
parents:
diff changeset
725 HeapWord *addr, *last;
a61af66fc99e Initial load
duke
parents:
diff changeset
726 size_t size;
a61af66fc99e Initial load
duke
parents:
diff changeset
727 for (addr = bottom(), last = end();
a61af66fc99e Initial load
duke
parents:
diff changeset
728 addr < last; addr += size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
729 FreeChunk* fc = (FreeChunk*)addr;
a61af66fc99e Initial load
duke
parents:
diff changeset
730 if (fc->isFree()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
731 // Since we hold the free list lock, which protects direct
a61af66fc99e Initial load
duke
parents:
diff changeset
732 // allocation in this generation by mutators, a free object
a61af66fc99e Initial load
duke
parents:
diff changeset
733 // will remain free throughout this iteration code.
a61af66fc99e Initial load
duke
parents:
diff changeset
734 size = fc->size();
a61af66fc99e Initial load
duke
parents:
diff changeset
735 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
736 // Note that the object need not necessarily be initialized,
a61af66fc99e Initial load
duke
parents:
diff changeset
737 // because (for instance) the free list lock does NOT protect
a61af66fc99e Initial load
duke
parents:
diff changeset
738 // object initialization. The closure application below must
a61af66fc99e Initial load
duke
parents:
diff changeset
739 // therefore be correct in the face of uninitialized objects.
a61af66fc99e Initial load
duke
parents:
diff changeset
740 size = cl->do_object_careful(oop(addr));
a61af66fc99e Initial load
duke
parents:
diff changeset
741 if (size == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
742 // An unparsable object found. Signal early termination.
a61af66fc99e Initial load
duke
parents:
diff changeset
743 return addr;
a61af66fc99e Initial load
duke
parents:
diff changeset
744 }
a61af66fc99e Initial load
duke
parents:
diff changeset
745 }
a61af66fc99e Initial load
duke
parents:
diff changeset
746 }
a61af66fc99e Initial load
duke
parents:
diff changeset
747 return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
748 }
a61af66fc99e Initial load
duke
parents:
diff changeset
749
a61af66fc99e Initial load
duke
parents:
diff changeset
750 // Callers of this iterator beware: The closure application should
a61af66fc99e Initial load
duke
parents:
diff changeset
751 // be robust in the face of uninitialized objects and should (always)
a61af66fc99e Initial load
duke
parents:
diff changeset
752 // return a correct size so that the next addr + size below gives us a
a61af66fc99e Initial load
duke
parents:
diff changeset
753 // valid block boundary. [See for instance,
a61af66fc99e Initial load
duke
parents:
diff changeset
754 // ScanMarkedObjectsAgainCarefullyClosure::do_object_careful()
a61af66fc99e Initial load
duke
parents:
diff changeset
755 // in ConcurrentMarkSweepGeneration.cpp.]
a61af66fc99e Initial load
duke
parents:
diff changeset
756 HeapWord*
a61af66fc99e Initial load
duke
parents:
diff changeset
757 CompactibleFreeListSpace::object_iterate_careful_m(MemRegion mr,
a61af66fc99e Initial load
duke
parents:
diff changeset
758 ObjectClosureCareful* cl) {
a61af66fc99e Initial load
duke
parents:
diff changeset
759 assert_lock_strong(freelistLock());
a61af66fc99e Initial load
duke
parents:
diff changeset
760 // Can't use used_region() below because it may not necessarily
a61af66fc99e Initial load
duke
parents:
diff changeset
761 // be the same as [bottom(),end()); although we could
a61af66fc99e Initial load
duke
parents:
diff changeset
762 // use [used_region().start(),round_to(used_region().end(),CardSize)),
a61af66fc99e Initial load
duke
parents:
diff changeset
763 // that appears too cumbersome, so we just do the simpler check
a61af66fc99e Initial load
duke
parents:
diff changeset
764 // in the assertion below.
a61af66fc99e Initial load
duke
parents:
diff changeset
765 assert(!mr.is_empty() && MemRegion(bottom(),end()).contains(mr),
a61af66fc99e Initial load
duke
parents:
diff changeset
766 "mr should be non-empty and within used space");
a61af66fc99e Initial load
duke
parents:
diff changeset
767 HeapWord *addr, *end;
a61af66fc99e Initial load
duke
parents:
diff changeset
768 size_t size;
a61af66fc99e Initial load
duke
parents:
diff changeset
769 for (addr = block_start_careful(mr.start()), end = mr.end();
a61af66fc99e Initial load
duke
parents:
diff changeset
770 addr < end; addr += size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
771 FreeChunk* fc = (FreeChunk*)addr;
a61af66fc99e Initial load
duke
parents:
diff changeset
772 if (fc->isFree()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
773 // Since we hold the free list lock, which protects direct
a61af66fc99e Initial load
duke
parents:
diff changeset
774 // allocation in this generation by mutators, a free object
a61af66fc99e Initial load
duke
parents:
diff changeset
775 // will remain free throughout this iteration code.
a61af66fc99e Initial load
duke
parents:
diff changeset
776 size = fc->size();
a61af66fc99e Initial load
duke
parents:
diff changeset
777 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
778 // Note that the object need not necessarily be initialized,
a61af66fc99e Initial load
duke
parents:
diff changeset
779 // because (for instance) the free list lock does NOT protect
a61af66fc99e Initial load
duke
parents:
diff changeset
780 // object initialization. The closure application below must
a61af66fc99e Initial load
duke
parents:
diff changeset
781 // therefore be correct in the face of uninitialized objects.
a61af66fc99e Initial load
duke
parents:
diff changeset
782 size = cl->do_object_careful_m(oop(addr), mr);
a61af66fc99e Initial load
duke
parents:
diff changeset
783 if (size == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
784 // An unparsable object found. Signal early termination.
a61af66fc99e Initial load
duke
parents:
diff changeset
785 return addr;
a61af66fc99e Initial load
duke
parents:
diff changeset
786 }
a61af66fc99e Initial load
duke
parents:
diff changeset
787 }
a61af66fc99e Initial load
duke
parents:
diff changeset
788 }
a61af66fc99e Initial load
duke
parents:
diff changeset
789 return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
790 }
a61af66fc99e Initial load
duke
parents:
diff changeset
791
a61af66fc99e Initial load
duke
parents:
diff changeset
792
342
37f87013dfd8 6711316: Open source the Garbage-First garbage collector
ysr
parents: 113
diff changeset
793 HeapWord* CompactibleFreeListSpace::block_start_const(const void* p) const {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
794 NOT_PRODUCT(verify_objects_initialized());
a61af66fc99e Initial load
duke
parents:
diff changeset
795 return _bt.block_start(p);
a61af66fc99e Initial load
duke
parents:
diff changeset
796 }
a61af66fc99e Initial load
duke
parents:
diff changeset
797
a61af66fc99e Initial load
duke
parents:
diff changeset
798 HeapWord* CompactibleFreeListSpace::block_start_careful(const void* p) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
799 return _bt.block_start_careful(p);
a61af66fc99e Initial load
duke
parents:
diff changeset
800 }
a61af66fc99e Initial load
duke
parents:
diff changeset
801
a61af66fc99e Initial load
duke
parents:
diff changeset
802 size_t CompactibleFreeListSpace::block_size(const HeapWord* p) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
803 NOT_PRODUCT(verify_objects_initialized());
a61af66fc99e Initial load
duke
parents:
diff changeset
804 assert(MemRegion(bottom(), end()).contains(p), "p not in space");
a61af66fc99e Initial load
duke
parents:
diff changeset
805 // This must be volatile, or else there is a danger that the compiler
a61af66fc99e Initial load
duke
parents:
diff changeset
806 // will compile the code below into a sometimes-infinite loop, by keeping
a61af66fc99e Initial load
duke
parents:
diff changeset
807 // the value read the first time in a register.
a61af66fc99e Initial load
duke
parents:
diff changeset
808 while (true) {
a61af66fc99e Initial load
duke
parents:
diff changeset
809 // We must do this until we get a consistent view of the object.
187
790e66e5fbac 6687581: Make CMS work with compressed oops
coleenp
parents: 113
diff changeset
810 if (FreeChunk::indicatesFreeChunk(p)) {
790e66e5fbac 6687581: Make CMS work with compressed oops
coleenp
parents: 113
diff changeset
811 volatile FreeChunk* fc = (volatile FreeChunk*)p;
790e66e5fbac 6687581: Make CMS work with compressed oops
coleenp
parents: 113
diff changeset
812 size_t res = fc->size();
790e66e5fbac 6687581: Make CMS work with compressed oops
coleenp
parents: 113
diff changeset
813 // If the object is still a free chunk, return the size, else it
790e66e5fbac 6687581: Make CMS work with compressed oops
coleenp
parents: 113
diff changeset
814 // has been allocated so try again.
790e66e5fbac 6687581: Make CMS work with compressed oops
coleenp
parents: 113
diff changeset
815 if (FreeChunk::indicatesFreeChunk(p)) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
816 assert(res != 0, "Block size should not be 0");
a61af66fc99e Initial load
duke
parents:
diff changeset
817 return res;
a61af66fc99e Initial load
duke
parents:
diff changeset
818 }
187
790e66e5fbac 6687581: Make CMS work with compressed oops
coleenp
parents: 113
diff changeset
819 } else {
790e66e5fbac 6687581: Make CMS work with compressed oops
coleenp
parents: 113
diff changeset
820 // must read from what 'p' points to in each loop.
790e66e5fbac 6687581: Make CMS work with compressed oops
coleenp
parents: 113
diff changeset
821 klassOop k = ((volatile oopDesc*)p)->klass_or_null();
790e66e5fbac 6687581: Make CMS work with compressed oops
coleenp
parents: 113
diff changeset
822 if (k != NULL) {
790e66e5fbac 6687581: Make CMS work with compressed oops
coleenp
parents: 113
diff changeset
823 assert(k->is_oop(true /* ignore mark word */), "Should really be klass oop.");
790e66e5fbac 6687581: Make CMS work with compressed oops
coleenp
parents: 113
diff changeset
824 oop o = (oop)p;
790e66e5fbac 6687581: Make CMS work with compressed oops
coleenp
parents: 113
diff changeset
825 assert(o->is_parsable(), "Should be parsable");
790e66e5fbac 6687581: Make CMS work with compressed oops
coleenp
parents: 113
diff changeset
826 assert(o->is_oop(true /* ignore mark word */), "Should be an oop.");
790e66e5fbac 6687581: Make CMS work with compressed oops
coleenp
parents: 113
diff changeset
827 size_t res = o->size_given_klass(k->klass_part());
790e66e5fbac 6687581: Make CMS work with compressed oops
coleenp
parents: 113
diff changeset
828 res = adjustObjectSize(res);
790e66e5fbac 6687581: Make CMS work with compressed oops
coleenp
parents: 113
diff changeset
829 assert(res != 0, "Block size should not be 0");
790e66e5fbac 6687581: Make CMS work with compressed oops
coleenp
parents: 113
diff changeset
830 return res;
790e66e5fbac 6687581: Make CMS work with compressed oops
coleenp
parents: 113
diff changeset
831 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
832 }
a61af66fc99e Initial load
duke
parents:
diff changeset
833 }
a61af66fc99e Initial load
duke
parents:
diff changeset
834 }
a61af66fc99e Initial load
duke
parents:
diff changeset
835
a61af66fc99e Initial load
duke
parents:
diff changeset
836 // A variant of the above that uses the Printezis bits for
a61af66fc99e Initial load
duke
parents:
diff changeset
837 // unparsable but allocated objects. This avoids any possible
a61af66fc99e Initial load
duke
parents:
diff changeset
838 // stalls waiting for mutators to initialize objects, and is
a61af66fc99e Initial load
duke
parents:
diff changeset
839 // thus potentially faster than the variant above. However,
a61af66fc99e Initial load
duke
parents:
diff changeset
840 // this variant may return a zero size for a block that is
a61af66fc99e Initial load
duke
parents:
diff changeset
841 // under mutation and for which a consistent size cannot be
a61af66fc99e Initial load
duke
parents:
diff changeset
842 // inferred without stalling; see CMSCollector::block_size_if_printezis_bits().
a61af66fc99e Initial load
duke
parents:
diff changeset
843 size_t CompactibleFreeListSpace::block_size_no_stall(HeapWord* p,
a61af66fc99e Initial load
duke
parents:
diff changeset
844 const CMSCollector* c)
a61af66fc99e Initial load
duke
parents:
diff changeset
845 const {
a61af66fc99e Initial load
duke
parents:
diff changeset
846 assert(MemRegion(bottom(), end()).contains(p), "p not in space");
a61af66fc99e Initial load
duke
parents:
diff changeset
847 // This must be volatile, or else there is a danger that the compiler
a61af66fc99e Initial load
duke
parents:
diff changeset
848 // will compile the code below into a sometimes-infinite loop, by keeping
a61af66fc99e Initial load
duke
parents:
diff changeset
849 // the value read the first time in a register.
a61af66fc99e Initial load
duke
parents:
diff changeset
850 DEBUG_ONLY(uint loops = 0;)
a61af66fc99e Initial load
duke
parents:
diff changeset
851 while (true) {
a61af66fc99e Initial load
duke
parents:
diff changeset
852 // We must do this until we get a consistent view of the object.
187
790e66e5fbac 6687581: Make CMS work with compressed oops
coleenp
parents: 113
diff changeset
853 if (FreeChunk::indicatesFreeChunk(p)) {
790e66e5fbac 6687581: Make CMS work with compressed oops
coleenp
parents: 113
diff changeset
854 volatile FreeChunk* fc = (volatile FreeChunk*)p;
790e66e5fbac 6687581: Make CMS work with compressed oops
coleenp
parents: 113
diff changeset
855 size_t res = fc->size();
790e66e5fbac 6687581: Make CMS work with compressed oops
coleenp
parents: 113
diff changeset
856 if (FreeChunk::indicatesFreeChunk(p)) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
857 assert(res != 0, "Block size should not be 0");
a61af66fc99e Initial load
duke
parents:
diff changeset
858 assert(loops == 0, "Should be 0");
a61af66fc99e Initial load
duke
parents:
diff changeset
859 return res;
a61af66fc99e Initial load
duke
parents:
diff changeset
860 }
a61af66fc99e Initial load
duke
parents:
diff changeset
861 } else {
187
790e66e5fbac 6687581: Make CMS work with compressed oops
coleenp
parents: 113
diff changeset
862 // must read from what 'p' points to in each loop.
790e66e5fbac 6687581: Make CMS work with compressed oops
coleenp
parents: 113
diff changeset
863 klassOop k = ((volatile oopDesc*)p)->klass_or_null();
790e66e5fbac 6687581: Make CMS work with compressed oops
coleenp
parents: 113
diff changeset
864 if (k != NULL && ((oopDesc*)p)->is_parsable()) {
790e66e5fbac 6687581: Make CMS work with compressed oops
coleenp
parents: 113
diff changeset
865 assert(k->is_oop(), "Should really be klass oop.");
790e66e5fbac 6687581: Make CMS work with compressed oops
coleenp
parents: 113
diff changeset
866 oop o = (oop)p;
790e66e5fbac 6687581: Make CMS work with compressed oops
coleenp
parents: 113
diff changeset
867 assert(o->is_oop(), "Should be an oop");
790e66e5fbac 6687581: Make CMS work with compressed oops
coleenp
parents: 113
diff changeset
868 size_t res = o->size_given_klass(k->klass_part());
790e66e5fbac 6687581: Make CMS work with compressed oops
coleenp
parents: 113
diff changeset
869 res = adjustObjectSize(res);
790e66e5fbac 6687581: Make CMS work with compressed oops
coleenp
parents: 113
diff changeset
870 assert(res != 0, "Block size should not be 0");
790e66e5fbac 6687581: Make CMS work with compressed oops
coleenp
parents: 113
diff changeset
871 return res;
790e66e5fbac 6687581: Make CMS work with compressed oops
coleenp
parents: 113
diff changeset
872 } else {
790e66e5fbac 6687581: Make CMS work with compressed oops
coleenp
parents: 113
diff changeset
873 return c->block_size_if_printezis_bits(p);
790e66e5fbac 6687581: Make CMS work with compressed oops
coleenp
parents: 113
diff changeset
874 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
875 }
a61af66fc99e Initial load
duke
parents:
diff changeset
876 assert(loops == 0, "Can loop at most once");
a61af66fc99e Initial load
duke
parents:
diff changeset
877 DEBUG_ONLY(loops++;)
a61af66fc99e Initial load
duke
parents:
diff changeset
878 }
a61af66fc99e Initial load
duke
parents:
diff changeset
879 }
a61af66fc99e Initial load
duke
parents:
diff changeset
880
a61af66fc99e Initial load
duke
parents:
diff changeset
881 size_t CompactibleFreeListSpace::block_size_nopar(const HeapWord* p) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
882 NOT_PRODUCT(verify_objects_initialized());
a61af66fc99e Initial load
duke
parents:
diff changeset
883 assert(MemRegion(bottom(), end()).contains(p), "p not in space");
a61af66fc99e Initial load
duke
parents:
diff changeset
884 FreeChunk* fc = (FreeChunk*)p;
a61af66fc99e Initial load
duke
parents:
diff changeset
885 if (fc->isFree()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
886 return fc->size();
a61af66fc99e Initial load
duke
parents:
diff changeset
887 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
888 // Ignore mark word because this may be a recently promoted
a61af66fc99e Initial load
duke
parents:
diff changeset
889 // object whose mark word is used to chain together grey
a61af66fc99e Initial load
duke
parents:
diff changeset
890 // objects (the last one would have a null value).
a61af66fc99e Initial load
duke
parents:
diff changeset
891 assert(oop(p)->is_oop(true), "Should be an oop");
a61af66fc99e Initial load
duke
parents:
diff changeset
892 return adjustObjectSize(oop(p)->size());
a61af66fc99e Initial load
duke
parents:
diff changeset
893 }
a61af66fc99e Initial load
duke
parents:
diff changeset
894 }
a61af66fc99e Initial load
duke
parents:
diff changeset
895
a61af66fc99e Initial load
duke
parents:
diff changeset
896 // This implementation assumes that the property of "being an object" is
a61af66fc99e Initial load
duke
parents:
diff changeset
897 // stable. But being a free chunk may not be (because of parallel
a61af66fc99e Initial load
duke
parents:
diff changeset
898 // promotion.)
a61af66fc99e Initial load
duke
parents:
diff changeset
899 bool CompactibleFreeListSpace::block_is_obj(const HeapWord* p) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
900 FreeChunk* fc = (FreeChunk*)p;
a61af66fc99e Initial load
duke
parents:
diff changeset
901 assert(is_in_reserved(p), "Should be in space");
a61af66fc99e Initial load
duke
parents:
diff changeset
902 // When doing a mark-sweep-compact of the CMS generation, this
a61af66fc99e Initial load
duke
parents:
diff changeset
903 // assertion may fail because prepare_for_compaction() uses
a61af66fc99e Initial load
duke
parents:
diff changeset
904 // space that is garbage to maintain information on ranges of
a61af66fc99e Initial load
duke
parents:
diff changeset
905 // live objects so that these live ranges can be moved as a whole.
a61af66fc99e Initial load
duke
parents:
diff changeset
906 // Comment out this assertion until that problem can be solved
a61af66fc99e Initial load
duke
parents:
diff changeset
907 // (i.e., that the block start calculation may look at objects
a61af66fc99e Initial load
duke
parents:
diff changeset
908 // at address below "p" in finding the object that contains "p"
a61af66fc99e Initial load
duke
parents:
diff changeset
909 // and those objects (if garbage) may have been modified to hold
a61af66fc99e Initial load
duke
parents:
diff changeset
910 // live range information.
a61af66fc99e Initial load
duke
parents:
diff changeset
911 // assert(ParallelGCThreads > 0 || _bt.block_start(p) == p, "Should be a block boundary");
187
790e66e5fbac 6687581: Make CMS work with compressed oops
coleenp
parents: 113
diff changeset
912 if (FreeChunk::indicatesFreeChunk(p)) return false;
790e66e5fbac 6687581: Make CMS work with compressed oops
coleenp
parents: 113
diff changeset
913 klassOop k = oop(p)->klass_or_null();
0
a61af66fc99e Initial load
duke
parents:
diff changeset
914 if (k != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
915 // Ignore mark word because it may have been used to
a61af66fc99e Initial load
duke
parents:
diff changeset
916 // chain together promoted objects (the last one
a61af66fc99e Initial load
duke
parents:
diff changeset
917 // would have a null value).
a61af66fc99e Initial load
duke
parents:
diff changeset
918 assert(oop(p)->is_oop(true), "Should be an oop");
a61af66fc99e Initial load
duke
parents:
diff changeset
919 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
920 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
921 return false; // Was not an object at the start of collection.
a61af66fc99e Initial load
duke
parents:
diff changeset
922 }
a61af66fc99e Initial load
duke
parents:
diff changeset
923 }
a61af66fc99e Initial load
duke
parents:
diff changeset
924
a61af66fc99e Initial load
duke
parents:
diff changeset
925 // Check if the object is alive. This fact is checked either by consulting
a61af66fc99e Initial load
duke
parents:
diff changeset
926 // the main marking bitmap in the sweeping phase or, if it's a permanent
a61af66fc99e Initial load
duke
parents:
diff changeset
927 // generation and we're not in the sweeping phase, by checking the
a61af66fc99e Initial load
duke
parents:
diff changeset
928 // perm_gen_verify_bit_map where we store the "deadness" information if
a61af66fc99e Initial load
duke
parents:
diff changeset
929 // we did not sweep the perm gen in the most recent previous GC cycle.
a61af66fc99e Initial load
duke
parents:
diff changeset
930 bool CompactibleFreeListSpace::obj_is_alive(const HeapWord* p) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
931 assert (block_is_obj(p), "The address should point to an object");
a61af66fc99e Initial load
duke
parents:
diff changeset
932
a61af66fc99e Initial load
duke
parents:
diff changeset
933 // If we're sweeping, we use object liveness information from the main bit map
a61af66fc99e Initial load
duke
parents:
diff changeset
934 // for both perm gen and old gen.
a61af66fc99e Initial load
duke
parents:
diff changeset
935 // We don't need to lock the bitmap (live_map or dead_map below), because
a61af66fc99e Initial load
duke
parents:
diff changeset
936 // EITHER we are in the middle of the sweeping phase, and the
a61af66fc99e Initial load
duke
parents:
diff changeset
937 // main marking bit map (live_map below) is locked,
a61af66fc99e Initial load
duke
parents:
diff changeset
938 // OR we're in other phases and perm_gen_verify_bit_map (dead_map below)
a61af66fc99e Initial load
duke
parents:
diff changeset
939 // is stable, because it's mutated only in the sweeping phase.
a61af66fc99e Initial load
duke
parents:
diff changeset
940 if (_collector->abstract_state() == CMSCollector::Sweeping) {
a61af66fc99e Initial load
duke
parents:
diff changeset
941 CMSBitMap* live_map = _collector->markBitMap();
a61af66fc99e Initial load
duke
parents:
diff changeset
942 return live_map->isMarked((HeapWord*) p);
a61af66fc99e Initial load
duke
parents:
diff changeset
943 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
944 // If we're not currently sweeping and we haven't swept the perm gen in
a61af66fc99e Initial load
duke
parents:
diff changeset
945 // the previous concurrent cycle then we may have dead but unswept objects
a61af66fc99e Initial load
duke
parents:
diff changeset
946 // in the perm gen. In this case, we use the "deadness" information
a61af66fc99e Initial load
duke
parents:
diff changeset
947 // that we had saved in perm_gen_verify_bit_map at the last sweep.
a61af66fc99e Initial load
duke
parents:
diff changeset
948 if (!CMSClassUnloadingEnabled && _collector->_permGen->reserved().contains(p)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
949 if (_collector->verifying()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
950 CMSBitMap* dead_map = _collector->perm_gen_verify_bit_map();
a61af66fc99e Initial load
duke
parents:
diff changeset
951 // Object is marked in the dead_map bitmap at the previous sweep
a61af66fc99e Initial load
duke
parents:
diff changeset
952 // when we know that it's dead; if the bitmap is not allocated then
a61af66fc99e Initial load
duke
parents:
diff changeset
953 // the object is alive.
a61af66fc99e Initial load
duke
parents:
diff changeset
954 return (dead_map->sizeInBits() == 0) // bit_map has been allocated
a61af66fc99e Initial load
duke
parents:
diff changeset
955 || !dead_map->par_isMarked((HeapWord*) p);
a61af66fc99e Initial load
duke
parents:
diff changeset
956 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
957 return false; // We can't say for sure if it's live, so we say that it's dead.
a61af66fc99e Initial load
duke
parents:
diff changeset
958 }
a61af66fc99e Initial load
duke
parents:
diff changeset
959 }
a61af66fc99e Initial load
duke
parents:
diff changeset
960 }
a61af66fc99e Initial load
duke
parents:
diff changeset
961 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
962 }
a61af66fc99e Initial load
duke
parents:
diff changeset
963
a61af66fc99e Initial load
duke
parents:
diff changeset
964 bool CompactibleFreeListSpace::block_is_obj_nopar(const HeapWord* p) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
965 FreeChunk* fc = (FreeChunk*)p;
a61af66fc99e Initial load
duke
parents:
diff changeset
966 assert(is_in_reserved(p), "Should be in space");
a61af66fc99e Initial load
duke
parents:
diff changeset
967 assert(_bt.block_start(p) == p, "Should be a block boundary");
a61af66fc99e Initial load
duke
parents:
diff changeset
968 if (!fc->isFree()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
969 // Ignore mark word because it may have been used to
a61af66fc99e Initial load
duke
parents:
diff changeset
970 // chain together promoted objects (the last one
a61af66fc99e Initial load
duke
parents:
diff changeset
971 // would have a null value).
a61af66fc99e Initial load
duke
parents:
diff changeset
972 assert(oop(p)->is_oop(true), "Should be an oop");
a61af66fc99e Initial load
duke
parents:
diff changeset
973 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
974 }
a61af66fc99e Initial load
duke
parents:
diff changeset
975 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
976 }
a61af66fc99e Initial load
duke
parents:
diff changeset
977
a61af66fc99e Initial load
duke
parents:
diff changeset
978 // "MT-safe but not guaranteed MT-precise" (TM); you may get an
a61af66fc99e Initial load
duke
parents:
diff changeset
979 // approximate answer if you don't hold the freelistlock when you call this.
a61af66fc99e Initial load
duke
parents:
diff changeset
980 size_t CompactibleFreeListSpace::totalSizeInIndexedFreeLists() const {
a61af66fc99e Initial load
duke
parents:
diff changeset
981 size_t size = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
982 for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
a61af66fc99e Initial load
duke
parents:
diff changeset
983 debug_only(
a61af66fc99e Initial load
duke
parents:
diff changeset
984 // We may be calling here without the lock in which case we
a61af66fc99e Initial load
duke
parents:
diff changeset
985 // won't do this modest sanity check.
a61af66fc99e Initial load
duke
parents:
diff changeset
986 if (freelistLock()->owned_by_self()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
987 size_t total_list_size = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
988 for (FreeChunk* fc = _indexedFreeList[i].head(); fc != NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
989 fc = fc->next()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
990 total_list_size += i;
a61af66fc99e Initial load
duke
parents:
diff changeset
991 }
a61af66fc99e Initial load
duke
parents:
diff changeset
992 assert(total_list_size == i * _indexedFreeList[i].count(),
a61af66fc99e Initial load
duke
parents:
diff changeset
993 "Count in list is incorrect");
a61af66fc99e Initial load
duke
parents:
diff changeset
994 }
a61af66fc99e Initial load
duke
parents:
diff changeset
995 )
a61af66fc99e Initial load
duke
parents:
diff changeset
996 size += i * _indexedFreeList[i].count();
a61af66fc99e Initial load
duke
parents:
diff changeset
997 }
a61af66fc99e Initial load
duke
parents:
diff changeset
998 return size;
a61af66fc99e Initial load
duke
parents:
diff changeset
999 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1000
a61af66fc99e Initial load
duke
parents:
diff changeset
1001 HeapWord* CompactibleFreeListSpace::par_allocate(size_t size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1002 MutexLockerEx x(freelistLock(), Mutex::_no_safepoint_check_flag);
a61af66fc99e Initial load
duke
parents:
diff changeset
1003 return allocate(size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1004 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1005
a61af66fc99e Initial load
duke
parents:
diff changeset
1006 HeapWord*
a61af66fc99e Initial load
duke
parents:
diff changeset
1007 CompactibleFreeListSpace::getChunkFromSmallLinearAllocBlockRemainder(size_t size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1008 return getChunkFromLinearAllocBlockRemainder(&_smallLinearAllocBlock, size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1009 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1010
a61af66fc99e Initial load
duke
parents:
diff changeset
1011 HeapWord* CompactibleFreeListSpace::allocate(size_t size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1012 assert_lock_strong(freelistLock());
a61af66fc99e Initial load
duke
parents:
diff changeset
1013 HeapWord* res = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
1014 assert(size == adjustObjectSize(size),
a61af66fc99e Initial load
duke
parents:
diff changeset
1015 "use adjustObjectSize() before calling into allocate()");
a61af66fc99e Initial load
duke
parents:
diff changeset
1016
a61af66fc99e Initial load
duke
parents:
diff changeset
1017 if (_adaptive_freelists) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1018 res = allocate_adaptive_freelists(size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1019 } else { // non-adaptive free lists
a61af66fc99e Initial load
duke
parents:
diff changeset
1020 res = allocate_non_adaptive_freelists(size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1021 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1022
a61af66fc99e Initial load
duke
parents:
diff changeset
1023 if (res != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1024 // check that res does lie in this space!
a61af66fc99e Initial load
duke
parents:
diff changeset
1025 assert(is_in_reserved(res), "Not in this space!");
a61af66fc99e Initial load
duke
parents:
diff changeset
1026 assert(is_aligned((void*)res), "alignment check");
a61af66fc99e Initial load
duke
parents:
diff changeset
1027
a61af66fc99e Initial load
duke
parents:
diff changeset
1028 FreeChunk* fc = (FreeChunk*)res;
a61af66fc99e Initial load
duke
parents:
diff changeset
1029 fc->markNotFree();
a61af66fc99e Initial load
duke
parents:
diff changeset
1030 assert(!fc->isFree(), "shouldn't be marked free");
187
790e66e5fbac 6687581: Make CMS work with compressed oops
coleenp
parents: 113
diff changeset
1031 assert(oop(fc)->klass_or_null() == NULL, "should look uninitialized");
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1032 // Verify that the block offset table shows this to
a61af66fc99e Initial load
duke
parents:
diff changeset
1033 // be a single block, but not one which is unallocated.
a61af66fc99e Initial load
duke
parents:
diff changeset
1034 _bt.verify_single_block(res, size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1035 _bt.verify_not_unallocated(res, size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1036 // mangle a just allocated object with a distinct pattern.
a61af66fc99e Initial load
duke
parents:
diff changeset
1037 debug_only(fc->mangleAllocated(size));
a61af66fc99e Initial load
duke
parents:
diff changeset
1038 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1039
a61af66fc99e Initial load
duke
parents:
diff changeset
1040 return res;
a61af66fc99e Initial load
duke
parents:
diff changeset
1041 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1042
a61af66fc99e Initial load
duke
parents:
diff changeset
1043 HeapWord* CompactibleFreeListSpace::allocate_non_adaptive_freelists(size_t size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1044 HeapWord* res = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
1045 // try and use linear allocation for smaller blocks
a61af66fc99e Initial load
duke
parents:
diff changeset
1046 if (size < _smallLinearAllocBlock._allocation_size_limit) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1047 // if successful, the following also adjusts block offset table
a61af66fc99e Initial load
duke
parents:
diff changeset
1048 res = getChunkFromSmallLinearAllocBlock(size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1049 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1050 // Else triage to indexed lists for smaller sizes
a61af66fc99e Initial load
duke
parents:
diff changeset
1051 if (res == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1052 if (size < SmallForDictionary) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1053 res = (HeapWord*) getChunkFromIndexedFreeList(size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1054 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1055 // else get it from the big dictionary; if even this doesn't
a61af66fc99e Initial load
duke
parents:
diff changeset
1056 // work we are out of luck.
a61af66fc99e Initial load
duke
parents:
diff changeset
1057 res = (HeapWord*)getChunkFromDictionaryExact(size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1058 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1059 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1060
a61af66fc99e Initial load
duke
parents:
diff changeset
1061 return res;
a61af66fc99e Initial load
duke
parents:
diff changeset
1062 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1063
a61af66fc99e Initial load
duke
parents:
diff changeset
1064 HeapWord* CompactibleFreeListSpace::allocate_adaptive_freelists(size_t size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1065 assert_lock_strong(freelistLock());
a61af66fc99e Initial load
duke
parents:
diff changeset
1066 HeapWord* res = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
1067 assert(size == adjustObjectSize(size),
a61af66fc99e Initial load
duke
parents:
diff changeset
1068 "use adjustObjectSize() before calling into allocate()");
a61af66fc99e Initial load
duke
parents:
diff changeset
1069
a61af66fc99e Initial load
duke
parents:
diff changeset
1070 // Strategy
a61af66fc99e Initial load
duke
parents:
diff changeset
1071 // if small
a61af66fc99e Initial load
duke
parents:
diff changeset
1072 // exact size from small object indexed list if small
a61af66fc99e Initial load
duke
parents:
diff changeset
1073 // small or large linear allocation block (linAB) as appropriate
a61af66fc99e Initial load
duke
parents:
diff changeset
1074 // take from lists of greater sized chunks
a61af66fc99e Initial load
duke
parents:
diff changeset
1075 // else
a61af66fc99e Initial load
duke
parents:
diff changeset
1076 // dictionary
a61af66fc99e Initial load
duke
parents:
diff changeset
1077 // small or large linear allocation block if it has the space
a61af66fc99e Initial load
duke
parents:
diff changeset
1078 // Try allocating exact size from indexTable first
a61af66fc99e Initial load
duke
parents:
diff changeset
1079 if (size < IndexSetSize) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1080 res = (HeapWord*) getChunkFromIndexedFreeList(size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1081 if(res != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1082 assert(res != (HeapWord*)_indexedFreeList[size].head(),
a61af66fc99e Initial load
duke
parents:
diff changeset
1083 "Not removed from free list");
a61af66fc99e Initial load
duke
parents:
diff changeset
1084 // no block offset table adjustment is necessary on blocks in
a61af66fc99e Initial load
duke
parents:
diff changeset
1085 // the indexed lists.
a61af66fc99e Initial load
duke
parents:
diff changeset
1086
a61af66fc99e Initial load
duke
parents:
diff changeset
1087 // Try allocating from the small LinAB
a61af66fc99e Initial load
duke
parents:
diff changeset
1088 } else if (size < _smallLinearAllocBlock._allocation_size_limit &&
a61af66fc99e Initial load
duke
parents:
diff changeset
1089 (res = getChunkFromSmallLinearAllocBlock(size)) != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1090 // if successful, the above also adjusts block offset table
a61af66fc99e Initial load
duke
parents:
diff changeset
1091 // Note that this call will refill the LinAB to
a61af66fc99e Initial load
duke
parents:
diff changeset
1092 // satisfy the request. This is different that
a61af66fc99e Initial load
duke
parents:
diff changeset
1093 // evm.
a61af66fc99e Initial load
duke
parents:
diff changeset
1094 // Don't record chunk off a LinAB? smallSplitBirth(size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1095
a61af66fc99e Initial load
duke
parents:
diff changeset
1096 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1097 // Raid the exact free lists larger than size, even if they are not
a61af66fc99e Initial load
duke
parents:
diff changeset
1098 // overpopulated.
a61af66fc99e Initial load
duke
parents:
diff changeset
1099 res = (HeapWord*) getChunkFromGreater(size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1100 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1101 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1102 // Big objects get allocated directly from the dictionary.
a61af66fc99e Initial load
duke
parents:
diff changeset
1103 res = (HeapWord*) getChunkFromDictionaryExact(size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1104 if (res == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1105 // Try hard not to fail since an allocation failure will likely
a61af66fc99e Initial load
duke
parents:
diff changeset
1106 // trigger a synchronous GC. Try to get the space from the
a61af66fc99e Initial load
duke
parents:
diff changeset
1107 // allocation blocks.
a61af66fc99e Initial load
duke
parents:
diff changeset
1108 res = getChunkFromSmallLinearAllocBlockRemainder(size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1109 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1110 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1111
a61af66fc99e Initial load
duke
parents:
diff changeset
1112 return res;
a61af66fc99e Initial load
duke
parents:
diff changeset
1113 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1114
a61af66fc99e Initial load
duke
parents:
diff changeset
1115 // A worst-case estimate of the space required (in HeapWords) to expand the heap
a61af66fc99e Initial load
duke
parents:
diff changeset
1116 // when promoting obj.
a61af66fc99e Initial load
duke
parents:
diff changeset
1117 size_t CompactibleFreeListSpace::expansionSpaceRequired(size_t obj_size) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
1118 // Depending on the object size, expansion may require refilling either a
a61af66fc99e Initial load
duke
parents:
diff changeset
1119 // bigLAB or a smallLAB plus refilling a PromotionInfo object. MinChunkSize
a61af66fc99e Initial load
duke
parents:
diff changeset
1120 // is added because the dictionary may over-allocate to avoid fragmentation.
a61af66fc99e Initial load
duke
parents:
diff changeset
1121 size_t space = obj_size;
a61af66fc99e Initial load
duke
parents:
diff changeset
1122 if (!_adaptive_freelists) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1123 space = MAX2(space, _smallLinearAllocBlock._refillSize);
a61af66fc99e Initial load
duke
parents:
diff changeset
1124 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1125 space += _promoInfo.refillSize() + 2 * MinChunkSize;
a61af66fc99e Initial load
duke
parents:
diff changeset
1126 return space;
a61af66fc99e Initial load
duke
parents:
diff changeset
1127 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1128
a61af66fc99e Initial load
duke
parents:
diff changeset
1129 FreeChunk* CompactibleFreeListSpace::getChunkFromGreater(size_t numWords) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1130 FreeChunk* ret;
a61af66fc99e Initial load
duke
parents:
diff changeset
1131
a61af66fc99e Initial load
duke
parents:
diff changeset
1132 assert(numWords >= MinChunkSize, "Size is less than minimum");
a61af66fc99e Initial load
duke
parents:
diff changeset
1133 assert(linearAllocationWouldFail() || bestFitFirst(),
a61af66fc99e Initial load
duke
parents:
diff changeset
1134 "Should not be here");
a61af66fc99e Initial load
duke
parents:
diff changeset
1135
a61af66fc99e Initial load
duke
parents:
diff changeset
1136 size_t i;
a61af66fc99e Initial load
duke
parents:
diff changeset
1137 size_t currSize = numWords + MinChunkSize;
a61af66fc99e Initial load
duke
parents:
diff changeset
1138 assert(currSize % MinObjAlignment == 0, "currSize should be aligned");
a61af66fc99e Initial load
duke
parents:
diff changeset
1139 for (i = currSize; i < IndexSetSize; i += IndexSetStride) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1140 FreeList* fl = &_indexedFreeList[i];
a61af66fc99e Initial load
duke
parents:
diff changeset
1141 if (fl->head()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1142 ret = getFromListGreater(fl, numWords);
a61af66fc99e Initial load
duke
parents:
diff changeset
1143 assert(ret == NULL || ret->isFree(), "Should be returning a free chunk");
a61af66fc99e Initial load
duke
parents:
diff changeset
1144 return ret;
a61af66fc99e Initial load
duke
parents:
diff changeset
1145 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1146 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1147
a61af66fc99e Initial load
duke
parents:
diff changeset
1148 currSize = MAX2((size_t)SmallForDictionary,
a61af66fc99e Initial load
duke
parents:
diff changeset
1149 (size_t)(numWords + MinChunkSize));
a61af66fc99e Initial load
duke
parents:
diff changeset
1150
a61af66fc99e Initial load
duke
parents:
diff changeset
1151 /* Try to get a chunk that satisfies request, while avoiding
a61af66fc99e Initial load
duke
parents:
diff changeset
1152 fragmentation that can't be handled. */
a61af66fc99e Initial load
duke
parents:
diff changeset
1153 {
a61af66fc99e Initial load
duke
parents:
diff changeset
1154 ret = dictionary()->getChunk(currSize);
a61af66fc99e Initial load
duke
parents:
diff changeset
1155 if (ret != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1156 assert(ret->size() - numWords >= MinChunkSize,
a61af66fc99e Initial load
duke
parents:
diff changeset
1157 "Chunk is too small");
a61af66fc99e Initial load
duke
parents:
diff changeset
1158 _bt.allocated((HeapWord*)ret, ret->size());
a61af66fc99e Initial load
duke
parents:
diff changeset
1159 /* Carve returned chunk. */
a61af66fc99e Initial load
duke
parents:
diff changeset
1160 (void) splitChunkAndReturnRemainder(ret, numWords);
a61af66fc99e Initial load
duke
parents:
diff changeset
1161 /* Label this as no longer a free chunk. */
a61af66fc99e Initial load
duke
parents:
diff changeset
1162 assert(ret->isFree(), "This chunk should be free");
a61af66fc99e Initial load
duke
parents:
diff changeset
1163 ret->linkPrev(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
1164 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1165 assert(ret == NULL || ret->isFree(), "Should be returning a free chunk");
a61af66fc99e Initial load
duke
parents:
diff changeset
1166 return ret;
a61af66fc99e Initial load
duke
parents:
diff changeset
1167 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1168 ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
1169 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1170
a61af66fc99e Initial load
duke
parents:
diff changeset
1171 bool CompactibleFreeListSpace::verifyChunkInIndexedFreeLists(FreeChunk* fc)
a61af66fc99e Initial load
duke
parents:
diff changeset
1172 const {
a61af66fc99e Initial load
duke
parents:
diff changeset
1173 assert(fc->size() < IndexSetSize, "Size of chunk is too large");
a61af66fc99e Initial load
duke
parents:
diff changeset
1174 return _indexedFreeList[fc->size()].verifyChunkInFreeLists(fc);
a61af66fc99e Initial load
duke
parents:
diff changeset
1175 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1176
a61af66fc99e Initial load
duke
parents:
diff changeset
1177 bool CompactibleFreeListSpace::verifyChunkInFreeLists(FreeChunk* fc) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
1178 if (fc->size() >= IndexSetSize) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1179 return dictionary()->verifyChunkInFreeLists(fc);
a61af66fc99e Initial load
duke
parents:
diff changeset
1180 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1181 return verifyChunkInIndexedFreeLists(fc);
a61af66fc99e Initial load
duke
parents:
diff changeset
1182 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1183 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1184
a61af66fc99e Initial load
duke
parents:
diff changeset
1185 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
1186 void CompactibleFreeListSpace::assert_locked() const {
a61af66fc99e Initial load
duke
parents:
diff changeset
1187 CMSLockVerifier::assert_locked(freelistLock(), parDictionaryAllocLock());
a61af66fc99e Initial load
duke
parents:
diff changeset
1188 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1189 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
1190
a61af66fc99e Initial load
duke
parents:
diff changeset
1191 FreeChunk* CompactibleFreeListSpace::allocateScratch(size_t size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1192 // In the parallel case, the main thread holds the free list lock
a61af66fc99e Initial load
duke
parents:
diff changeset
1193 // on behalf the parallel threads.
a61af66fc99e Initial load
duke
parents:
diff changeset
1194 assert_locked();
a61af66fc99e Initial load
duke
parents:
diff changeset
1195 FreeChunk* fc;
a61af66fc99e Initial load
duke
parents:
diff changeset
1196 {
a61af66fc99e Initial load
duke
parents:
diff changeset
1197 // If GC is parallel, this might be called by several threads.
a61af66fc99e Initial load
duke
parents:
diff changeset
1198 // This should be rare enough that the locking overhead won't affect
a61af66fc99e Initial load
duke
parents:
diff changeset
1199 // the sequential code.
a61af66fc99e Initial load
duke
parents:
diff changeset
1200 MutexLockerEx x(parDictionaryAllocLock(),
a61af66fc99e Initial load
duke
parents:
diff changeset
1201 Mutex::_no_safepoint_check_flag);
a61af66fc99e Initial load
duke
parents:
diff changeset
1202 fc = getChunkFromDictionary(size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1203 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1204 if (fc != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1205 fc->dontCoalesce();
a61af66fc99e Initial load
duke
parents:
diff changeset
1206 assert(fc->isFree(), "Should be free, but not coalescable");
a61af66fc99e Initial load
duke
parents:
diff changeset
1207 // Verify that the block offset table shows this to
a61af66fc99e Initial load
duke
parents:
diff changeset
1208 // be a single block, but not one which is unallocated.
a61af66fc99e Initial load
duke
parents:
diff changeset
1209 _bt.verify_single_block((HeapWord*)fc, fc->size());
a61af66fc99e Initial load
duke
parents:
diff changeset
1210 _bt.verify_not_unallocated((HeapWord*)fc, fc->size());
a61af66fc99e Initial load
duke
parents:
diff changeset
1211 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1212 return fc;
a61af66fc99e Initial load
duke
parents:
diff changeset
1213 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1214
113
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 12
diff changeset
1215 oop CompactibleFreeListSpace::promote(oop obj, size_t obj_size) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1216 assert(obj_size == (size_t)obj->size(), "bad obj_size passed in");
a61af66fc99e Initial load
duke
parents:
diff changeset
1217 assert_locked();
a61af66fc99e Initial load
duke
parents:
diff changeset
1218
a61af66fc99e Initial load
duke
parents:
diff changeset
1219 // if we are tracking promotions, then first ensure space for
a61af66fc99e Initial load
duke
parents:
diff changeset
1220 // promotion (including spooling space for saving header if necessary).
a61af66fc99e Initial load
duke
parents:
diff changeset
1221 // then allocate and copy, then track promoted info if needed.
a61af66fc99e Initial load
duke
parents:
diff changeset
1222 // When tracking (see PromotionInfo::track()), the mark word may
a61af66fc99e Initial load
duke
parents:
diff changeset
1223 // be displaced and in this case restoration of the mark word
a61af66fc99e Initial load
duke
parents:
diff changeset
1224 // occurs in the (oop_since_save_marks_)iterate phase.
a61af66fc99e Initial load
duke
parents:
diff changeset
1225 if (_promoInfo.tracking() && !_promoInfo.ensure_spooling_space()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1226 return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
1227 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1228 // Call the allocate(size_t, bool) form directly to avoid the
a61af66fc99e Initial load
duke
parents:
diff changeset
1229 // additional call through the allocate(size_t) form. Having
a61af66fc99e Initial load
duke
parents:
diff changeset
1230 // the compile inline the call is problematic because allocate(size_t)
a61af66fc99e Initial load
duke
parents:
diff changeset
1231 // is a virtual method.
a61af66fc99e Initial load
duke
parents:
diff changeset
1232 HeapWord* res = allocate(adjustObjectSize(obj_size));
a61af66fc99e Initial load
duke
parents:
diff changeset
1233 if (res != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1234 Copy::aligned_disjoint_words((HeapWord*)obj, res, obj_size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1235 // if we should be tracking promotions, do so.
a61af66fc99e Initial load
duke
parents:
diff changeset
1236 if (_promoInfo.tracking()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1237 _promoInfo.track((PromotedObject*)res);
a61af66fc99e Initial load
duke
parents:
diff changeset
1238 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1239 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1240 return oop(res);
a61af66fc99e Initial load
duke
parents:
diff changeset
1241 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1242
a61af66fc99e Initial load
duke
parents:
diff changeset
1243 HeapWord*
a61af66fc99e Initial load
duke
parents:
diff changeset
1244 CompactibleFreeListSpace::getChunkFromSmallLinearAllocBlock(size_t size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1245 assert_locked();
a61af66fc99e Initial load
duke
parents:
diff changeset
1246 assert(size >= MinChunkSize, "minimum chunk size");
a61af66fc99e Initial load
duke
parents:
diff changeset
1247 assert(size < _smallLinearAllocBlock._allocation_size_limit,
a61af66fc99e Initial load
duke
parents:
diff changeset
1248 "maximum from smallLinearAllocBlock");
a61af66fc99e Initial load
duke
parents:
diff changeset
1249 return getChunkFromLinearAllocBlock(&_smallLinearAllocBlock, size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1250 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1251
a61af66fc99e Initial load
duke
parents:
diff changeset
1252 HeapWord*
a61af66fc99e Initial load
duke
parents:
diff changeset
1253 CompactibleFreeListSpace::getChunkFromLinearAllocBlock(LinearAllocBlock *blk,
a61af66fc99e Initial load
duke
parents:
diff changeset
1254 size_t size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1255 assert_locked();
a61af66fc99e Initial load
duke
parents:
diff changeset
1256 assert(size >= MinChunkSize, "too small");
a61af66fc99e Initial load
duke
parents:
diff changeset
1257 HeapWord* res = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
1258 // Try to do linear allocation from blk, making sure that
a61af66fc99e Initial load
duke
parents:
diff changeset
1259 if (blk->_word_size == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1260 // We have probably been unable to fill this either in the prologue or
a61af66fc99e Initial load
duke
parents:
diff changeset
1261 // when it was exhausted at the last linear allocation. Bail out until
a61af66fc99e Initial load
duke
parents:
diff changeset
1262 // next time.
a61af66fc99e Initial load
duke
parents:
diff changeset
1263 assert(blk->_ptr == NULL, "consistency check");
a61af66fc99e Initial load
duke
parents:
diff changeset
1264 return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
1265 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1266 assert(blk->_word_size != 0 && blk->_ptr != NULL, "consistency check");
a61af66fc99e Initial load
duke
parents:
diff changeset
1267 res = getChunkFromLinearAllocBlockRemainder(blk, size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1268 if (res != NULL) return res;
a61af66fc99e Initial load
duke
parents:
diff changeset
1269
a61af66fc99e Initial load
duke
parents:
diff changeset
1270 // about to exhaust this linear allocation block
a61af66fc99e Initial load
duke
parents:
diff changeset
1271 if (blk->_word_size == size) { // exactly satisfied
a61af66fc99e Initial load
duke
parents:
diff changeset
1272 res = blk->_ptr;
a61af66fc99e Initial load
duke
parents:
diff changeset
1273 _bt.allocated(res, blk->_word_size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1274 } else if (size + MinChunkSize <= blk->_refillSize) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1275 // Update _unallocated_block if the size is such that chunk would be
a61af66fc99e Initial load
duke
parents:
diff changeset
1276 // returned to the indexed free list. All other chunks in the indexed
a61af66fc99e Initial load
duke
parents:
diff changeset
1277 // free lists are allocated from the dictionary so that _unallocated_block
a61af66fc99e Initial load
duke
parents:
diff changeset
1278 // has already been adjusted for them. Do it here so that the cost
a61af66fc99e Initial load
duke
parents:
diff changeset
1279 // for all chunks added back to the indexed free lists.
a61af66fc99e Initial load
duke
parents:
diff changeset
1280 if (blk->_word_size < SmallForDictionary) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1281 _bt.allocated(blk->_ptr, blk->_word_size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1282 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1283 // Return the chunk that isn't big enough, and then refill below.
a61af66fc99e Initial load
duke
parents:
diff changeset
1284 addChunkToFreeLists(blk->_ptr, blk->_word_size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1285 _bt.verify_single_block(blk->_ptr, (blk->_ptr + blk->_word_size));
a61af66fc99e Initial load
duke
parents:
diff changeset
1286 // Don't keep statistics on adding back chunk from a LinAB.
a61af66fc99e Initial load
duke
parents:
diff changeset
1287 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1288 // A refilled block would not satisfy the request.
a61af66fc99e Initial load
duke
parents:
diff changeset
1289 return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
1290 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1291
a61af66fc99e Initial load
duke
parents:
diff changeset
1292 blk->_ptr = NULL; blk->_word_size = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1293 refillLinearAllocBlock(blk);
a61af66fc99e Initial load
duke
parents:
diff changeset
1294 assert(blk->_ptr == NULL || blk->_word_size >= size + MinChunkSize,
a61af66fc99e Initial load
duke
parents:
diff changeset
1295 "block was replenished");
a61af66fc99e Initial load
duke
parents:
diff changeset
1296 if (res != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1297 splitBirth(size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1298 repairLinearAllocBlock(blk);
a61af66fc99e Initial load
duke
parents:
diff changeset
1299 } else if (blk->_ptr != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1300 res = blk->_ptr;
a61af66fc99e Initial load
duke
parents:
diff changeset
1301 size_t blk_size = blk->_word_size;
a61af66fc99e Initial load
duke
parents:
diff changeset
1302 blk->_word_size -= size;
a61af66fc99e Initial load
duke
parents:
diff changeset
1303 blk->_ptr += size;
a61af66fc99e Initial load
duke
parents:
diff changeset
1304 splitBirth(size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1305 repairLinearAllocBlock(blk);
a61af66fc99e Initial load
duke
parents:
diff changeset
1306 // Update BOT last so that other (parallel) GC threads see a consistent
a61af66fc99e Initial load
duke
parents:
diff changeset
1307 // view of the BOT and free blocks.
a61af66fc99e Initial load
duke
parents:
diff changeset
1308 // Above must occur before BOT is updated below.
a61af66fc99e Initial load
duke
parents:
diff changeset
1309 _bt.split_block(res, blk_size, size); // adjust block offset table
a61af66fc99e Initial load
duke
parents:
diff changeset
1310 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1311 return res;
a61af66fc99e Initial load
duke
parents:
diff changeset
1312 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1313
a61af66fc99e Initial load
duke
parents:
diff changeset
1314 HeapWord* CompactibleFreeListSpace::getChunkFromLinearAllocBlockRemainder(
a61af66fc99e Initial load
duke
parents:
diff changeset
1315 LinearAllocBlock* blk,
a61af66fc99e Initial load
duke
parents:
diff changeset
1316 size_t size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1317 assert_locked();
a61af66fc99e Initial load
duke
parents:
diff changeset
1318 assert(size >= MinChunkSize, "too small");
a61af66fc99e Initial load
duke
parents:
diff changeset
1319
a61af66fc99e Initial load
duke
parents:
diff changeset
1320 HeapWord* res = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
1321 // This is the common case. Keep it simple.
a61af66fc99e Initial load
duke
parents:
diff changeset
1322 if (blk->_word_size >= size + MinChunkSize) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1323 assert(blk->_ptr != NULL, "consistency check");
a61af66fc99e Initial load
duke
parents:
diff changeset
1324 res = blk->_ptr;
a61af66fc99e Initial load
duke
parents:
diff changeset
1325 // Note that the BOT is up-to-date for the linAB before allocation. It
a61af66fc99e Initial load
duke
parents:
diff changeset
1326 // indicates the start of the linAB. The split_block() updates the
a61af66fc99e Initial load
duke
parents:
diff changeset
1327 // BOT for the linAB after the allocation (indicates the start of the
a61af66fc99e Initial load
duke
parents:
diff changeset
1328 // next chunk to be allocated).
a61af66fc99e Initial load
duke
parents:
diff changeset
1329 size_t blk_size = blk->_word_size;
a61af66fc99e Initial load
duke
parents:
diff changeset
1330 blk->_word_size -= size;
a61af66fc99e Initial load
duke
parents:
diff changeset
1331 blk->_ptr += size;
a61af66fc99e Initial load
duke
parents:
diff changeset
1332 splitBirth(size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1333 repairLinearAllocBlock(blk);
a61af66fc99e Initial load
duke
parents:
diff changeset
1334 // Update BOT last so that other (parallel) GC threads see a consistent
a61af66fc99e Initial load
duke
parents:
diff changeset
1335 // view of the BOT and free blocks.
a61af66fc99e Initial load
duke
parents:
diff changeset
1336 // Above must occur before BOT is updated below.
a61af66fc99e Initial load
duke
parents:
diff changeset
1337 _bt.split_block(res, blk_size, size); // adjust block offset table
a61af66fc99e Initial load
duke
parents:
diff changeset
1338 _bt.allocated(res, size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1339 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1340 return res;
a61af66fc99e Initial load
duke
parents:
diff changeset
1341 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1342
a61af66fc99e Initial load
duke
parents:
diff changeset
1343 FreeChunk*
a61af66fc99e Initial load
duke
parents:
diff changeset
1344 CompactibleFreeListSpace::getChunkFromIndexedFreeList(size_t size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1345 assert_locked();
a61af66fc99e Initial load
duke
parents:
diff changeset
1346 assert(size < SmallForDictionary, "just checking");
a61af66fc99e Initial load
duke
parents:
diff changeset
1347 FreeChunk* res;
a61af66fc99e Initial load
duke
parents:
diff changeset
1348 res = _indexedFreeList[size].getChunkAtHead();
a61af66fc99e Initial load
duke
parents:
diff changeset
1349 if (res == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1350 res = getChunkFromIndexedFreeListHelper(size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1351 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1352 _bt.verify_not_unallocated((HeapWord*) res, size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1353 return res;
a61af66fc99e Initial load
duke
parents:
diff changeset
1354 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1355
a61af66fc99e Initial load
duke
parents:
diff changeset
1356 FreeChunk*
a61af66fc99e Initial load
duke
parents:
diff changeset
1357 CompactibleFreeListSpace::getChunkFromIndexedFreeListHelper(size_t size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1358 assert_locked();
a61af66fc99e Initial load
duke
parents:
diff changeset
1359 FreeChunk* fc = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
1360 if (size < SmallForDictionary) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1361 assert(_indexedFreeList[size].head() == NULL ||
a61af66fc99e Initial load
duke
parents:
diff changeset
1362 _indexedFreeList[size].surplus() <= 0,
a61af66fc99e Initial load
duke
parents:
diff changeset
1363 "List for this size should be empty or under populated");
a61af66fc99e Initial load
duke
parents:
diff changeset
1364 // Try best fit in exact lists before replenishing the list
a61af66fc99e Initial load
duke
parents:
diff changeset
1365 if (!bestFitFirst() || (fc = bestFitSmall(size)) == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1366 // Replenish list.
a61af66fc99e Initial load
duke
parents:
diff changeset
1367 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1368 // Things tried that failed.
a61af66fc99e Initial load
duke
parents:
diff changeset
1369 // Tried allocating out of the two LinAB's first before
a61af66fc99e Initial load
duke
parents:
diff changeset
1370 // replenishing lists.
a61af66fc99e Initial load
duke
parents:
diff changeset
1371 // Tried small linAB of size 256 (size in indexed list)
a61af66fc99e Initial load
duke
parents:
diff changeset
1372 // and replenishing indexed lists from the small linAB.
a61af66fc99e Initial load
duke
parents:
diff changeset
1373 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1374 FreeChunk* newFc = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
1375 size_t replenish_size = CMSIndexedFreeListReplenish * size;
a61af66fc99e Initial load
duke
parents:
diff changeset
1376 if (replenish_size < SmallForDictionary) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1377 // Do not replenish from an underpopulated size.
a61af66fc99e Initial load
duke
parents:
diff changeset
1378 if (_indexedFreeList[replenish_size].surplus() > 0 &&
a61af66fc99e Initial load
duke
parents:
diff changeset
1379 _indexedFreeList[replenish_size].head() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1380 newFc =
a61af66fc99e Initial load
duke
parents:
diff changeset
1381 _indexedFreeList[replenish_size].getChunkAtHead();
a61af66fc99e Initial load
duke
parents:
diff changeset
1382 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1383 newFc = bestFitSmall(replenish_size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1384 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1385 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1386 if (newFc != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1387 splitDeath(replenish_size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1388 } else if (replenish_size > size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1389 assert(CMSIndexedFreeListReplenish > 1, "ctl pt invariant");
a61af66fc99e Initial load
duke
parents:
diff changeset
1390 newFc =
a61af66fc99e Initial load
duke
parents:
diff changeset
1391 getChunkFromIndexedFreeListHelper(replenish_size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1392 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1393 if (newFc != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1394 assert(newFc->size() == replenish_size, "Got wrong size");
a61af66fc99e Initial load
duke
parents:
diff changeset
1395 size_t i;
a61af66fc99e Initial load
duke
parents:
diff changeset
1396 FreeChunk *curFc, *nextFc;
a61af66fc99e Initial load
duke
parents:
diff changeset
1397 // carve up and link blocks 0, ..., CMSIndexedFreeListReplenish - 2
a61af66fc99e Initial load
duke
parents:
diff changeset
1398 // The last chunk is not added to the lists but is returned as the
a61af66fc99e Initial load
duke
parents:
diff changeset
1399 // free chunk.
a61af66fc99e Initial load
duke
parents:
diff changeset
1400 for (curFc = newFc, nextFc = (FreeChunk*)((HeapWord*)curFc + size),
a61af66fc99e Initial load
duke
parents:
diff changeset
1401 i = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1402 i < (CMSIndexedFreeListReplenish - 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1403 curFc = nextFc, nextFc = (FreeChunk*)((HeapWord*)nextFc + size),
a61af66fc99e Initial load
duke
parents:
diff changeset
1404 i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1405 curFc->setSize(size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1406 // Don't record this as a return in order to try and
a61af66fc99e Initial load
duke
parents:
diff changeset
1407 // determine the "returns" from a GC.
a61af66fc99e Initial load
duke
parents:
diff changeset
1408 _bt.verify_not_unallocated((HeapWord*) fc, size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1409 _indexedFreeList[size].returnChunkAtTail(curFc, false);
a61af66fc99e Initial load
duke
parents:
diff changeset
1410 _bt.mark_block((HeapWord*)curFc, size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1411 splitBirth(size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1412 // Don't record the initial population of the indexed list
a61af66fc99e Initial load
duke
parents:
diff changeset
1413 // as a split birth.
a61af66fc99e Initial load
duke
parents:
diff changeset
1414 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1415
a61af66fc99e Initial load
duke
parents:
diff changeset
1416 // check that the arithmetic was OK above
a61af66fc99e Initial load
duke
parents:
diff changeset
1417 assert((HeapWord*)nextFc == (HeapWord*)newFc + replenish_size,
a61af66fc99e Initial load
duke
parents:
diff changeset
1418 "inconsistency in carving newFc");
a61af66fc99e Initial load
duke
parents:
diff changeset
1419 curFc->setSize(size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1420 _bt.mark_block((HeapWord*)curFc, size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1421 splitBirth(size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1422 return curFc;
a61af66fc99e Initial load
duke
parents:
diff changeset
1423 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1424 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1425 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1426 // Get a free chunk from the free chunk dictionary to be returned to
a61af66fc99e Initial load
duke
parents:
diff changeset
1427 // replenish the indexed free list.
a61af66fc99e Initial load
duke
parents:
diff changeset
1428 fc = getChunkFromDictionaryExact(size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1429 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1430 assert(fc == NULL || fc->isFree(), "Should be returning a free chunk");
a61af66fc99e Initial load
duke
parents:
diff changeset
1431 return fc;
a61af66fc99e Initial load
duke
parents:
diff changeset
1432 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1433
a61af66fc99e Initial load
duke
parents:
diff changeset
1434 FreeChunk*
a61af66fc99e Initial load
duke
parents:
diff changeset
1435 CompactibleFreeListSpace::getChunkFromDictionary(size_t size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1436 assert_locked();
a61af66fc99e Initial load
duke
parents:
diff changeset
1437 FreeChunk* fc = _dictionary->getChunk(size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1438 if (fc == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1439 return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
1440 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1441 _bt.allocated((HeapWord*)fc, fc->size());
a61af66fc99e Initial load
duke
parents:
diff changeset
1442 if (fc->size() >= size + MinChunkSize) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1443 fc = splitChunkAndReturnRemainder(fc, size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1444 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1445 assert(fc->size() >= size, "chunk too small");
a61af66fc99e Initial load
duke
parents:
diff changeset
1446 assert(fc->size() < size + MinChunkSize, "chunk too big");
a61af66fc99e Initial load
duke
parents:
diff changeset
1447 _bt.verify_single_block((HeapWord*)fc, fc->size());
a61af66fc99e Initial load
duke
parents:
diff changeset
1448 return fc;
a61af66fc99e Initial load
duke
parents:
diff changeset
1449 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1450
a61af66fc99e Initial load
duke
parents:
diff changeset
1451 FreeChunk*
a61af66fc99e Initial load
duke
parents:
diff changeset
1452 CompactibleFreeListSpace::getChunkFromDictionaryExact(size_t size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1453 assert_locked();
a61af66fc99e Initial load
duke
parents:
diff changeset
1454 FreeChunk* fc = _dictionary->getChunk(size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1455 if (fc == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1456 return fc;
a61af66fc99e Initial load
duke
parents:
diff changeset
1457 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1458 _bt.allocated((HeapWord*)fc, fc->size());
a61af66fc99e Initial load
duke
parents:
diff changeset
1459 if (fc->size() == size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1460 _bt.verify_single_block((HeapWord*)fc, size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1461 return fc;
a61af66fc99e Initial load
duke
parents:
diff changeset
1462 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1463 assert(fc->size() > size, "getChunk() guarantee");
a61af66fc99e Initial load
duke
parents:
diff changeset
1464 if (fc->size() < size + MinChunkSize) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1465 // Return the chunk to the dictionary and go get a bigger one.
a61af66fc99e Initial load
duke
parents:
diff changeset
1466 returnChunkToDictionary(fc);
a61af66fc99e Initial load
duke
parents:
diff changeset
1467 fc = _dictionary->getChunk(size + MinChunkSize);
a61af66fc99e Initial load
duke
parents:
diff changeset
1468 if (fc == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1469 return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
1470 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1471 _bt.allocated((HeapWord*)fc, fc->size());
a61af66fc99e Initial load
duke
parents:
diff changeset
1472 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1473 assert(fc->size() >= size + MinChunkSize, "tautology");
a61af66fc99e Initial load
duke
parents:
diff changeset
1474 fc = splitChunkAndReturnRemainder(fc, size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1475 assert(fc->size() == size, "chunk is wrong size");
a61af66fc99e Initial load
duke
parents:
diff changeset
1476 _bt.verify_single_block((HeapWord*)fc, size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1477 return fc;
a61af66fc99e Initial load
duke
parents:
diff changeset
1478 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1479
a61af66fc99e Initial load
duke
parents:
diff changeset
1480 void
a61af66fc99e Initial load
duke
parents:
diff changeset
1481 CompactibleFreeListSpace::returnChunkToDictionary(FreeChunk* chunk) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1482 assert_locked();
a61af66fc99e Initial load
duke
parents:
diff changeset
1483
a61af66fc99e Initial load
duke
parents:
diff changeset
1484 size_t size = chunk->size();
a61af66fc99e Initial load
duke
parents:
diff changeset
1485 _bt.verify_single_block((HeapWord*)chunk, size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1486 // adjust _unallocated_block downward, as necessary
a61af66fc99e Initial load
duke
parents:
diff changeset
1487 _bt.freed((HeapWord*)chunk, size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1488 _dictionary->returnChunk(chunk);
a61af66fc99e Initial load
duke
parents:
diff changeset
1489 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1490
a61af66fc99e Initial load
duke
parents:
diff changeset
1491 void
a61af66fc99e Initial load
duke
parents:
diff changeset
1492 CompactibleFreeListSpace::returnChunkToFreeList(FreeChunk* fc) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1493 assert_locked();
a61af66fc99e Initial load
duke
parents:
diff changeset
1494 size_t size = fc->size();
a61af66fc99e Initial load
duke
parents:
diff changeset
1495 _bt.verify_single_block((HeapWord*) fc, size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1496 _bt.verify_not_unallocated((HeapWord*) fc, size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1497 if (_adaptive_freelists) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1498 _indexedFreeList[size].returnChunkAtTail(fc);
a61af66fc99e Initial load
duke
parents:
diff changeset
1499 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1500 _indexedFreeList[size].returnChunkAtHead(fc);
a61af66fc99e Initial load
duke
parents:
diff changeset
1501 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1502 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1503
a61af66fc99e Initial load
duke
parents:
diff changeset
1504 // Add chunk to end of last block -- if it's the largest
a61af66fc99e Initial load
duke
parents:
diff changeset
1505 // block -- and update BOT and census data. We would
a61af66fc99e Initial load
duke
parents:
diff changeset
1506 // of course have preferred to coalesce it with the
a61af66fc99e Initial load
duke
parents:
diff changeset
1507 // last block, but it's currently less expensive to find the
a61af66fc99e Initial load
duke
parents:
diff changeset
1508 // largest block than it is to find the last.
a61af66fc99e Initial load
duke
parents:
diff changeset
1509 void
a61af66fc99e Initial load
duke
parents:
diff changeset
1510 CompactibleFreeListSpace::addChunkToFreeListsAtEndRecordingStats(
a61af66fc99e Initial load
duke
parents:
diff changeset
1511 HeapWord* chunk, size_t size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1512 // check that the chunk does lie in this space!
a61af66fc99e Initial load
duke
parents:
diff changeset
1513 assert(chunk != NULL && is_in_reserved(chunk), "Not in this space!");
a61af66fc99e Initial load
duke
parents:
diff changeset
1514 assert_locked();
a61af66fc99e Initial load
duke
parents:
diff changeset
1515 // One of the parallel gc task threads may be here
a61af66fc99e Initial load
duke
parents:
diff changeset
1516 // whilst others are allocating.
a61af66fc99e Initial load
duke
parents:
diff changeset
1517 Mutex* lock = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
1518 if (ParallelGCThreads != 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1519 lock = &_parDictionaryAllocLock;
a61af66fc99e Initial load
duke
parents:
diff changeset
1520 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1521 FreeChunk* ec;
a61af66fc99e Initial load
duke
parents:
diff changeset
1522 {
a61af66fc99e Initial load
duke
parents:
diff changeset
1523 MutexLockerEx x(lock, Mutex::_no_safepoint_check_flag);
a61af66fc99e Initial load
duke
parents:
diff changeset
1524 ec = dictionary()->findLargestDict(); // get largest block
a61af66fc99e Initial load
duke
parents:
diff changeset
1525 if (ec != NULL && ec->end() == chunk) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1526 // It's a coterminal block - we can coalesce.
a61af66fc99e Initial load
duke
parents:
diff changeset
1527 size_t old_size = ec->size();
a61af66fc99e Initial load
duke
parents:
diff changeset
1528 coalDeath(old_size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1529 removeChunkFromDictionary(ec);
a61af66fc99e Initial load
duke
parents:
diff changeset
1530 size += old_size;
a61af66fc99e Initial load
duke
parents:
diff changeset
1531 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1532 ec = (FreeChunk*)chunk;
a61af66fc99e Initial load
duke
parents:
diff changeset
1533 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1534 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1535 ec->setSize(size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1536 debug_only(ec->mangleFreed(size));
a61af66fc99e Initial load
duke
parents:
diff changeset
1537 if (size < SmallForDictionary) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1538 lock = _indexedFreeListParLocks[size];
a61af66fc99e Initial load
duke
parents:
diff changeset
1539 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1540 MutexLockerEx x(lock, Mutex::_no_safepoint_check_flag);
a61af66fc99e Initial load
duke
parents:
diff changeset
1541 addChunkAndRepairOffsetTable((HeapWord*)ec, size, true);
a61af66fc99e Initial load
duke
parents:
diff changeset
1542 // record the birth under the lock since the recording involves
a61af66fc99e Initial load
duke
parents:
diff changeset
1543 // manipulation of the list on which the chunk lives and
a61af66fc99e Initial load
duke
parents:
diff changeset
1544 // if the chunk is allocated and is the last on the list,
a61af66fc99e Initial load
duke
parents:
diff changeset
1545 // the list can go away.
a61af66fc99e Initial load
duke
parents:
diff changeset
1546 coalBirth(size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1547 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1548
a61af66fc99e Initial load
duke
parents:
diff changeset
1549 void
a61af66fc99e Initial load
duke
parents:
diff changeset
1550 CompactibleFreeListSpace::addChunkToFreeLists(HeapWord* chunk,
a61af66fc99e Initial load
duke
parents:
diff changeset
1551 size_t size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1552 // check that the chunk does lie in this space!
a61af66fc99e Initial load
duke
parents:
diff changeset
1553 assert(chunk != NULL && is_in_reserved(chunk), "Not in this space!");
a61af66fc99e Initial load
duke
parents:
diff changeset
1554 assert_locked();
a61af66fc99e Initial load
duke
parents:
diff changeset
1555 _bt.verify_single_block(chunk, size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1556
a61af66fc99e Initial load
duke
parents:
diff changeset
1557 FreeChunk* fc = (FreeChunk*) chunk;
a61af66fc99e Initial load
duke
parents:
diff changeset
1558 fc->setSize(size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1559 debug_only(fc->mangleFreed(size));
a61af66fc99e Initial load
duke
parents:
diff changeset
1560 if (size < SmallForDictionary) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1561 returnChunkToFreeList(fc);
a61af66fc99e Initial load
duke
parents:
diff changeset
1562 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1563 returnChunkToDictionary(fc);
a61af66fc99e Initial load
duke
parents:
diff changeset
1564 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1565 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1566
a61af66fc99e Initial load
duke
parents:
diff changeset
1567 void
a61af66fc99e Initial load
duke
parents:
diff changeset
1568 CompactibleFreeListSpace::addChunkAndRepairOffsetTable(HeapWord* chunk,
a61af66fc99e Initial load
duke
parents:
diff changeset
1569 size_t size, bool coalesced) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1570 assert_locked();
a61af66fc99e Initial load
duke
parents:
diff changeset
1571 assert(chunk != NULL, "null chunk");
a61af66fc99e Initial load
duke
parents:
diff changeset
1572 if (coalesced) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1573 // repair BOT
a61af66fc99e Initial load
duke
parents:
diff changeset
1574 _bt.single_block(chunk, size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1575 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1576 addChunkToFreeLists(chunk, size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1577 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1578
a61af66fc99e Initial load
duke
parents:
diff changeset
1579 // We _must_ find the purported chunk on our free lists;
a61af66fc99e Initial load
duke
parents:
diff changeset
1580 // we assert if we don't.
a61af66fc99e Initial load
duke
parents:
diff changeset
1581 void
a61af66fc99e Initial load
duke
parents:
diff changeset
1582 CompactibleFreeListSpace::removeFreeChunkFromFreeLists(FreeChunk* fc) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1583 size_t size = fc->size();
a61af66fc99e Initial load
duke
parents:
diff changeset
1584 assert_locked();
a61af66fc99e Initial load
duke
parents:
diff changeset
1585 debug_only(verifyFreeLists());
a61af66fc99e Initial load
duke
parents:
diff changeset
1586 if (size < SmallForDictionary) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1587 removeChunkFromIndexedFreeList(fc);
a61af66fc99e Initial load
duke
parents:
diff changeset
1588 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1589 removeChunkFromDictionary(fc);
a61af66fc99e Initial load
duke
parents:
diff changeset
1590 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1591 _bt.verify_single_block((HeapWord*)fc, size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1592 debug_only(verifyFreeLists());
a61af66fc99e Initial load
duke
parents:
diff changeset
1593 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1594
a61af66fc99e Initial load
duke
parents:
diff changeset
1595 void
a61af66fc99e Initial load
duke
parents:
diff changeset
1596 CompactibleFreeListSpace::removeChunkFromDictionary(FreeChunk* fc) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1597 size_t size = fc->size();
a61af66fc99e Initial load
duke
parents:
diff changeset
1598 assert_locked();
a61af66fc99e Initial load
duke
parents:
diff changeset
1599 assert(fc != NULL, "null chunk");
a61af66fc99e Initial load
duke
parents:
diff changeset
1600 _bt.verify_single_block((HeapWord*)fc, size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1601 _dictionary->removeChunk(fc);
a61af66fc99e Initial load
duke
parents:
diff changeset
1602 // adjust _unallocated_block upward, as necessary
a61af66fc99e Initial load
duke
parents:
diff changeset
1603 _bt.allocated((HeapWord*)fc, size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1604 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1605
a61af66fc99e Initial load
duke
parents:
diff changeset
1606 void
a61af66fc99e Initial load
duke
parents:
diff changeset
1607 CompactibleFreeListSpace::removeChunkFromIndexedFreeList(FreeChunk* fc) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1608 assert_locked();
a61af66fc99e Initial load
duke
parents:
diff changeset
1609 size_t size = fc->size();
a61af66fc99e Initial load
duke
parents:
diff changeset
1610 _bt.verify_single_block((HeapWord*)fc, size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1611 NOT_PRODUCT(
a61af66fc99e Initial load
duke
parents:
diff changeset
1612 if (FLSVerifyIndexTable) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1613 verifyIndexedFreeList(size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1614 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1615 )
a61af66fc99e Initial load
duke
parents:
diff changeset
1616 _indexedFreeList[size].removeChunk(fc);
a61af66fc99e Initial load
duke
parents:
diff changeset
1617 debug_only(fc->clearNext());
a61af66fc99e Initial load
duke
parents:
diff changeset
1618 debug_only(fc->clearPrev());
a61af66fc99e Initial load
duke
parents:
diff changeset
1619 NOT_PRODUCT(
a61af66fc99e Initial load
duke
parents:
diff changeset
1620 if (FLSVerifyIndexTable) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1621 verifyIndexedFreeList(size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1622 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1623 )
a61af66fc99e Initial load
duke
parents:
diff changeset
1624 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1625
a61af66fc99e Initial load
duke
parents:
diff changeset
1626 FreeChunk* CompactibleFreeListSpace::bestFitSmall(size_t numWords) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1627 /* A hint is the next larger size that has a surplus.
a61af66fc99e Initial load
duke
parents:
diff changeset
1628 Start search at a size large enough to guarantee that
a61af66fc99e Initial load
duke
parents:
diff changeset
1629 the excess is >= MIN_CHUNK. */
a61af66fc99e Initial load
duke
parents:
diff changeset
1630 size_t start = align_object_size(numWords + MinChunkSize);
a61af66fc99e Initial load
duke
parents:
diff changeset
1631 if (start < IndexSetSize) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1632 FreeList* it = _indexedFreeList;
a61af66fc99e Initial load
duke
parents:
diff changeset
1633 size_t hint = _indexedFreeList[start].hint();
a61af66fc99e Initial load
duke
parents:
diff changeset
1634 while (hint < IndexSetSize) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1635 assert(hint % MinObjAlignment == 0, "hint should be aligned");
a61af66fc99e Initial load
duke
parents:
diff changeset
1636 FreeList *fl = &_indexedFreeList[hint];
a61af66fc99e Initial load
duke
parents:
diff changeset
1637 if (fl->surplus() > 0 && fl->head() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1638 // Found a list with surplus, reset original hint
a61af66fc99e Initial load
duke
parents:
diff changeset
1639 // and split out a free chunk which is returned.
a61af66fc99e Initial load
duke
parents:
diff changeset
1640 _indexedFreeList[start].set_hint(hint);
a61af66fc99e Initial load
duke
parents:
diff changeset
1641 FreeChunk* res = getFromListGreater(fl, numWords);
a61af66fc99e Initial load
duke
parents:
diff changeset
1642 assert(res == NULL || res->isFree(),
a61af66fc99e Initial load
duke
parents:
diff changeset
1643 "Should be returning a free chunk");
a61af66fc99e Initial load
duke
parents:
diff changeset
1644 return res;
a61af66fc99e Initial load
duke
parents:
diff changeset
1645 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1646 hint = fl->hint(); /* keep looking */
a61af66fc99e Initial load
duke
parents:
diff changeset
1647 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1648 /* None found. */
a61af66fc99e Initial load
duke
parents:
diff changeset
1649 it[start].set_hint(IndexSetSize);
a61af66fc99e Initial load
duke
parents:
diff changeset
1650 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1651 return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
1652 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1653
a61af66fc99e Initial load
duke
parents:
diff changeset
1654 /* Requires fl->size >= numWords + MinChunkSize */
a61af66fc99e Initial load
duke
parents:
diff changeset
1655 FreeChunk* CompactibleFreeListSpace::getFromListGreater(FreeList* fl,
a61af66fc99e Initial load
duke
parents:
diff changeset
1656 size_t numWords) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1657 FreeChunk *curr = fl->head();
a61af66fc99e Initial load
duke
parents:
diff changeset
1658 size_t oldNumWords = curr->size();
a61af66fc99e Initial load
duke
parents:
diff changeset
1659 assert(numWords >= MinChunkSize, "Word size is too small");
a61af66fc99e Initial load
duke
parents:
diff changeset
1660 assert(curr != NULL, "List is empty");
a61af66fc99e Initial load
duke
parents:
diff changeset
1661 assert(oldNumWords >= numWords + MinChunkSize,
a61af66fc99e Initial load
duke
parents:
diff changeset
1662 "Size of chunks in the list is too small");
a61af66fc99e Initial load
duke
parents:
diff changeset
1663
a61af66fc99e Initial load
duke
parents:
diff changeset
1664 fl->removeChunk(curr);
a61af66fc99e Initial load
duke
parents:
diff changeset
1665 // recorded indirectly by splitChunkAndReturnRemainder -
a61af66fc99e Initial load
duke
parents:
diff changeset
1666 // smallSplit(oldNumWords, numWords);
a61af66fc99e Initial load
duke
parents:
diff changeset
1667 FreeChunk* new_chunk = splitChunkAndReturnRemainder(curr, numWords);
a61af66fc99e Initial load
duke
parents:
diff changeset
1668 // Does anything have to be done for the remainder in terms of
a61af66fc99e Initial load
duke
parents:
diff changeset
1669 // fixing the card table?
a61af66fc99e Initial load
duke
parents:
diff changeset
1670 assert(new_chunk == NULL || new_chunk->isFree(),
a61af66fc99e Initial load
duke
parents:
diff changeset
1671 "Should be returning a free chunk");
a61af66fc99e Initial load
duke
parents:
diff changeset
1672 return new_chunk;
a61af66fc99e Initial load
duke
parents:
diff changeset
1673 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1674
a61af66fc99e Initial load
duke
parents:
diff changeset
1675 FreeChunk*
a61af66fc99e Initial load
duke
parents:
diff changeset
1676 CompactibleFreeListSpace::splitChunkAndReturnRemainder(FreeChunk* chunk,
a61af66fc99e Initial load
duke
parents:
diff changeset
1677 size_t new_size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1678 assert_locked();
a61af66fc99e Initial load
duke
parents:
diff changeset
1679 size_t size = chunk->size();
a61af66fc99e Initial load
duke
parents:
diff changeset
1680 assert(size > new_size, "Split from a smaller block?");
a61af66fc99e Initial load
duke
parents:
diff changeset
1681 assert(is_aligned(chunk), "alignment problem");
a61af66fc99e Initial load
duke
parents:
diff changeset
1682 assert(size == adjustObjectSize(size), "alignment problem");
a61af66fc99e Initial load
duke
parents:
diff changeset
1683 size_t rem_size = size - new_size;
a61af66fc99e Initial load
duke
parents:
diff changeset
1684 assert(rem_size == adjustObjectSize(rem_size), "alignment problem");
a61af66fc99e Initial load
duke
parents:
diff changeset
1685 assert(rem_size >= MinChunkSize, "Free chunk smaller than minimum");
a61af66fc99e Initial load
duke
parents:
diff changeset
1686 FreeChunk* ffc = (FreeChunk*)((HeapWord*)chunk + new_size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1687 assert(is_aligned(ffc), "alignment problem");
a61af66fc99e Initial load
duke
parents:
diff changeset
1688 ffc->setSize(rem_size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1689 ffc->linkNext(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
1690 ffc->linkPrev(NULL); // Mark as a free block for other (parallel) GC threads.
a61af66fc99e Initial load
duke
parents:
diff changeset
1691 // Above must occur before BOT is updated below.
a61af66fc99e Initial load
duke
parents:
diff changeset
1692 // adjust block offset table
a61af66fc99e Initial load
duke
parents:
diff changeset
1693 _bt.split_block((HeapWord*)chunk, chunk->size(), new_size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1694 if (rem_size < SmallForDictionary) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1695 bool is_par = (SharedHeap::heap()->n_par_threads() > 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1696 if (is_par) _indexedFreeListParLocks[rem_size]->lock();
a61af66fc99e Initial load
duke
parents:
diff changeset
1697 returnChunkToFreeList(ffc);
a61af66fc99e Initial load
duke
parents:
diff changeset
1698 split(size, rem_size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1699 if (is_par) _indexedFreeListParLocks[rem_size]->unlock();
a61af66fc99e Initial load
duke
parents:
diff changeset
1700 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1701 returnChunkToDictionary(ffc);
a61af66fc99e Initial load
duke
parents:
diff changeset
1702 split(size ,rem_size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1703 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1704 chunk->setSize(new_size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1705 return chunk;
a61af66fc99e Initial load
duke
parents:
diff changeset
1706 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1707
a61af66fc99e Initial load
duke
parents:
diff changeset
1708 void
a61af66fc99e Initial load
duke
parents:
diff changeset
1709 CompactibleFreeListSpace::sweep_completed() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1710 // Now that space is probably plentiful, refill linear
a61af66fc99e Initial load
duke
parents:
diff changeset
1711 // allocation blocks as needed.
a61af66fc99e Initial load
duke
parents:
diff changeset
1712 refillLinearAllocBlocksIfNeeded();
a61af66fc99e Initial load
duke
parents:
diff changeset
1713 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1714
a61af66fc99e Initial load
duke
parents:
diff changeset
1715 void
a61af66fc99e Initial load
duke
parents:
diff changeset
1716 CompactibleFreeListSpace::gc_prologue() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1717 assert_locked();
a61af66fc99e Initial load
duke
parents:
diff changeset
1718 if (PrintFLSStatistics != 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1719 gclog_or_tty->print("Before GC:\n");
a61af66fc99e Initial load
duke
parents:
diff changeset
1720 reportFreeListStatistics();
a61af66fc99e Initial load
duke
parents:
diff changeset
1721 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1722 refillLinearAllocBlocksIfNeeded();
a61af66fc99e Initial load
duke
parents:
diff changeset
1723 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1724
a61af66fc99e Initial load
duke
parents:
diff changeset
1725 void
a61af66fc99e Initial load
duke
parents:
diff changeset
1726 CompactibleFreeListSpace::gc_epilogue() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1727 assert_locked();
a61af66fc99e Initial load
duke
parents:
diff changeset
1728 if (PrintGCDetails && Verbose && !_adaptive_freelists) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1729 if (_smallLinearAllocBlock._word_size == 0)
a61af66fc99e Initial load
duke
parents:
diff changeset
1730 warning("CompactibleFreeListSpace(epilogue):: Linear allocation failure");
a61af66fc99e Initial load
duke
parents:
diff changeset
1731 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1732 assert(_promoInfo.noPromotions(), "_promoInfo inconsistency");
a61af66fc99e Initial load
duke
parents:
diff changeset
1733 _promoInfo.stopTrackingPromotions();
a61af66fc99e Initial load
duke
parents:
diff changeset
1734 repairLinearAllocationBlocks();
a61af66fc99e Initial load
duke
parents:
diff changeset
1735 // Print Space's stats
a61af66fc99e Initial load
duke
parents:
diff changeset
1736 if (PrintFLSStatistics != 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1737 gclog_or_tty->print("After GC:\n");
a61af66fc99e Initial load
duke
parents:
diff changeset
1738 reportFreeListStatistics();
a61af66fc99e Initial load
duke
parents:
diff changeset
1739 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1740 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1741
a61af66fc99e Initial load
duke
parents:
diff changeset
1742 // Iteration support, mostly delegated from a CMS generation
a61af66fc99e Initial load
duke
parents:
diff changeset
1743
a61af66fc99e Initial load
duke
parents:
diff changeset
1744 void CompactibleFreeListSpace::save_marks() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1745 // mark the "end" of the used space at the time of this call;
a61af66fc99e Initial load
duke
parents:
diff changeset
1746 // note, however, that promoted objects from this point
a61af66fc99e Initial load
duke
parents:
diff changeset
1747 // on are tracked in the _promoInfo below.
a61af66fc99e Initial load
duke
parents:
diff changeset
1748 set_saved_mark_word(BlockOffsetArrayUseUnallocatedBlock ?
a61af66fc99e Initial load
duke
parents:
diff changeset
1749 unallocated_block() : end());
a61af66fc99e Initial load
duke
parents:
diff changeset
1750 // inform allocator that promotions should be tracked.
a61af66fc99e Initial load
duke
parents:
diff changeset
1751 assert(_promoInfo.noPromotions(), "_promoInfo inconsistency");
a61af66fc99e Initial load
duke
parents:
diff changeset
1752 _promoInfo.startTrackingPromotions();
a61af66fc99e Initial load
duke
parents:
diff changeset
1753 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1754
a61af66fc99e Initial load
duke
parents:
diff changeset
1755 bool CompactibleFreeListSpace::no_allocs_since_save_marks() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1756 assert(_promoInfo.tracking(), "No preceding save_marks?");
a61af66fc99e Initial load
duke
parents:
diff changeset
1757 guarantee(SharedHeap::heap()->n_par_threads() == 0,
a61af66fc99e Initial load
duke
parents:
diff changeset
1758 "Shouldn't be called (yet) during parallel part of gc.");
a61af66fc99e Initial load
duke
parents:
diff changeset
1759 return _promoInfo.noPromotions();
a61af66fc99e Initial load
duke
parents:
diff changeset
1760 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1761
a61af66fc99e Initial load
duke
parents:
diff changeset
1762 #define CFLS_OOP_SINCE_SAVE_MARKS_DEFN(OopClosureType, nv_suffix) \
a61af66fc99e Initial load
duke
parents:
diff changeset
1763 \
a61af66fc99e Initial load
duke
parents:
diff changeset
1764 void CompactibleFreeListSpace:: \
a61af66fc99e Initial load
duke
parents:
diff changeset
1765 oop_since_save_marks_iterate##nv_suffix(OopClosureType* blk) { \
a61af66fc99e Initial load
duke
parents:
diff changeset
1766 assert(SharedHeap::heap()->n_par_threads() == 0, \
a61af66fc99e Initial load
duke
parents:
diff changeset
1767 "Shouldn't be called (yet) during parallel part of gc."); \
a61af66fc99e Initial load
duke
parents:
diff changeset
1768 _promoInfo.promoted_oops_iterate##nv_suffix(blk); \
a61af66fc99e Initial load
duke
parents:
diff changeset
1769 /* \
a61af66fc99e Initial load
duke
parents:
diff changeset
1770 * This also restores any displaced headers and removes the elements from \
a61af66fc99e Initial load
duke
parents:
diff changeset
1771 * the iteration set as they are processed, so that we have a clean slate \
a61af66fc99e Initial load
duke
parents:
diff changeset
1772 * at the end of the iteration. Note, thus, that if new objects are \
a61af66fc99e Initial load
duke
parents:
diff changeset
1773 * promoted as a result of the iteration they are iterated over as well. \
a61af66fc99e Initial load
duke
parents:
diff changeset
1774 */ \
a61af66fc99e Initial load
duke
parents:
diff changeset
1775 assert(_promoInfo.noPromotions(), "_promoInfo inconsistency"); \
a61af66fc99e Initial load
duke
parents:
diff changeset
1776 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1777
a61af66fc99e Initial load
duke
parents:
diff changeset
1778 ALL_SINCE_SAVE_MARKS_CLOSURES(CFLS_OOP_SINCE_SAVE_MARKS_DEFN)
a61af66fc99e Initial load
duke
parents:
diff changeset
1779
a61af66fc99e Initial load
duke
parents:
diff changeset
1780 //////////////////////////////////////////////////////////////////////////////
a61af66fc99e Initial load
duke
parents:
diff changeset
1781 // We go over the list of promoted objects, removing each from the list,
a61af66fc99e Initial load
duke
parents:
diff changeset
1782 // and applying the closure (this may, in turn, add more elements to
a61af66fc99e Initial load
duke
parents:
diff changeset
1783 // the tail of the promoted list, and these newly added objects will
a61af66fc99e Initial load
duke
parents:
diff changeset
1784 // also be processed) until the list is empty.
a61af66fc99e Initial load
duke
parents:
diff changeset
1785 // To aid verification and debugging, in the non-product builds
a61af66fc99e Initial load
duke
parents:
diff changeset
1786 // we actually forward _promoHead each time we process a promoted oop.
a61af66fc99e Initial load
duke
parents:
diff changeset
1787 // Note that this is not necessary in general (i.e. when we don't need to
a61af66fc99e Initial load
duke
parents:
diff changeset
1788 // call PromotionInfo::verify()) because oop_iterate can only add to the
a61af66fc99e Initial load
duke
parents:
diff changeset
1789 // end of _promoTail, and never needs to look at _promoHead.
a61af66fc99e Initial load
duke
parents:
diff changeset
1790
a61af66fc99e Initial load
duke
parents:
diff changeset
1791 #define PROMOTED_OOPS_ITERATE_DEFN(OopClosureType, nv_suffix) \
a61af66fc99e Initial load
duke
parents:
diff changeset
1792 \
a61af66fc99e Initial load
duke
parents:
diff changeset
1793 void PromotionInfo::promoted_oops_iterate##nv_suffix(OopClosureType* cl) { \
a61af66fc99e Initial load
duke
parents:
diff changeset
1794 NOT_PRODUCT(verify()); \
a61af66fc99e Initial load
duke
parents:
diff changeset
1795 PromotedObject *curObj, *nextObj; \
a61af66fc99e Initial load
duke
parents:
diff changeset
1796 for (curObj = _promoHead; curObj != NULL; curObj = nextObj) { \
a61af66fc99e Initial load
duke
parents:
diff changeset
1797 if ((nextObj = curObj->next()) == NULL) { \
a61af66fc99e Initial load
duke
parents:
diff changeset
1798 /* protect ourselves against additions due to closure application \
a61af66fc99e Initial load
duke
parents:
diff changeset
1799 below by resetting the list. */ \
a61af66fc99e Initial load
duke
parents:
diff changeset
1800 assert(_promoTail == curObj, "Should have been the tail"); \
a61af66fc99e Initial load
duke
parents:
diff changeset
1801 _promoHead = _promoTail = NULL; \
a61af66fc99e Initial load
duke
parents:
diff changeset
1802 } \
a61af66fc99e Initial load
duke
parents:
diff changeset
1803 if (curObj->hasDisplacedMark()) { \
a61af66fc99e Initial load
duke
parents:
diff changeset
1804 /* restore displaced header */ \
a61af66fc99e Initial load
duke
parents:
diff changeset
1805 oop(curObj)->set_mark(nextDisplacedHeader()); \
a61af66fc99e Initial load
duke
parents:
diff changeset
1806 } else { \
a61af66fc99e Initial load
duke
parents:
diff changeset
1807 /* restore prototypical header */ \
a61af66fc99e Initial load
duke
parents:
diff changeset
1808 oop(curObj)->init_mark(); \
a61af66fc99e Initial load
duke
parents:
diff changeset
1809 } \
a61af66fc99e Initial load
duke
parents:
diff changeset
1810 /* The "promoted_mark" should now not be set */ \
a61af66fc99e Initial load
duke
parents:
diff changeset
1811 assert(!curObj->hasPromotedMark(), \
a61af66fc99e Initial load
duke
parents:
diff changeset
1812 "Should have been cleared by restoring displaced mark-word"); \
a61af66fc99e Initial load
duke
parents:
diff changeset
1813 NOT_PRODUCT(_promoHead = nextObj); \
a61af66fc99e Initial load
duke
parents:
diff changeset
1814 if (cl != NULL) oop(curObj)->oop_iterate(cl); \
a61af66fc99e Initial load
duke
parents:
diff changeset
1815 if (nextObj == NULL) { /* start at head of list reset above */ \
a61af66fc99e Initial load
duke
parents:
diff changeset
1816 nextObj = _promoHead; \
a61af66fc99e Initial load
duke
parents:
diff changeset
1817 } \
a61af66fc99e Initial load
duke
parents:
diff changeset
1818 } \
a61af66fc99e Initial load
duke
parents:
diff changeset
1819 assert(noPromotions(), "post-condition violation"); \
a61af66fc99e Initial load
duke
parents:
diff changeset
1820 assert(_promoHead == NULL && _promoTail == NULL, "emptied promoted list");\
a61af66fc99e Initial load
duke
parents:
diff changeset
1821 assert(_spoolHead == _spoolTail, "emptied spooling buffers"); \
a61af66fc99e Initial load
duke
parents:
diff changeset
1822 assert(_firstIndex == _nextIndex, "empty buffer"); \
a61af66fc99e Initial load
duke
parents:
diff changeset
1823 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1824
a61af66fc99e Initial load
duke
parents:
diff changeset
1825 // This should have been ALL_SINCE_...() just like the others,
a61af66fc99e Initial load
duke
parents:
diff changeset
1826 // but, because the body of the method above is somehwat longer,
a61af66fc99e Initial load
duke
parents:
diff changeset
1827 // the MSVC compiler cannot cope; as a workaround, we split the
a61af66fc99e Initial load
duke
parents:
diff changeset
1828 // macro into its 3 constituent parts below (see original macro
a61af66fc99e Initial load
duke
parents:
diff changeset
1829 // definition in specializedOopClosures.hpp).
a61af66fc99e Initial load
duke
parents:
diff changeset
1830 SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES_YOUNG(PROMOTED_OOPS_ITERATE_DEFN)
a61af66fc99e Initial load
duke
parents:
diff changeset
1831 PROMOTED_OOPS_ITERATE_DEFN(OopsInGenClosure,_v)
a61af66fc99e Initial load
duke
parents:
diff changeset
1832
a61af66fc99e Initial load
duke
parents:
diff changeset
1833
a61af66fc99e Initial load
duke
parents:
diff changeset
1834 void CompactibleFreeListSpace::object_iterate_since_last_GC(ObjectClosure* cl) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1835 // ugghh... how would one do this efficiently for a non-contiguous space?
a61af66fc99e Initial load
duke
parents:
diff changeset
1836 guarantee(false, "NYI");
a61af66fc99e Initial load
duke
parents:
diff changeset
1837 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1838
12
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
1839 bool CompactibleFreeListSpace::linearAllocationWouldFail() const {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1840 return _smallLinearAllocBlock._word_size == 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1841 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1842
a61af66fc99e Initial load
duke
parents:
diff changeset
1843 void CompactibleFreeListSpace::repairLinearAllocationBlocks() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1844 // Fix up linear allocation blocks to look like free blocks
a61af66fc99e Initial load
duke
parents:
diff changeset
1845 repairLinearAllocBlock(&_smallLinearAllocBlock);
a61af66fc99e Initial load
duke
parents:
diff changeset
1846 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1847
a61af66fc99e Initial load
duke
parents:
diff changeset
1848 void CompactibleFreeListSpace::repairLinearAllocBlock(LinearAllocBlock* blk) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1849 assert_locked();
a61af66fc99e Initial load
duke
parents:
diff changeset
1850 if (blk->_ptr != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1851 assert(blk->_word_size != 0 && blk->_word_size >= MinChunkSize,
a61af66fc99e Initial load
duke
parents:
diff changeset
1852 "Minimum block size requirement");
a61af66fc99e Initial load
duke
parents:
diff changeset
1853 FreeChunk* fc = (FreeChunk*)(blk->_ptr);
a61af66fc99e Initial load
duke
parents:
diff changeset
1854 fc->setSize(blk->_word_size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1855 fc->linkPrev(NULL); // mark as free
a61af66fc99e Initial load
duke
parents:
diff changeset
1856 fc->dontCoalesce();
a61af66fc99e Initial load
duke
parents:
diff changeset
1857 assert(fc->isFree(), "just marked it free");
a61af66fc99e Initial load
duke
parents:
diff changeset
1858 assert(fc->cantCoalesce(), "just marked it uncoalescable");
a61af66fc99e Initial load
duke
parents:
diff changeset
1859 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1860 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1861
a61af66fc99e Initial load
duke
parents:
diff changeset
1862 void CompactibleFreeListSpace::refillLinearAllocBlocksIfNeeded() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1863 assert_locked();
a61af66fc99e Initial load
duke
parents:
diff changeset
1864 if (_smallLinearAllocBlock._ptr == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1865 assert(_smallLinearAllocBlock._word_size == 0,
a61af66fc99e Initial load
duke
parents:
diff changeset
1866 "Size of linAB should be zero if the ptr is NULL");
a61af66fc99e Initial load
duke
parents:
diff changeset
1867 // Reset the linAB refill and allocation size limit.
a61af66fc99e Initial load
duke
parents:
diff changeset
1868 _smallLinearAllocBlock.set(0, 0, 1024*SmallForLinearAlloc, SmallForLinearAlloc);
a61af66fc99e Initial load
duke
parents:
diff changeset
1869 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1870 refillLinearAllocBlockIfNeeded(&_smallLinearAllocBlock);
a61af66fc99e Initial load
duke
parents:
diff changeset
1871 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1872
a61af66fc99e Initial load
duke
parents:
diff changeset
1873 void
a61af66fc99e Initial load
duke
parents:
diff changeset
1874 CompactibleFreeListSpace::refillLinearAllocBlockIfNeeded(LinearAllocBlock* blk) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1875 assert_locked();
a61af66fc99e Initial load
duke
parents:
diff changeset
1876 assert((blk->_ptr == NULL && blk->_word_size == 0) ||
a61af66fc99e Initial load
duke
parents:
diff changeset
1877 (blk->_ptr != NULL && blk->_word_size >= MinChunkSize),
a61af66fc99e Initial load
duke
parents:
diff changeset
1878 "blk invariant");
a61af66fc99e Initial load
duke
parents:
diff changeset
1879 if (blk->_ptr == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1880 refillLinearAllocBlock(blk);
a61af66fc99e Initial load
duke
parents:
diff changeset
1881 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1882 if (PrintMiscellaneous && Verbose) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1883 if (blk->_word_size == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1884 warning("CompactibleFreeListSpace(prologue):: Linear allocation failure");
a61af66fc99e Initial load
duke
parents:
diff changeset
1885 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1886 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1887 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1888
a61af66fc99e Initial load
duke
parents:
diff changeset
1889 void
a61af66fc99e Initial load
duke
parents:
diff changeset
1890 CompactibleFreeListSpace::refillLinearAllocBlock(LinearAllocBlock* blk) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1891 assert_locked();
a61af66fc99e Initial load
duke
parents:
diff changeset
1892 assert(blk->_word_size == 0 && blk->_ptr == NULL,
a61af66fc99e Initial load
duke
parents:
diff changeset
1893 "linear allocation block should be empty");
a61af66fc99e Initial load
duke
parents:
diff changeset
1894 FreeChunk* fc;
a61af66fc99e Initial load
duke
parents:
diff changeset
1895 if (blk->_refillSize < SmallForDictionary &&
a61af66fc99e Initial load
duke
parents:
diff changeset
1896 (fc = getChunkFromIndexedFreeList(blk->_refillSize)) != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1897 // A linAB's strategy might be to use small sizes to reduce
a61af66fc99e Initial load
duke
parents:
diff changeset
1898 // fragmentation but still get the benefits of allocation from a
a61af66fc99e Initial load
duke
parents:
diff changeset
1899 // linAB.
a61af66fc99e Initial load
duke
parents:
diff changeset
1900 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1901 fc = getChunkFromDictionary(blk->_refillSize);
a61af66fc99e Initial load
duke
parents:
diff changeset
1902 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1903 if (fc != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1904 blk->_ptr = (HeapWord*)fc;
a61af66fc99e Initial load
duke
parents:
diff changeset
1905 blk->_word_size = fc->size();
a61af66fc99e Initial load
duke
parents:
diff changeset
1906 fc->dontCoalesce(); // to prevent sweeper from sweeping us up
a61af66fc99e Initial load
duke
parents:
diff changeset
1907 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1908 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1909
12
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
1910 // Support for concurrent collection policy decisions.
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
1911 bool CompactibleFreeListSpace::should_concurrent_collect() const {
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
1912 // In the future we might want to add in frgamentation stats --
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
1913 // including erosion of the "mountain" into this decision as well.
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
1914 return !adaptive_freelists() && linearAllocationWouldFail();
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
1915 }
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
1916
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1917 // Support for compaction
a61af66fc99e Initial load
duke
parents:
diff changeset
1918
a61af66fc99e Initial load
duke
parents:
diff changeset
1919 void CompactibleFreeListSpace::prepare_for_compaction(CompactPoint* cp) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1920 SCAN_AND_FORWARD(cp,end,block_is_obj,block_size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1921 // prepare_for_compaction() uses the space between live objects
a61af66fc99e Initial load
duke
parents:
diff changeset
1922 // so that later phase can skip dead space quickly. So verification
a61af66fc99e Initial load
duke
parents:
diff changeset
1923 // of the free lists doesn't work after.
a61af66fc99e Initial load
duke
parents:
diff changeset
1924 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1925
a61af66fc99e Initial load
duke
parents:
diff changeset
1926 #define obj_size(q) adjustObjectSize(oop(q)->size())
a61af66fc99e Initial load
duke
parents:
diff changeset
1927 #define adjust_obj_size(s) adjustObjectSize(s)
a61af66fc99e Initial load
duke
parents:
diff changeset
1928
a61af66fc99e Initial load
duke
parents:
diff changeset
1929 void CompactibleFreeListSpace::adjust_pointers() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1930 // In other versions of adjust_pointers(), a bail out
a61af66fc99e Initial load
duke
parents:
diff changeset
1931 // based on the amount of live data in the generation
a61af66fc99e Initial load
duke
parents:
diff changeset
1932 // (i.e., if 0, bail out) may be used.
a61af66fc99e Initial load
duke
parents:
diff changeset
1933 // Cannot test used() == 0 here because the free lists have already
a61af66fc99e Initial load
duke
parents:
diff changeset
1934 // been mangled by the compaction.
a61af66fc99e Initial load
duke
parents:
diff changeset
1935
a61af66fc99e Initial load
duke
parents:
diff changeset
1936 SCAN_AND_ADJUST_POINTERS(adjust_obj_size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1937 // See note about verification in prepare_for_compaction().
a61af66fc99e Initial load
duke
parents:
diff changeset
1938 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1939
a61af66fc99e Initial load
duke
parents:
diff changeset
1940 void CompactibleFreeListSpace::compact() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1941 SCAN_AND_COMPACT(obj_size);
a61af66fc99e Initial load
duke
parents:
diff changeset
1942 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1943
a61af66fc99e Initial load
duke
parents:
diff changeset
1944 // fragmentation_metric = 1 - [sum of (fbs**2) / (sum of fbs)**2]
a61af66fc99e Initial load
duke
parents:
diff changeset
1945 // where fbs is free block sizes
a61af66fc99e Initial load
duke
parents:
diff changeset
1946 double CompactibleFreeListSpace::flsFrag() const {
a61af66fc99e Initial load
duke
parents:
diff changeset
1947 size_t itabFree = totalSizeInIndexedFreeLists();
a61af66fc99e Initial load
duke
parents:
diff changeset
1948 double frag = 0.0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1949 size_t i;
a61af66fc99e Initial load
duke
parents:
diff changeset
1950
a61af66fc99e Initial load
duke
parents:
diff changeset
1951 for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1952 double sz = i;
a61af66fc99e Initial load
duke
parents:
diff changeset
1953 frag += _indexedFreeList[i].count() * (sz * sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
1954 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1955
a61af66fc99e Initial load
duke
parents:
diff changeset
1956 double totFree = itabFree +
a61af66fc99e Initial load
duke
parents:
diff changeset
1957 _dictionary->totalChunkSize(DEBUG_ONLY(freelistLock()));
a61af66fc99e Initial load
duke
parents:
diff changeset
1958 if (totFree > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1959 frag = ((frag + _dictionary->sum_of_squared_block_sizes()) /
a61af66fc99e Initial load
duke
parents:
diff changeset
1960 (totFree * totFree));
a61af66fc99e Initial load
duke
parents:
diff changeset
1961 frag = (double)1.0 - frag;
a61af66fc99e Initial load
duke
parents:
diff changeset
1962 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1963 assert(frag == 0.0, "Follows from totFree == 0");
a61af66fc99e Initial load
duke
parents:
diff changeset
1964 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1965 return frag;
a61af66fc99e Initial load
duke
parents:
diff changeset
1966 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1967
a61af66fc99e Initial load
duke
parents:
diff changeset
1968 #define CoalSurplusPercent 1.05
a61af66fc99e Initial load
duke
parents:
diff changeset
1969 #define SplitSurplusPercent 1.10
a61af66fc99e Initial load
duke
parents:
diff changeset
1970
a61af66fc99e Initial load
duke
parents:
diff changeset
1971 void CompactibleFreeListSpace::beginSweepFLCensus(
a61af66fc99e Initial load
duke
parents:
diff changeset
1972 float inter_sweep_current,
a61af66fc99e Initial load
duke
parents:
diff changeset
1973 float inter_sweep_estimate) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1974 assert_locked();
a61af66fc99e Initial load
duke
parents:
diff changeset
1975 size_t i;
a61af66fc99e Initial load
duke
parents:
diff changeset
1976 for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1977 FreeList* fl = &_indexedFreeList[i];
a61af66fc99e Initial load
duke
parents:
diff changeset
1978 fl->compute_desired(inter_sweep_current, inter_sweep_estimate);
a61af66fc99e Initial load
duke
parents:
diff changeset
1979 fl->set_coalDesired((ssize_t)((double)fl->desired() * CoalSurplusPercent));
a61af66fc99e Initial load
duke
parents:
diff changeset
1980 fl->set_beforeSweep(fl->count());
a61af66fc99e Initial load
duke
parents:
diff changeset
1981 fl->set_bfrSurp(fl->surplus());
a61af66fc99e Initial load
duke
parents:
diff changeset
1982 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1983 _dictionary->beginSweepDictCensus(CoalSurplusPercent,
a61af66fc99e Initial load
duke
parents:
diff changeset
1984 inter_sweep_current,
a61af66fc99e Initial load
duke
parents:
diff changeset
1985 inter_sweep_estimate);
a61af66fc99e Initial load
duke
parents:
diff changeset
1986 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1987
a61af66fc99e Initial load
duke
parents:
diff changeset
1988 void CompactibleFreeListSpace::setFLSurplus() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1989 assert_locked();
a61af66fc99e Initial load
duke
parents:
diff changeset
1990 size_t i;
a61af66fc99e Initial load
duke
parents:
diff changeset
1991 for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1992 FreeList *fl = &_indexedFreeList[i];
a61af66fc99e Initial load
duke
parents:
diff changeset
1993 fl->set_surplus(fl->count() -
a61af66fc99e Initial load
duke
parents:
diff changeset
1994 (ssize_t)((double)fl->desired() * SplitSurplusPercent));
a61af66fc99e Initial load
duke
parents:
diff changeset
1995 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1996 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1997
a61af66fc99e Initial load
duke
parents:
diff changeset
1998 void CompactibleFreeListSpace::setFLHints() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1999 assert_locked();
a61af66fc99e Initial load
duke
parents:
diff changeset
2000 size_t i;
a61af66fc99e Initial load
duke
parents:
diff changeset
2001 size_t h = IndexSetSize;
a61af66fc99e Initial load
duke
parents:
diff changeset
2002 for (i = IndexSetSize - 1; i != 0; i -= IndexSetStride) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2003 FreeList *fl = &_indexedFreeList[i];
a61af66fc99e Initial load
duke
parents:
diff changeset
2004 fl->set_hint(h);
a61af66fc99e Initial load
duke
parents:
diff changeset
2005 if (fl->surplus() > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2006 h = i;
a61af66fc99e Initial load
duke
parents:
diff changeset
2007 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2008 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2009 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2010
a61af66fc99e Initial load
duke
parents:
diff changeset
2011 void CompactibleFreeListSpace::clearFLCensus() {
a61af66fc99e Initial load
duke
parents:
diff changeset
2012 assert_locked();
a61af66fc99e Initial load
duke
parents:
diff changeset
2013 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
2014 for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2015 FreeList *fl = &_indexedFreeList[i];
a61af66fc99e Initial load
duke
parents:
diff changeset
2016 fl->set_prevSweep(fl->count());
a61af66fc99e Initial load
duke
parents:
diff changeset
2017 fl->set_coalBirths(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
2018 fl->set_coalDeaths(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
2019 fl->set_splitBirths(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
2020 fl->set_splitDeaths(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
2021 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2022 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2023
12
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
2024 void CompactibleFreeListSpace::endSweepFLCensus(size_t sweep_count) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2025 setFLSurplus();
a61af66fc99e Initial load
duke
parents:
diff changeset
2026 setFLHints();
a61af66fc99e Initial load
duke
parents:
diff changeset
2027 if (PrintGC && PrintFLSCensus > 0) {
12
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
2028 printFLCensus(sweep_count);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2029 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2030 clearFLCensus();
a61af66fc99e Initial load
duke
parents:
diff changeset
2031 assert_locked();
a61af66fc99e Initial load
duke
parents:
diff changeset
2032 _dictionary->endSweepDictCensus(SplitSurplusPercent);
a61af66fc99e Initial load
duke
parents:
diff changeset
2033 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2034
a61af66fc99e Initial load
duke
parents:
diff changeset
2035 bool CompactibleFreeListSpace::coalOverPopulated(size_t size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2036 if (size < SmallForDictionary) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2037 FreeList *fl = &_indexedFreeList[size];
a61af66fc99e Initial load
duke
parents:
diff changeset
2038 return (fl->coalDesired() < 0) ||
a61af66fc99e Initial load
duke
parents:
diff changeset
2039 ((int)fl->count() > fl->coalDesired());
a61af66fc99e Initial load
duke
parents:
diff changeset
2040 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2041 return dictionary()->coalDictOverPopulated(size);
a61af66fc99e Initial load
duke
parents:
diff changeset
2042 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2043 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2044
a61af66fc99e Initial load
duke
parents:
diff changeset
2045 void CompactibleFreeListSpace::smallCoalBirth(size_t size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2046 assert(size < SmallForDictionary, "Size too large for indexed list");
a61af66fc99e Initial load
duke
parents:
diff changeset
2047 FreeList *fl = &_indexedFreeList[size];
a61af66fc99e Initial load
duke
parents:
diff changeset
2048 fl->increment_coalBirths();
a61af66fc99e Initial load
duke
parents:
diff changeset
2049 fl->increment_surplus();
a61af66fc99e Initial load
duke
parents:
diff changeset
2050 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2051
a61af66fc99e Initial load
duke
parents:
diff changeset
2052 void CompactibleFreeListSpace::smallCoalDeath(size_t size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2053 assert(size < SmallForDictionary, "Size too large for indexed list");
a61af66fc99e Initial load
duke
parents:
diff changeset
2054 FreeList *fl = &_indexedFreeList[size];
a61af66fc99e Initial load
duke
parents:
diff changeset
2055 fl->increment_coalDeaths();
a61af66fc99e Initial load
duke
parents:
diff changeset
2056 fl->decrement_surplus();
a61af66fc99e Initial load
duke
parents:
diff changeset
2057 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2058
a61af66fc99e Initial load
duke
parents:
diff changeset
2059 void CompactibleFreeListSpace::coalBirth(size_t size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2060 if (size < SmallForDictionary) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2061 smallCoalBirth(size);
a61af66fc99e Initial load
duke
parents:
diff changeset
2062 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2063 dictionary()->dictCensusUpdate(size,
a61af66fc99e Initial load
duke
parents:
diff changeset
2064 false /* split */,
a61af66fc99e Initial load
duke
parents:
diff changeset
2065 true /* birth */);
a61af66fc99e Initial load
duke
parents:
diff changeset
2066 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2067 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2068
a61af66fc99e Initial load
duke
parents:
diff changeset
2069 void CompactibleFreeListSpace::coalDeath(size_t size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2070 if(size < SmallForDictionary) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2071 smallCoalDeath(size);
a61af66fc99e Initial load
duke
parents:
diff changeset
2072 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2073 dictionary()->dictCensusUpdate(size,
a61af66fc99e Initial load
duke
parents:
diff changeset
2074 false /* split */,
a61af66fc99e Initial load
duke
parents:
diff changeset
2075 false /* birth */);
a61af66fc99e Initial load
duke
parents:
diff changeset
2076 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2077 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2078
a61af66fc99e Initial load
duke
parents:
diff changeset
2079 void CompactibleFreeListSpace::smallSplitBirth(size_t size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2080 assert(size < SmallForDictionary, "Size too large for indexed list");
a61af66fc99e Initial load
duke
parents:
diff changeset
2081 FreeList *fl = &_indexedFreeList[size];
a61af66fc99e Initial load
duke
parents:
diff changeset
2082 fl->increment_splitBirths();
a61af66fc99e Initial load
duke
parents:
diff changeset
2083 fl->increment_surplus();
a61af66fc99e Initial load
duke
parents:
diff changeset
2084 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2085
a61af66fc99e Initial load
duke
parents:
diff changeset
2086 void CompactibleFreeListSpace::smallSplitDeath(size_t size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2087 assert(size < SmallForDictionary, "Size too large for indexed list");
a61af66fc99e Initial load
duke
parents:
diff changeset
2088 FreeList *fl = &_indexedFreeList[size];
a61af66fc99e Initial load
duke
parents:
diff changeset
2089 fl->increment_splitDeaths();
a61af66fc99e Initial load
duke
parents:
diff changeset
2090 fl->decrement_surplus();
a61af66fc99e Initial load
duke
parents:
diff changeset
2091 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2092
a61af66fc99e Initial load
duke
parents:
diff changeset
2093 void CompactibleFreeListSpace::splitBirth(size_t size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2094 if (size < SmallForDictionary) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2095 smallSplitBirth(size);
a61af66fc99e Initial load
duke
parents:
diff changeset
2096 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2097 dictionary()->dictCensusUpdate(size,
a61af66fc99e Initial load
duke
parents:
diff changeset
2098 true /* split */,
a61af66fc99e Initial load
duke
parents:
diff changeset
2099 true /* birth */);
a61af66fc99e Initial load
duke
parents:
diff changeset
2100 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2101 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2102
a61af66fc99e Initial load
duke
parents:
diff changeset
2103 void CompactibleFreeListSpace::splitDeath(size_t size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2104 if (size < SmallForDictionary) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2105 smallSplitDeath(size);
a61af66fc99e Initial load
duke
parents:
diff changeset
2106 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2107 dictionary()->dictCensusUpdate(size,
a61af66fc99e Initial load
duke
parents:
diff changeset
2108 true /* split */,
a61af66fc99e Initial load
duke
parents:
diff changeset
2109 false /* birth */);
a61af66fc99e Initial load
duke
parents:
diff changeset
2110 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2111 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2112
a61af66fc99e Initial load
duke
parents:
diff changeset
2113 void CompactibleFreeListSpace::split(size_t from, size_t to1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2114 size_t to2 = from - to1;
a61af66fc99e Initial load
duke
parents:
diff changeset
2115 splitDeath(from);
a61af66fc99e Initial load
duke
parents:
diff changeset
2116 splitBirth(to1);
a61af66fc99e Initial load
duke
parents:
diff changeset
2117 splitBirth(to2);
a61af66fc99e Initial load
duke
parents:
diff changeset
2118 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2119
a61af66fc99e Initial load
duke
parents:
diff changeset
2120 void CompactibleFreeListSpace::print() const {
a61af66fc99e Initial load
duke
parents:
diff changeset
2121 tty->print(" CompactibleFreeListSpace");
a61af66fc99e Initial load
duke
parents:
diff changeset
2122 Space::print();
a61af66fc99e Initial load
duke
parents:
diff changeset
2123 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2124
a61af66fc99e Initial load
duke
parents:
diff changeset
2125 void CompactibleFreeListSpace::prepare_for_verify() {
a61af66fc99e Initial load
duke
parents:
diff changeset
2126 assert_locked();
a61af66fc99e Initial load
duke
parents:
diff changeset
2127 repairLinearAllocationBlocks();
a61af66fc99e Initial load
duke
parents:
diff changeset
2128 // Verify that the SpoolBlocks look like free blocks of
a61af66fc99e Initial load
duke
parents:
diff changeset
2129 // appropriate sizes... To be done ...
a61af66fc99e Initial load
duke
parents:
diff changeset
2130 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2131
a61af66fc99e Initial load
duke
parents:
diff changeset
2132 class VerifyAllBlksClosure: public BlkClosure {
113
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 12
diff changeset
2133 private:
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2134 const CompactibleFreeListSpace* _sp;
a61af66fc99e Initial load
duke
parents:
diff changeset
2135 const MemRegion _span;
a61af66fc99e Initial load
duke
parents:
diff changeset
2136
a61af66fc99e Initial load
duke
parents:
diff changeset
2137 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
2138 VerifyAllBlksClosure(const CompactibleFreeListSpace* sp,
a61af66fc99e Initial load
duke
parents:
diff changeset
2139 MemRegion span) : _sp(sp), _span(span) { }
a61af66fc99e Initial load
duke
parents:
diff changeset
2140
113
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 12
diff changeset
2141 virtual size_t do_blk(HeapWord* addr) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2142 size_t res;
a61af66fc99e Initial load
duke
parents:
diff changeset
2143 if (_sp->block_is_obj(addr)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2144 oop p = oop(addr);
a61af66fc99e Initial load
duke
parents:
diff changeset
2145 guarantee(p->is_oop(), "Should be an oop");
a61af66fc99e Initial load
duke
parents:
diff changeset
2146 res = _sp->adjustObjectSize(p->size());
a61af66fc99e Initial load
duke
parents:
diff changeset
2147 if (_sp->obj_is_alive(addr)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2148 p->verify();
a61af66fc99e Initial load
duke
parents:
diff changeset
2149 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2150 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2151 FreeChunk* fc = (FreeChunk*)addr;
a61af66fc99e Initial load
duke
parents:
diff changeset
2152 res = fc->size();
a61af66fc99e Initial load
duke
parents:
diff changeset
2153 if (FLSVerifyLists && !fc->cantCoalesce()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2154 guarantee(_sp->verifyChunkInFreeLists(fc),
a61af66fc99e Initial load
duke
parents:
diff changeset
2155 "Chunk should be on a free list");
a61af66fc99e Initial load
duke
parents:
diff changeset
2156 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2157 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2158 guarantee(res != 0, "Livelock: no rank reduction!");
a61af66fc99e Initial load
duke
parents:
diff changeset
2159 return res;
a61af66fc99e Initial load
duke
parents:
diff changeset
2160 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2161 };
a61af66fc99e Initial load
duke
parents:
diff changeset
2162
a61af66fc99e Initial load
duke
parents:
diff changeset
2163 class VerifyAllOopsClosure: public OopClosure {
113
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 12
diff changeset
2164 private:
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2165 const CMSCollector* _collector;
a61af66fc99e Initial load
duke
parents:
diff changeset
2166 const CompactibleFreeListSpace* _sp;
a61af66fc99e Initial load
duke
parents:
diff changeset
2167 const MemRegion _span;
a61af66fc99e Initial load
duke
parents:
diff changeset
2168 const bool _past_remark;
a61af66fc99e Initial load
duke
parents:
diff changeset
2169 const CMSBitMap* _bit_map;
a61af66fc99e Initial load
duke
parents:
diff changeset
2170
113
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 12
diff changeset
2171 protected:
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 12
diff changeset
2172 void do_oop(void* p, oop obj) {
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 12
diff changeset
2173 if (_span.contains(obj)) { // the interior oop points into CMS heap
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 12
diff changeset
2174 if (!_span.contains(p)) { // reference from outside CMS heap
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 12
diff changeset
2175 // Should be a valid object; the first disjunct below allows
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 12
diff changeset
2176 // us to sidestep an assertion in block_is_obj() that insists
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 12
diff changeset
2177 // that p be in _sp. Note that several generations (and spaces)
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 12
diff changeset
2178 // are spanned by _span (CMS heap) above.
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 12
diff changeset
2179 guarantee(!_sp->is_in_reserved(obj) ||
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 12
diff changeset
2180 _sp->block_is_obj((HeapWord*)obj),
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 12
diff changeset
2181 "Should be an object");
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 12
diff changeset
2182 guarantee(obj->is_oop(), "Should be an oop");
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 12
diff changeset
2183 obj->verify();
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 12
diff changeset
2184 if (_past_remark) {
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 12
diff changeset
2185 // Remark has been completed, the object should be marked
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 12
diff changeset
2186 _bit_map->isMarked((HeapWord*)obj);
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 12
diff changeset
2187 }
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 12
diff changeset
2188 } else { // reference within CMS heap
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 12
diff changeset
2189 if (_past_remark) {
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 12
diff changeset
2190 // Remark has been completed -- so the referent should have
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 12
diff changeset
2191 // been marked, if referring object is.
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 12
diff changeset
2192 if (_bit_map->isMarked(_collector->block_start(p))) {
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 12
diff changeset
2193 guarantee(_bit_map->isMarked((HeapWord*)obj), "Marking error?");
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 12
diff changeset
2194 }
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 12
diff changeset
2195 }
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 12
diff changeset
2196 }
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 12
diff changeset
2197 } else if (_sp->is_in_reserved(p)) {
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 12
diff changeset
2198 // the reference is from FLS, and points out of FLS
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 12
diff changeset
2199 guarantee(obj->is_oop(), "Should be an oop");
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 12
diff changeset
2200 obj->verify();
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 12
diff changeset
2201 }
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 12
diff changeset
2202 }
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 12
diff changeset
2203
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 12
diff changeset
2204 template <class T> void do_oop_work(T* p) {
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 12
diff changeset
2205 T heap_oop = oopDesc::load_heap_oop(p);
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 12
diff changeset
2206 if (!oopDesc::is_null(heap_oop)) {
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 12
diff changeset
2207 oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 12
diff changeset
2208 do_oop(p, obj);
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 12
diff changeset
2209 }
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 12
diff changeset
2210 }
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 12
diff changeset
2211
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2212 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
2213 VerifyAllOopsClosure(const CMSCollector* collector,
a61af66fc99e Initial load
duke
parents:
diff changeset
2214 const CompactibleFreeListSpace* sp, MemRegion span,
a61af66fc99e Initial load
duke
parents:
diff changeset
2215 bool past_remark, CMSBitMap* bit_map) :
a61af66fc99e Initial load
duke
parents:
diff changeset
2216 OopClosure(), _collector(collector), _sp(sp), _span(span),
a61af66fc99e Initial load
duke
parents:
diff changeset
2217 _past_remark(past_remark), _bit_map(bit_map) { }
a61af66fc99e Initial load
duke
parents:
diff changeset
2218
113
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 12
diff changeset
2219 virtual void do_oop(oop* p) { VerifyAllOopsClosure::do_oop_work(p); }
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 12
diff changeset
2220 virtual void do_oop(narrowOop* p) { VerifyAllOopsClosure::do_oop_work(p); }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2221 };
a61af66fc99e Initial load
duke
parents:
diff changeset
2222
a61af66fc99e Initial load
duke
parents:
diff changeset
2223 void CompactibleFreeListSpace::verify(bool ignored) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
2224 assert_lock_strong(&_freelistLock);
a61af66fc99e Initial load
duke
parents:
diff changeset
2225 verify_objects_initialized();
a61af66fc99e Initial load
duke
parents:
diff changeset
2226 MemRegion span = _collector->_span;
a61af66fc99e Initial load
duke
parents:
diff changeset
2227 bool past_remark = (_collector->abstract_state() ==
a61af66fc99e Initial load
duke
parents:
diff changeset
2228 CMSCollector::Sweeping);
a61af66fc99e Initial load
duke
parents:
diff changeset
2229
a61af66fc99e Initial load
duke
parents:
diff changeset
2230 ResourceMark rm;
a61af66fc99e Initial load
duke
parents:
diff changeset
2231 HandleMark hm;
a61af66fc99e Initial load
duke
parents:
diff changeset
2232
a61af66fc99e Initial load
duke
parents:
diff changeset
2233 // Check integrity of CFL data structures
a61af66fc99e Initial load
duke
parents:
diff changeset
2234 _promoInfo.verify();
a61af66fc99e Initial load
duke
parents:
diff changeset
2235 _dictionary->verify();
a61af66fc99e Initial load
duke
parents:
diff changeset
2236 if (FLSVerifyIndexTable) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2237 verifyIndexedFreeLists();
a61af66fc99e Initial load
duke
parents:
diff changeset
2238 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2239 // Check integrity of all objects and free blocks in space
a61af66fc99e Initial load
duke
parents:
diff changeset
2240 {
a61af66fc99e Initial load
duke
parents:
diff changeset
2241 VerifyAllBlksClosure cl(this, span);
a61af66fc99e Initial load
duke
parents:
diff changeset
2242 ((CompactibleFreeListSpace*)this)->blk_iterate(&cl); // cast off const
a61af66fc99e Initial load
duke
parents:
diff changeset
2243 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2244 // Check that all references in the heap to FLS
a61af66fc99e Initial load
duke
parents:
diff changeset
2245 // are to valid objects in FLS or that references in
a61af66fc99e Initial load
duke
parents:
diff changeset
2246 // FLS are to valid objects elsewhere in the heap
a61af66fc99e Initial load
duke
parents:
diff changeset
2247 if (FLSVerifyAllHeapReferences)
a61af66fc99e Initial load
duke
parents:
diff changeset
2248 {
a61af66fc99e Initial load
duke
parents:
diff changeset
2249 VerifyAllOopsClosure cl(_collector, this, span, past_remark,
a61af66fc99e Initial load
duke
parents:
diff changeset
2250 _collector->markBitMap());
a61af66fc99e Initial load
duke
parents:
diff changeset
2251 CollectedHeap* ch = Universe::heap();
a61af66fc99e Initial load
duke
parents:
diff changeset
2252 ch->oop_iterate(&cl); // all oops in generations
a61af66fc99e Initial load
duke
parents:
diff changeset
2253 ch->permanent_oop_iterate(&cl); // all oops in perm gen
a61af66fc99e Initial load
duke
parents:
diff changeset
2254 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2255
a61af66fc99e Initial load
duke
parents:
diff changeset
2256 if (VerifyObjectStartArray) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2257 // Verify the block offset table
a61af66fc99e Initial load
duke
parents:
diff changeset
2258 _bt.verify();
a61af66fc99e Initial load
duke
parents:
diff changeset
2259 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2260 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2261
a61af66fc99e Initial load
duke
parents:
diff changeset
2262 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
2263 void CompactibleFreeListSpace::verifyFreeLists() const {
a61af66fc99e Initial load
duke
parents:
diff changeset
2264 if (FLSVerifyLists) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2265 _dictionary->verify();
a61af66fc99e Initial load
duke
parents:
diff changeset
2266 verifyIndexedFreeLists();
a61af66fc99e Initial load
duke
parents:
diff changeset
2267 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2268 if (FLSVerifyDictionary) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2269 _dictionary->verify();
a61af66fc99e Initial load
duke
parents:
diff changeset
2270 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2271 if (FLSVerifyIndexTable) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2272 verifyIndexedFreeLists();
a61af66fc99e Initial load
duke
parents:
diff changeset
2273 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2274 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2275 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2276 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2277
a61af66fc99e Initial load
duke
parents:
diff changeset
2278 void CompactibleFreeListSpace::verifyIndexedFreeLists() const {
a61af66fc99e Initial load
duke
parents:
diff changeset
2279 size_t i = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
2280 for (; i < MinChunkSize; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2281 guarantee(_indexedFreeList[i].head() == NULL, "should be NULL");
a61af66fc99e Initial load
duke
parents:
diff changeset
2282 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2283 for (; i < IndexSetSize; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2284 verifyIndexedFreeList(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
2285 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2286 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2287
a61af66fc99e Initial load
duke
parents:
diff changeset
2288 void CompactibleFreeListSpace::verifyIndexedFreeList(size_t size) const {
342
37f87013dfd8 6711316: Open source the Garbage-First garbage collector
ysr
parents: 113
diff changeset
2289 FreeChunk* fc = _indexedFreeList[size].head();
37f87013dfd8 6711316: Open source the Garbage-First garbage collector
ysr
parents: 113
diff changeset
2290 guarantee((size % 2 == 0) || fc == NULL, "Odd slots should be empty");
37f87013dfd8 6711316: Open source the Garbage-First garbage collector
ysr
parents: 113
diff changeset
2291 for (; fc != NULL; fc = fc->next()) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2292 guarantee(fc->size() == size, "Size inconsistency");
a61af66fc99e Initial load
duke
parents:
diff changeset
2293 guarantee(fc->isFree(), "!free?");
a61af66fc99e Initial load
duke
parents:
diff changeset
2294 guarantee(fc->next() == NULL || fc->next()->prev() == fc, "Broken list");
a61af66fc99e Initial load
duke
parents:
diff changeset
2295 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2296 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2297
a61af66fc99e Initial load
duke
parents:
diff changeset
2298 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
2299 void CompactibleFreeListSpace::checkFreeListConsistency() const {
a61af66fc99e Initial load
duke
parents:
diff changeset
2300 assert(_dictionary->minSize() <= IndexSetSize,
a61af66fc99e Initial load
duke
parents:
diff changeset
2301 "Some sizes can't be allocated without recourse to"
a61af66fc99e Initial load
duke
parents:
diff changeset
2302 " linear allocation buffers");
a61af66fc99e Initial load
duke
parents:
diff changeset
2303 assert(MIN_TREE_CHUNK_SIZE*HeapWordSize == sizeof(TreeChunk),
a61af66fc99e Initial load
duke
parents:
diff changeset
2304 "else MIN_TREE_CHUNK_SIZE is wrong");
a61af66fc99e Initial load
duke
parents:
diff changeset
2305 assert((IndexSetStride == 2 && IndexSetStart == 2) ||
a61af66fc99e Initial load
duke
parents:
diff changeset
2306 (IndexSetStride == 1 && IndexSetStart == 1), "just checking");
a61af66fc99e Initial load
duke
parents:
diff changeset
2307 assert((IndexSetStride != 2) || (MinChunkSize % 2 == 0),
a61af66fc99e Initial load
duke
parents:
diff changeset
2308 "Some for-loops may be incorrectly initialized");
a61af66fc99e Initial load
duke
parents:
diff changeset
2309 assert((IndexSetStride != 2) || (IndexSetSize % 2 == 1),
a61af66fc99e Initial load
duke
parents:
diff changeset
2310 "For-loops that iterate over IndexSet with stride 2 may be wrong");
a61af66fc99e Initial load
duke
parents:
diff changeset
2311 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2312 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2313
12
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
2314 void CompactibleFreeListSpace::printFLCensus(size_t sweep_count) const {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2315 assert_lock_strong(&_freelistLock);
12
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
2316 FreeList total;
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
2317 gclog_or_tty->print("end sweep# " SIZE_FORMAT "\n", sweep_count);
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
2318 FreeList::print_labels_on(gclog_or_tty, "size");
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2319 size_t totalFree = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
2320 for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2321 const FreeList *fl = &_indexedFreeList[i];
12
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
2322 totalFree += fl->count() * fl->size();
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
2323 if (i % (40*IndexSetStride) == 0) {
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
2324 FreeList::print_labels_on(gclog_or_tty, "size");
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
2325 }
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
2326 fl->print_on(gclog_or_tty);
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
2327 total.set_bfrSurp( total.bfrSurp() + fl->bfrSurp() );
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
2328 total.set_surplus( total.surplus() + fl->surplus() );
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
2329 total.set_desired( total.desired() + fl->desired() );
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
2330 total.set_prevSweep( total.prevSweep() + fl->prevSweep() );
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
2331 total.set_beforeSweep(total.beforeSweep() + fl->beforeSweep());
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
2332 total.set_count( total.count() + fl->count() );
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
2333 total.set_coalBirths( total.coalBirths() + fl->coalBirths() );
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
2334 total.set_coalDeaths( total.coalDeaths() + fl->coalDeaths() );
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
2335 total.set_splitBirths(total.splitBirths() + fl->splitBirths());
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
2336 total.set_splitDeaths(total.splitDeaths() + fl->splitDeaths());
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2337 }
12
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
2338 total.print_on(gclog_or_tty, "TOTAL");
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
2339 gclog_or_tty->print_cr("Total free in indexed lists "
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
2340 SIZE_FORMAT " words", totalFree);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2341 gclog_or_tty->print("growth: %8.5f deficit: %8.5f\n",
12
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
2342 (double)(total.splitBirths()+total.coalBirths()-total.splitDeaths()-total.coalDeaths())/
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
2343 (total.prevSweep() != 0 ? (double)total.prevSweep() : 1.0),
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
2344 (double)(total.desired() - total.count())/(total.desired() != 0 ? (double)total.desired() : 1.0));
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2345 _dictionary->printDictCensus();
a61af66fc99e Initial load
duke
parents:
diff changeset
2346 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2347
a61af66fc99e Initial load
duke
parents:
diff changeset
2348 // Return the next displaced header, incrementing the pointer and
a61af66fc99e Initial load
duke
parents:
diff changeset
2349 // recycling spool area as necessary.
a61af66fc99e Initial load
duke
parents:
diff changeset
2350 markOop PromotionInfo::nextDisplacedHeader() {
a61af66fc99e Initial load
duke
parents:
diff changeset
2351 assert(_spoolHead != NULL, "promotionInfo inconsistency");
a61af66fc99e Initial load
duke
parents:
diff changeset
2352 assert(_spoolHead != _spoolTail || _firstIndex < _nextIndex,
a61af66fc99e Initial load
duke
parents:
diff changeset
2353 "Empty spool space: no displaced header can be fetched");
a61af66fc99e Initial load
duke
parents:
diff changeset
2354 assert(_spoolHead->bufferSize > _firstIndex, "Off by one error at head?");
a61af66fc99e Initial load
duke
parents:
diff changeset
2355 markOop hdr = _spoolHead->displacedHdr[_firstIndex];
a61af66fc99e Initial load
duke
parents:
diff changeset
2356 // Spool forward
a61af66fc99e Initial load
duke
parents:
diff changeset
2357 if (++_firstIndex == _spoolHead->bufferSize) { // last location in this block
a61af66fc99e Initial load
duke
parents:
diff changeset
2358 // forward to next block, recycling this block into spare spool buffer
a61af66fc99e Initial load
duke
parents:
diff changeset
2359 SpoolBlock* tmp = _spoolHead->nextSpoolBlock;
a61af66fc99e Initial load
duke
parents:
diff changeset
2360 assert(_spoolHead != _spoolTail, "Spooling storage mix-up");
a61af66fc99e Initial load
duke
parents:
diff changeset
2361 _spoolHead->nextSpoolBlock = _spareSpool;
a61af66fc99e Initial load
duke
parents:
diff changeset
2362 _spareSpool = _spoolHead;
a61af66fc99e Initial load
duke
parents:
diff changeset
2363 _spoolHead = tmp;
a61af66fc99e Initial load
duke
parents:
diff changeset
2364 _firstIndex = 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
2365 NOT_PRODUCT(
a61af66fc99e Initial load
duke
parents:
diff changeset
2366 if (_spoolHead == NULL) { // all buffers fully consumed
a61af66fc99e Initial load
duke
parents:
diff changeset
2367 assert(_spoolTail == NULL && _nextIndex == 1,
a61af66fc99e Initial load
duke
parents:
diff changeset
2368 "spool buffers processing inconsistency");
a61af66fc99e Initial load
duke
parents:
diff changeset
2369 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2370 )
a61af66fc99e Initial load
duke
parents:
diff changeset
2371 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2372 return hdr;
a61af66fc99e Initial load
duke
parents:
diff changeset
2373 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2374
a61af66fc99e Initial load
duke
parents:
diff changeset
2375 void PromotionInfo::track(PromotedObject* trackOop) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2376 track(trackOop, oop(trackOop)->klass());
a61af66fc99e Initial load
duke
parents:
diff changeset
2377 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2378
a61af66fc99e Initial load
duke
parents:
diff changeset
2379 void PromotionInfo::track(PromotedObject* trackOop, klassOop klassOfOop) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2380 // make a copy of header as it may need to be spooled
a61af66fc99e Initial load
duke
parents:
diff changeset
2381 markOop mark = oop(trackOop)->mark();
a61af66fc99e Initial load
duke
parents:
diff changeset
2382 trackOop->clearNext();
a61af66fc99e Initial load
duke
parents:
diff changeset
2383 if (mark->must_be_preserved_for_cms_scavenge(klassOfOop)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2384 // save non-prototypical header, and mark oop
a61af66fc99e Initial load
duke
parents:
diff changeset
2385 saveDisplacedHeader(mark);
a61af66fc99e Initial load
duke
parents:
diff changeset
2386 trackOop->setDisplacedMark();
a61af66fc99e Initial load
duke
parents:
diff changeset
2387 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2388 // we'd like to assert something like the following:
a61af66fc99e Initial load
duke
parents:
diff changeset
2389 // assert(mark == markOopDesc::prototype(), "consistency check");
a61af66fc99e Initial load
duke
parents:
diff changeset
2390 // ... but the above won't work because the age bits have not (yet) been
a61af66fc99e Initial load
duke
parents:
diff changeset
2391 // cleared. The remainder of the check would be identical to the
a61af66fc99e Initial load
duke
parents:
diff changeset
2392 // condition checked in must_be_preserved() above, so we don't really
a61af66fc99e Initial load
duke
parents:
diff changeset
2393 // have anything useful to check here!
a61af66fc99e Initial load
duke
parents:
diff changeset
2394 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2395 if (_promoTail != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2396 assert(_promoHead != NULL, "List consistency");
a61af66fc99e Initial load
duke
parents:
diff changeset
2397 _promoTail->setNext(trackOop);
a61af66fc99e Initial load
duke
parents:
diff changeset
2398 _promoTail = trackOop;
a61af66fc99e Initial load
duke
parents:
diff changeset
2399 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2400 assert(_promoHead == NULL, "List consistency");
a61af66fc99e Initial load
duke
parents:
diff changeset
2401 _promoHead = _promoTail = trackOop;
a61af66fc99e Initial load
duke
parents:
diff changeset
2402 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2403 // Mask as newly promoted, so we can skip over such objects
a61af66fc99e Initial load
duke
parents:
diff changeset
2404 // when scanning dirty cards
a61af66fc99e Initial load
duke
parents:
diff changeset
2405 assert(!trackOop->hasPromotedMark(), "Should not have been marked");
a61af66fc99e Initial load
duke
parents:
diff changeset
2406 trackOop->setPromotedMark();
a61af66fc99e Initial load
duke
parents:
diff changeset
2407 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2408
a61af66fc99e Initial load
duke
parents:
diff changeset
2409 // Save the given displaced header, incrementing the pointer and
a61af66fc99e Initial load
duke
parents:
diff changeset
2410 // obtaining more spool area as necessary.
a61af66fc99e Initial load
duke
parents:
diff changeset
2411 void PromotionInfo::saveDisplacedHeader(markOop hdr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2412 assert(_spoolHead != NULL && _spoolTail != NULL,
a61af66fc99e Initial load
duke
parents:
diff changeset
2413 "promotionInfo inconsistency");
a61af66fc99e Initial load
duke
parents:
diff changeset
2414 assert(_spoolTail->bufferSize > _nextIndex, "Off by one error at tail?");
a61af66fc99e Initial load
duke
parents:
diff changeset
2415 _spoolTail->displacedHdr[_nextIndex] = hdr;
a61af66fc99e Initial load
duke
parents:
diff changeset
2416 // Spool forward
a61af66fc99e Initial load
duke
parents:
diff changeset
2417 if (++_nextIndex == _spoolTail->bufferSize) { // last location in this block
a61af66fc99e Initial load
duke
parents:
diff changeset
2418 // get a new spooling block
a61af66fc99e Initial load
duke
parents:
diff changeset
2419 assert(_spoolTail->nextSpoolBlock == NULL, "tail should terminate spool list");
a61af66fc99e Initial load
duke
parents:
diff changeset
2420 _splice_point = _spoolTail; // save for splicing
a61af66fc99e Initial load
duke
parents:
diff changeset
2421 _spoolTail->nextSpoolBlock = getSpoolBlock(); // might fail
a61af66fc99e Initial load
duke
parents:
diff changeset
2422 _spoolTail = _spoolTail->nextSpoolBlock; // might become NULL ...
a61af66fc99e Initial load
duke
parents:
diff changeset
2423 // ... but will attempt filling before next promotion attempt
a61af66fc99e Initial load
duke
parents:
diff changeset
2424 _nextIndex = 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
2425 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2426 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2427
a61af66fc99e Initial load
duke
parents:
diff changeset
2428 // Ensure that spooling space exists. Return false if spooling space
a61af66fc99e Initial load
duke
parents:
diff changeset
2429 // could not be obtained.
a61af66fc99e Initial load
duke
parents:
diff changeset
2430 bool PromotionInfo::ensure_spooling_space_work() {
a61af66fc99e Initial load
duke
parents:
diff changeset
2431 assert(!has_spooling_space(), "Only call when there is no spooling space");
a61af66fc99e Initial load
duke
parents:
diff changeset
2432 // Try and obtain more spooling space
a61af66fc99e Initial load
duke
parents:
diff changeset
2433 SpoolBlock* newSpool = getSpoolBlock();
a61af66fc99e Initial load
duke
parents:
diff changeset
2434 assert(newSpool == NULL ||
a61af66fc99e Initial load
duke
parents:
diff changeset
2435 (newSpool->bufferSize != 0 && newSpool->nextSpoolBlock == NULL),
a61af66fc99e Initial load
duke
parents:
diff changeset
2436 "getSpoolBlock() sanity check");
a61af66fc99e Initial load
duke
parents:
diff changeset
2437 if (newSpool == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2438 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
2439 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2440 _nextIndex = 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
2441 if (_spoolTail == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2442 _spoolTail = newSpool;
a61af66fc99e Initial load
duke
parents:
diff changeset
2443 if (_spoolHead == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2444 _spoolHead = newSpool;
a61af66fc99e Initial load
duke
parents:
diff changeset
2445 _firstIndex = 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
2446 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2447 assert(_splice_point != NULL && _splice_point->nextSpoolBlock == NULL,
a61af66fc99e Initial load
duke
parents:
diff changeset
2448 "Splice point invariant");
a61af66fc99e Initial load
duke
parents:
diff changeset
2449 // Extra check that _splice_point is connected to list
a61af66fc99e Initial load
duke
parents:
diff changeset
2450 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
2451 {
a61af66fc99e Initial load
duke
parents:
diff changeset
2452 SpoolBlock* blk = _spoolHead;
a61af66fc99e Initial load
duke
parents:
diff changeset
2453 for (; blk->nextSpoolBlock != NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
2454 blk = blk->nextSpoolBlock);
a61af66fc99e Initial load
duke
parents:
diff changeset
2455 assert(blk != NULL && blk == _splice_point,
a61af66fc99e Initial load
duke
parents:
diff changeset
2456 "Splice point incorrect");
a61af66fc99e Initial load
duke
parents:
diff changeset
2457 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2458 #endif // ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
2459 _splice_point->nextSpoolBlock = newSpool;
a61af66fc99e Initial load
duke
parents:
diff changeset
2460 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2461 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2462 assert(_spoolHead != NULL, "spool list consistency");
a61af66fc99e Initial load
duke
parents:
diff changeset
2463 _spoolTail->nextSpoolBlock = newSpool;
a61af66fc99e Initial load
duke
parents:
diff changeset
2464 _spoolTail = newSpool;
a61af66fc99e Initial load
duke
parents:
diff changeset
2465 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2466 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
2467 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2468
a61af66fc99e Initial load
duke
parents:
diff changeset
2469 // Get a free spool buffer from the free pool, getting a new block
a61af66fc99e Initial load
duke
parents:
diff changeset
2470 // from the heap if necessary.
a61af66fc99e Initial load
duke
parents:
diff changeset
2471 SpoolBlock* PromotionInfo::getSpoolBlock() {
a61af66fc99e Initial load
duke
parents:
diff changeset
2472 SpoolBlock* res;
a61af66fc99e Initial load
duke
parents:
diff changeset
2473 if ((res = _spareSpool) != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2474 _spareSpool = _spareSpool->nextSpoolBlock;
a61af66fc99e Initial load
duke
parents:
diff changeset
2475 res->nextSpoolBlock = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
2476 } else { // spare spool exhausted, get some from heap
a61af66fc99e Initial load
duke
parents:
diff changeset
2477 res = (SpoolBlock*)(space()->allocateScratch(refillSize()));
a61af66fc99e Initial load
duke
parents:
diff changeset
2478 if (res != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2479 res->init();
a61af66fc99e Initial load
duke
parents:
diff changeset
2480 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2481 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2482 assert(res == NULL || res->nextSpoolBlock == NULL, "postcondition");
a61af66fc99e Initial load
duke
parents:
diff changeset
2483 return res;
a61af66fc99e Initial load
duke
parents:
diff changeset
2484 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2485
a61af66fc99e Initial load
duke
parents:
diff changeset
2486 void PromotionInfo::startTrackingPromotions() {
a61af66fc99e Initial load
duke
parents:
diff changeset
2487 assert(_spoolHead == _spoolTail && _firstIndex == _nextIndex,
a61af66fc99e Initial load
duke
parents:
diff changeset
2488 "spooling inconsistency?");
a61af66fc99e Initial load
duke
parents:
diff changeset
2489 _firstIndex = _nextIndex = 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
2490 _tracking = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
2491 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2492
a61af66fc99e Initial load
duke
parents:
diff changeset
2493 void PromotionInfo::stopTrackingPromotions() {
a61af66fc99e Initial load
duke
parents:
diff changeset
2494 assert(_spoolHead == _spoolTail && _firstIndex == _nextIndex,
a61af66fc99e Initial load
duke
parents:
diff changeset
2495 "spooling inconsistency?");
a61af66fc99e Initial load
duke
parents:
diff changeset
2496 _firstIndex = _nextIndex = 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
2497 _tracking = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
2498 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2499
a61af66fc99e Initial load
duke
parents:
diff changeset
2500 // When _spoolTail is not NULL, then the slot <_spoolTail, _nextIndex>
a61af66fc99e Initial load
duke
parents:
diff changeset
2501 // points to the next slot available for filling.
a61af66fc99e Initial load
duke
parents:
diff changeset
2502 // The set of slots holding displaced headers are then all those in the
a61af66fc99e Initial load
duke
parents:
diff changeset
2503 // right-open interval denoted by:
a61af66fc99e Initial load
duke
parents:
diff changeset
2504 //
a61af66fc99e Initial load
duke
parents:
diff changeset
2505 // [ <_spoolHead, _firstIndex>, <_spoolTail, _nextIndex> )
a61af66fc99e Initial load
duke
parents:
diff changeset
2506 //
a61af66fc99e Initial load
duke
parents:
diff changeset
2507 // When _spoolTail is NULL, then the set of slots with displaced headers
a61af66fc99e Initial load
duke
parents:
diff changeset
2508 // is all those starting at the slot <_spoolHead, _firstIndex> and
a61af66fc99e Initial load
duke
parents:
diff changeset
2509 // going up to the last slot of last block in the linked list.
a61af66fc99e Initial load
duke
parents:
diff changeset
2510 // In this lartter case, _splice_point points to the tail block of
a61af66fc99e Initial load
duke
parents:
diff changeset
2511 // this linked list of blocks holding displaced headers.
a61af66fc99e Initial load
duke
parents:
diff changeset
2512 void PromotionInfo::verify() const {
a61af66fc99e Initial load
duke
parents:
diff changeset
2513 // Verify the following:
a61af66fc99e Initial load
duke
parents:
diff changeset
2514 // 1. the number of displaced headers matches the number of promoted
a61af66fc99e Initial load
duke
parents:
diff changeset
2515 // objects that have displaced headers
a61af66fc99e Initial load
duke
parents:
diff changeset
2516 // 2. each promoted object lies in this space
a61af66fc99e Initial load
duke
parents:
diff changeset
2517 debug_only(
a61af66fc99e Initial load
duke
parents:
diff changeset
2518 PromotedObject* junk = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
2519 assert(junk->next_addr() == (void*)(oop(junk)->mark_addr()),
a61af66fc99e Initial load
duke
parents:
diff changeset
2520 "Offset of PromotedObject::_next is expected to align with "
a61af66fc99e Initial load
duke
parents:
diff changeset
2521 " the OopDesc::_mark within OopDesc");
a61af66fc99e Initial load
duke
parents:
diff changeset
2522 )
a61af66fc99e Initial load
duke
parents:
diff changeset
2523 // FIXME: guarantee????
a61af66fc99e Initial load
duke
parents:
diff changeset
2524 guarantee(_spoolHead == NULL || _spoolTail != NULL ||
a61af66fc99e Initial load
duke
parents:
diff changeset
2525 _splice_point != NULL, "list consistency");
a61af66fc99e Initial load
duke
parents:
diff changeset
2526 guarantee(_promoHead == NULL || _promoTail != NULL, "list consistency");
a61af66fc99e Initial load
duke
parents:
diff changeset
2527 // count the number of objects with displaced headers
a61af66fc99e Initial load
duke
parents:
diff changeset
2528 size_t numObjsWithDisplacedHdrs = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
2529 for (PromotedObject* curObj = _promoHead; curObj != NULL; curObj = curObj->next()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2530 guarantee(space()->is_in_reserved((HeapWord*)curObj), "Containment");
a61af66fc99e Initial load
duke
parents:
diff changeset
2531 // the last promoted object may fail the mark() != NULL test of is_oop().
a61af66fc99e Initial load
duke
parents:
diff changeset
2532 guarantee(curObj->next() == NULL || oop(curObj)->is_oop(), "must be an oop");
a61af66fc99e Initial load
duke
parents:
diff changeset
2533 if (curObj->hasDisplacedMark()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2534 numObjsWithDisplacedHdrs++;
a61af66fc99e Initial load
duke
parents:
diff changeset
2535 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2536 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2537 // Count the number of displaced headers
a61af66fc99e Initial load
duke
parents:
diff changeset
2538 size_t numDisplacedHdrs = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
2539 for (SpoolBlock* curSpool = _spoolHead;
a61af66fc99e Initial load
duke
parents:
diff changeset
2540 curSpool != _spoolTail && curSpool != NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
2541 curSpool = curSpool->nextSpoolBlock) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2542 // the first entry is just a self-pointer; indices 1 through
a61af66fc99e Initial load
duke
parents:
diff changeset
2543 // bufferSize - 1 are occupied (thus, bufferSize - 1 slots).
a61af66fc99e Initial load
duke
parents:
diff changeset
2544 guarantee((void*)curSpool->displacedHdr == (void*)&curSpool->displacedHdr,
a61af66fc99e Initial load
duke
parents:
diff changeset
2545 "first entry of displacedHdr should be self-referential");
a61af66fc99e Initial load
duke
parents:
diff changeset
2546 numDisplacedHdrs += curSpool->bufferSize - 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
2547 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2548 guarantee((_spoolHead == _spoolTail) == (numDisplacedHdrs == 0),
a61af66fc99e Initial load
duke
parents:
diff changeset
2549 "internal consistency");
a61af66fc99e Initial load
duke
parents:
diff changeset
2550 guarantee(_spoolTail != NULL || _nextIndex == 1,
a61af66fc99e Initial load
duke
parents:
diff changeset
2551 "Inconsistency between _spoolTail and _nextIndex");
a61af66fc99e Initial load
duke
parents:
diff changeset
2552 // We overcounted (_firstIndex-1) worth of slots in block
a61af66fc99e Initial load
duke
parents:
diff changeset
2553 // _spoolHead and we undercounted (_nextIndex-1) worth of
a61af66fc99e Initial load
duke
parents:
diff changeset
2554 // slots in block _spoolTail. We make an appropriate
a61af66fc99e Initial load
duke
parents:
diff changeset
2555 // adjustment by subtracting the first and adding the
a61af66fc99e Initial load
duke
parents:
diff changeset
2556 // second: - (_firstIndex - 1) + (_nextIndex - 1)
a61af66fc99e Initial load
duke
parents:
diff changeset
2557 numDisplacedHdrs += (_nextIndex - _firstIndex);
a61af66fc99e Initial load
duke
parents:
diff changeset
2558 guarantee(numDisplacedHdrs == numObjsWithDisplacedHdrs, "Displaced hdr count");
a61af66fc99e Initial load
duke
parents:
diff changeset
2559 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2560
a61af66fc99e Initial load
duke
parents:
diff changeset
2561
a61af66fc99e Initial load
duke
parents:
diff changeset
2562 CFLS_LAB::CFLS_LAB(CompactibleFreeListSpace* cfls) :
a61af66fc99e Initial load
duke
parents:
diff changeset
2563 _cfls(cfls)
a61af66fc99e Initial load
duke
parents:
diff changeset
2564 {
a61af66fc99e Initial load
duke
parents:
diff changeset
2565 _blocks_to_claim = CMSParPromoteBlocksToClaim;
a61af66fc99e Initial load
duke
parents:
diff changeset
2566 for (size_t i = CompactibleFreeListSpace::IndexSetStart;
a61af66fc99e Initial load
duke
parents:
diff changeset
2567 i < CompactibleFreeListSpace::IndexSetSize;
a61af66fc99e Initial load
duke
parents:
diff changeset
2568 i += CompactibleFreeListSpace::IndexSetStride) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2569 _indexedFreeList[i].set_size(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
2570 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2571 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2572
a61af66fc99e Initial load
duke
parents:
diff changeset
2573 HeapWord* CFLS_LAB::alloc(size_t word_sz) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2574 FreeChunk* res;
a61af66fc99e Initial load
duke
parents:
diff changeset
2575 word_sz = _cfls->adjustObjectSize(word_sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
2576 if (word_sz >= CompactibleFreeListSpace::IndexSetSize) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2577 // This locking manages sync with other large object allocations.
a61af66fc99e Initial load
duke
parents:
diff changeset
2578 MutexLockerEx x(_cfls->parDictionaryAllocLock(),
a61af66fc99e Initial load
duke
parents:
diff changeset
2579 Mutex::_no_safepoint_check_flag);
a61af66fc99e Initial load
duke
parents:
diff changeset
2580 res = _cfls->getChunkFromDictionaryExact(word_sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
2581 if (res == NULL) return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
2582 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2583 FreeList* fl = &_indexedFreeList[word_sz];
a61af66fc99e Initial load
duke
parents:
diff changeset
2584 bool filled = false; //TRAP
a61af66fc99e Initial load
duke
parents:
diff changeset
2585 if (fl->count() == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2586 bool filled = true; //TRAP
a61af66fc99e Initial load
duke
parents:
diff changeset
2587 // Attempt to refill this local free list.
a61af66fc99e Initial load
duke
parents:
diff changeset
2588 _cfls->par_get_chunk_of_blocks(word_sz, _blocks_to_claim, fl);
a61af66fc99e Initial load
duke
parents:
diff changeset
2589 // If it didn't work, give up.
a61af66fc99e Initial load
duke
parents:
diff changeset
2590 if (fl->count() == 0) return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
2591 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2592 res = fl->getChunkAtHead();
a61af66fc99e Initial load
duke
parents:
diff changeset
2593 assert(res != NULL, "Why was count non-zero?");
a61af66fc99e Initial load
duke
parents:
diff changeset
2594 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2595 res->markNotFree();
a61af66fc99e Initial load
duke
parents:
diff changeset
2596 assert(!res->isFree(), "shouldn't be marked free");
187
790e66e5fbac 6687581: Make CMS work with compressed oops
coleenp
parents: 113
diff changeset
2597 assert(oop(res)->klass_or_null() == NULL, "should look uninitialized");
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2598 // mangle a just allocated object with a distinct pattern.
a61af66fc99e Initial load
duke
parents:
diff changeset
2599 debug_only(res->mangleAllocated(word_sz));
a61af66fc99e Initial load
duke
parents:
diff changeset
2600 return (HeapWord*)res;
a61af66fc99e Initial load
duke
parents:
diff changeset
2601 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2602
a61af66fc99e Initial load
duke
parents:
diff changeset
2603 void CFLS_LAB::retire() {
a61af66fc99e Initial load
duke
parents:
diff changeset
2604 for (size_t i = CompactibleFreeListSpace::IndexSetStart;
a61af66fc99e Initial load
duke
parents:
diff changeset
2605 i < CompactibleFreeListSpace::IndexSetSize;
a61af66fc99e Initial load
duke
parents:
diff changeset
2606 i += CompactibleFreeListSpace::IndexSetStride) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2607 if (_indexedFreeList[i].count() > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2608 MutexLockerEx x(_cfls->_indexedFreeListParLocks[i],
a61af66fc99e Initial load
duke
parents:
diff changeset
2609 Mutex::_no_safepoint_check_flag);
a61af66fc99e Initial load
duke
parents:
diff changeset
2610 _cfls->_indexedFreeList[i].prepend(&_indexedFreeList[i]);
a61af66fc99e Initial load
duke
parents:
diff changeset
2611 // Reset this list.
a61af66fc99e Initial load
duke
parents:
diff changeset
2612 _indexedFreeList[i] = FreeList();
a61af66fc99e Initial load
duke
parents:
diff changeset
2613 _indexedFreeList[i].set_size(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
2614 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2615 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2616 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2617
a61af66fc99e Initial load
duke
parents:
diff changeset
2618 void
a61af66fc99e Initial load
duke
parents:
diff changeset
2619 CompactibleFreeListSpace::
a61af66fc99e Initial load
duke
parents:
diff changeset
2620 par_get_chunk_of_blocks(size_t word_sz, size_t n, FreeList* fl) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2621 assert(fl->count() == 0, "Precondition.");
a61af66fc99e Initial load
duke
parents:
diff changeset
2622 assert(word_sz < CompactibleFreeListSpace::IndexSetSize,
a61af66fc99e Initial load
duke
parents:
diff changeset
2623 "Precondition");
a61af66fc99e Initial load
duke
parents:
diff changeset
2624
a61af66fc99e Initial load
duke
parents:
diff changeset
2625 // We'll try all multiples of word_sz in the indexed set (starting with
a61af66fc99e Initial load
duke
parents:
diff changeset
2626 // word_sz itself), then try getting a big chunk and splitting it.
a61af66fc99e Initial load
duke
parents:
diff changeset
2627 int k = 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
2628 size_t cur_sz = k * word_sz;
a61af66fc99e Initial load
duke
parents:
diff changeset
2629 bool found = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
2630 while (cur_sz < CompactibleFreeListSpace::IndexSetSize && k == 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2631 FreeList* gfl = &_indexedFreeList[cur_sz];
a61af66fc99e Initial load
duke
parents:
diff changeset
2632 FreeList fl_for_cur_sz; // Empty.
a61af66fc99e Initial load
duke
parents:
diff changeset
2633 fl_for_cur_sz.set_size(cur_sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
2634 {
a61af66fc99e Initial load
duke
parents:
diff changeset
2635 MutexLockerEx x(_indexedFreeListParLocks[cur_sz],
a61af66fc99e Initial load
duke
parents:
diff changeset
2636 Mutex::_no_safepoint_check_flag);
a61af66fc99e Initial load
duke
parents:
diff changeset
2637 if (gfl->count() != 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2638 size_t nn = MAX2(n/k, (size_t)1);
a61af66fc99e Initial load
duke
parents:
diff changeset
2639 gfl->getFirstNChunksFromList(nn, &fl_for_cur_sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
2640 found = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
2641 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2642 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2643 // Now transfer fl_for_cur_sz to fl. Common case, we hope, is k = 1.
a61af66fc99e Initial load
duke
parents:
diff changeset
2644 if (found) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2645 if (k == 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2646 fl->prepend(&fl_for_cur_sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
2647 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2648 // Divide each block on fl_for_cur_sz up k ways.
a61af66fc99e Initial load
duke
parents:
diff changeset
2649 FreeChunk* fc;
a61af66fc99e Initial load
duke
parents:
diff changeset
2650 while ((fc = fl_for_cur_sz.getChunkAtHead()) != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2651 // Must do this in reverse order, so that anybody attempting to
a61af66fc99e Initial load
duke
parents:
diff changeset
2652 // access the main chunk sees it as a single free block until we
a61af66fc99e Initial load
duke
parents:
diff changeset
2653 // change it.
a61af66fc99e Initial load
duke
parents:
diff changeset
2654 size_t fc_size = fc->size();
a61af66fc99e Initial load
duke
parents:
diff changeset
2655 for (int i = k-1; i >= 0; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2656 FreeChunk* ffc = (FreeChunk*)((HeapWord*)fc + i * word_sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
2657 ffc->setSize(word_sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
2658 ffc->linkNext(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
2659 ffc->linkPrev(NULL); // Mark as a free block for other (parallel) GC threads.
a61af66fc99e Initial load
duke
parents:
diff changeset
2660 // Above must occur before BOT is updated below.
a61af66fc99e Initial load
duke
parents:
diff changeset
2661 // splitting from the right, fc_size == (k - i + 1) * wordsize
a61af66fc99e Initial load
duke
parents:
diff changeset
2662 _bt.mark_block((HeapWord*)ffc, word_sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
2663 fc_size -= word_sz;
a61af66fc99e Initial load
duke
parents:
diff changeset
2664 _bt.verify_not_unallocated((HeapWord*)ffc, ffc->size());
a61af66fc99e Initial load
duke
parents:
diff changeset
2665 _bt.verify_single_block((HeapWord*)fc, fc_size);
a61af66fc99e Initial load
duke
parents:
diff changeset
2666 _bt.verify_single_block((HeapWord*)ffc, ffc->size());
a61af66fc99e Initial load
duke
parents:
diff changeset
2667 // Push this on "fl".
a61af66fc99e Initial load
duke
parents:
diff changeset
2668 fl->returnChunkAtHead(ffc);
a61af66fc99e Initial load
duke
parents:
diff changeset
2669 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2670 // TRAP
a61af66fc99e Initial load
duke
parents:
diff changeset
2671 assert(fl->tail()->next() == NULL, "List invariant.");
a61af66fc99e Initial load
duke
parents:
diff changeset
2672 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2673 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2674 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
2675 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2676 k++; cur_sz = k * word_sz;
a61af66fc99e Initial load
duke
parents:
diff changeset
2677 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2678 // Otherwise, we'll split a block from the dictionary.
a61af66fc99e Initial load
duke
parents:
diff changeset
2679 FreeChunk* fc = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
2680 FreeChunk* rem_fc = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
2681 size_t rem;
a61af66fc99e Initial load
duke
parents:
diff changeset
2682 {
a61af66fc99e Initial load
duke
parents:
diff changeset
2683 MutexLockerEx x(parDictionaryAllocLock(),
a61af66fc99e Initial load
duke
parents:
diff changeset
2684 Mutex::_no_safepoint_check_flag);
a61af66fc99e Initial load
duke
parents:
diff changeset
2685 while (n > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2686 fc = dictionary()->getChunk(MAX2(n * word_sz,
a61af66fc99e Initial load
duke
parents:
diff changeset
2687 _dictionary->minSize()),
a61af66fc99e Initial load
duke
parents:
diff changeset
2688 FreeBlockDictionary::atLeast);
a61af66fc99e Initial load
duke
parents:
diff changeset
2689 if (fc != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2690 _bt.allocated((HeapWord*)fc, fc->size()); // update _unallocated_blk
a61af66fc99e Initial load
duke
parents:
diff changeset
2691 dictionary()->dictCensusUpdate(fc->size(),
a61af66fc99e Initial load
duke
parents:
diff changeset
2692 true /*split*/,
a61af66fc99e Initial load
duke
parents:
diff changeset
2693 false /*birth*/);
a61af66fc99e Initial load
duke
parents:
diff changeset
2694 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
2695 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2696 n--;
a61af66fc99e Initial load
duke
parents:
diff changeset
2697 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2698 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2699 if (fc == NULL) return;
a61af66fc99e Initial load
duke
parents:
diff changeset
2700 // Otherwise, split up that block.
a61af66fc99e Initial load
duke
parents:
diff changeset
2701 size_t nn = fc->size() / word_sz;
a61af66fc99e Initial load
duke
parents:
diff changeset
2702 n = MIN2(nn, n);
a61af66fc99e Initial load
duke
parents:
diff changeset
2703 rem = fc->size() - n * word_sz;
a61af66fc99e Initial load
duke
parents:
diff changeset
2704 // If there is a remainder, and it's too small, allocate one fewer.
a61af66fc99e Initial load
duke
parents:
diff changeset
2705 if (rem > 0 && rem < MinChunkSize) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2706 n--; rem += word_sz;
a61af66fc99e Initial load
duke
parents:
diff changeset
2707 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2708 // First return the remainder, if any.
a61af66fc99e Initial load
duke
parents:
diff changeset
2709 // Note that we hold the lock until we decide if we're going to give
a61af66fc99e Initial load
duke
parents:
diff changeset
2710 // back the remainder to the dictionary, since a contending allocator
a61af66fc99e Initial load
duke
parents:
diff changeset
2711 // may otherwise see the heap as empty. (We're willing to take that
a61af66fc99e Initial load
duke
parents:
diff changeset
2712 // hit if the block is a small block.)
a61af66fc99e Initial load
duke
parents:
diff changeset
2713 if (rem > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2714 size_t prefix_size = n * word_sz;
a61af66fc99e Initial load
duke
parents:
diff changeset
2715 rem_fc = (FreeChunk*)((HeapWord*)fc + prefix_size);
a61af66fc99e Initial load
duke
parents:
diff changeset
2716 rem_fc->setSize(rem);
a61af66fc99e Initial load
duke
parents:
diff changeset
2717 rem_fc->linkNext(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
2718 rem_fc->linkPrev(NULL); // Mark as a free block for other (parallel) GC threads.
a61af66fc99e Initial load
duke
parents:
diff changeset
2719 // Above must occur before BOT is updated below.
a61af66fc99e Initial load
duke
parents:
diff changeset
2720 _bt.split_block((HeapWord*)fc, fc->size(), prefix_size);
a61af66fc99e Initial load
duke
parents:
diff changeset
2721 if (rem >= IndexSetSize) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2722 returnChunkToDictionary(rem_fc);
a61af66fc99e Initial load
duke
parents:
diff changeset
2723 dictionary()->dictCensusUpdate(fc->size(),
a61af66fc99e Initial load
duke
parents:
diff changeset
2724 true /*split*/,
a61af66fc99e Initial load
duke
parents:
diff changeset
2725 true /*birth*/);
a61af66fc99e Initial load
duke
parents:
diff changeset
2726 rem_fc = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
2727 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2728 // Otherwise, return it to the small list below.
a61af66fc99e Initial load
duke
parents:
diff changeset
2729 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2730 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2731 //
a61af66fc99e Initial load
duke
parents:
diff changeset
2732 if (rem_fc != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2733 MutexLockerEx x(_indexedFreeListParLocks[rem],
a61af66fc99e Initial load
duke
parents:
diff changeset
2734 Mutex::_no_safepoint_check_flag);
a61af66fc99e Initial load
duke
parents:
diff changeset
2735 _bt.verify_not_unallocated((HeapWord*)rem_fc, rem_fc->size());
a61af66fc99e Initial load
duke
parents:
diff changeset
2736 _indexedFreeList[rem].returnChunkAtHead(rem_fc);
a61af66fc99e Initial load
duke
parents:
diff changeset
2737 smallSplitBirth(rem);
a61af66fc99e Initial load
duke
parents:
diff changeset
2738 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2739
a61af66fc99e Initial load
duke
parents:
diff changeset
2740 // Now do the splitting up.
a61af66fc99e Initial load
duke
parents:
diff changeset
2741 // Must do this in reverse order, so that anybody attempting to
a61af66fc99e Initial load
duke
parents:
diff changeset
2742 // access the main chunk sees it as a single free block until we
a61af66fc99e Initial load
duke
parents:
diff changeset
2743 // change it.
a61af66fc99e Initial load
duke
parents:
diff changeset
2744 size_t fc_size = n * word_sz;
a61af66fc99e Initial load
duke
parents:
diff changeset
2745 // All but first chunk in this loop
a61af66fc99e Initial load
duke
parents:
diff changeset
2746 for (ssize_t i = n-1; i > 0; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2747 FreeChunk* ffc = (FreeChunk*)((HeapWord*)fc + i * word_sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
2748 ffc->setSize(word_sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
2749 ffc->linkNext(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
2750 ffc->linkPrev(NULL); // Mark as a free block for other (parallel) GC threads.
a61af66fc99e Initial load
duke
parents:
diff changeset
2751 // Above must occur before BOT is updated below.
a61af66fc99e Initial load
duke
parents:
diff changeset
2752 // splitting from the right, fc_size == (n - i + 1) * wordsize
a61af66fc99e Initial load
duke
parents:
diff changeset
2753 _bt.mark_block((HeapWord*)ffc, word_sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
2754 fc_size -= word_sz;
a61af66fc99e Initial load
duke
parents:
diff changeset
2755 _bt.verify_not_unallocated((HeapWord*)ffc, ffc->size());
a61af66fc99e Initial load
duke
parents:
diff changeset
2756 _bt.verify_single_block((HeapWord*)ffc, ffc->size());
a61af66fc99e Initial load
duke
parents:
diff changeset
2757 _bt.verify_single_block((HeapWord*)fc, fc_size);
a61af66fc99e Initial load
duke
parents:
diff changeset
2758 // Push this on "fl".
a61af66fc99e Initial load
duke
parents:
diff changeset
2759 fl->returnChunkAtHead(ffc);
a61af66fc99e Initial load
duke
parents:
diff changeset
2760 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2761 // First chunk
a61af66fc99e Initial load
duke
parents:
diff changeset
2762 fc->setSize(word_sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
2763 fc->linkNext(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
2764 fc->linkPrev(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
2765 _bt.verify_not_unallocated((HeapWord*)fc, fc->size());
a61af66fc99e Initial load
duke
parents:
diff changeset
2766 _bt.verify_single_block((HeapWord*)fc, fc->size());
a61af66fc99e Initial load
duke
parents:
diff changeset
2767 fl->returnChunkAtHead(fc);
a61af66fc99e Initial load
duke
parents:
diff changeset
2768
a61af66fc99e Initial load
duke
parents:
diff changeset
2769 {
a61af66fc99e Initial load
duke
parents:
diff changeset
2770 MutexLockerEx x(_indexedFreeListParLocks[word_sz],
a61af66fc99e Initial load
duke
parents:
diff changeset
2771 Mutex::_no_safepoint_check_flag);
a61af66fc99e Initial load
duke
parents:
diff changeset
2772 ssize_t new_births = _indexedFreeList[word_sz].splitBirths() + n;
a61af66fc99e Initial load
duke
parents:
diff changeset
2773 _indexedFreeList[word_sz].set_splitBirths(new_births);
a61af66fc99e Initial load
duke
parents:
diff changeset
2774 ssize_t new_surplus = _indexedFreeList[word_sz].surplus() + n;
a61af66fc99e Initial load
duke
parents:
diff changeset
2775 _indexedFreeList[word_sz].set_surplus(new_surplus);
a61af66fc99e Initial load
duke
parents:
diff changeset
2776 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2777
a61af66fc99e Initial load
duke
parents:
diff changeset
2778 // TRAP
a61af66fc99e Initial load
duke
parents:
diff changeset
2779 assert(fl->tail()->next() == NULL, "List invariant.");
a61af66fc99e Initial load
duke
parents:
diff changeset
2780 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2781
a61af66fc99e Initial load
duke
parents:
diff changeset
2782 // Set up the space's par_seq_tasks structure for work claiming
a61af66fc99e Initial load
duke
parents:
diff changeset
2783 // for parallel rescan. See CMSParRemarkTask where this is currently used.
a61af66fc99e Initial load
duke
parents:
diff changeset
2784 // XXX Need to suitably abstract and generalize this and the next
a61af66fc99e Initial load
duke
parents:
diff changeset
2785 // method into one.
a61af66fc99e Initial load
duke
parents:
diff changeset
2786 void
a61af66fc99e Initial load
duke
parents:
diff changeset
2787 CompactibleFreeListSpace::
a61af66fc99e Initial load
duke
parents:
diff changeset
2788 initialize_sequential_subtasks_for_rescan(int n_threads) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2789 // The "size" of each task is fixed according to rescan_task_size.
a61af66fc99e Initial load
duke
parents:
diff changeset
2790 assert(n_threads > 0, "Unexpected n_threads argument");
a61af66fc99e Initial load
duke
parents:
diff changeset
2791 const size_t task_size = rescan_task_size();
a61af66fc99e Initial load
duke
parents:
diff changeset
2792 size_t n_tasks = (used_region().word_size() + task_size - 1)/task_size;
340
ebeb6490b814 6722116: CMS: Incorrect overflow handling when using parallel concurrent marking
ysr
parents: 269
diff changeset
2793 assert((n_tasks == 0) == used_region().is_empty(), "n_tasks incorrect");
ebeb6490b814 6722116: CMS: Incorrect overflow handling when using parallel concurrent marking
ysr
parents: 269
diff changeset
2794 assert(n_tasks == 0 ||
ebeb6490b814 6722116: CMS: Incorrect overflow handling when using parallel concurrent marking
ysr
parents: 269
diff changeset
2795 ((used_region().start() + (n_tasks - 1)*task_size < used_region().end()) &&
ebeb6490b814 6722116: CMS: Incorrect overflow handling when using parallel concurrent marking
ysr
parents: 269
diff changeset
2796 (used_region().start() + n_tasks*task_size >= used_region().end())),
ebeb6490b814 6722116: CMS: Incorrect overflow handling when using parallel concurrent marking
ysr
parents: 269
diff changeset
2797 "n_tasks calculation incorrect");
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2798 SequentialSubTasksDone* pst = conc_par_seq_tasks();
a61af66fc99e Initial load
duke
parents:
diff changeset
2799 assert(!pst->valid(), "Clobbering existing data?");
a61af66fc99e Initial load
duke
parents:
diff changeset
2800 pst->set_par_threads(n_threads);
a61af66fc99e Initial load
duke
parents:
diff changeset
2801 pst->set_n_tasks((int)n_tasks);
a61af66fc99e Initial load
duke
parents:
diff changeset
2802 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2803
a61af66fc99e Initial load
duke
parents:
diff changeset
2804 // Set up the space's par_seq_tasks structure for work claiming
a61af66fc99e Initial load
duke
parents:
diff changeset
2805 // for parallel concurrent marking. See CMSConcMarkTask where this is currently used.
a61af66fc99e Initial load
duke
parents:
diff changeset
2806 void
a61af66fc99e Initial load
duke
parents:
diff changeset
2807 CompactibleFreeListSpace::
a61af66fc99e Initial load
duke
parents:
diff changeset
2808 initialize_sequential_subtasks_for_marking(int n_threads,
a61af66fc99e Initial load
duke
parents:
diff changeset
2809 HeapWord* low) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2810 // The "size" of each task is fixed according to rescan_task_size.
a61af66fc99e Initial load
duke
parents:
diff changeset
2811 assert(n_threads > 0, "Unexpected n_threads argument");
a61af66fc99e Initial load
duke
parents:
diff changeset
2812 const size_t task_size = marking_task_size();
a61af66fc99e Initial load
duke
parents:
diff changeset
2813 assert(task_size > CardTableModRefBS::card_size_in_words &&
a61af66fc99e Initial load
duke
parents:
diff changeset
2814 (task_size % CardTableModRefBS::card_size_in_words == 0),
a61af66fc99e Initial load
duke
parents:
diff changeset
2815 "Otherwise arithmetic below would be incorrect");
a61af66fc99e Initial load
duke
parents:
diff changeset
2816 MemRegion span = _gen->reserved();
a61af66fc99e Initial load
duke
parents:
diff changeset
2817 if (low != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2818 if (span.contains(low)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2819 // Align low down to a card boundary so that
a61af66fc99e Initial load
duke
parents:
diff changeset
2820 // we can use block_offset_careful() on span boundaries.
a61af66fc99e Initial load
duke
parents:
diff changeset
2821 HeapWord* aligned_low = (HeapWord*)align_size_down((uintptr_t)low,
a61af66fc99e Initial load
duke
parents:
diff changeset
2822 CardTableModRefBS::card_size);
a61af66fc99e Initial load
duke
parents:
diff changeset
2823 // Clip span prefix at aligned_low
a61af66fc99e Initial load
duke
parents:
diff changeset
2824 span = span.intersection(MemRegion(aligned_low, span.end()));
a61af66fc99e Initial load
duke
parents:
diff changeset
2825 } else if (low > span.end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2826 span = MemRegion(low, low); // Null region
a61af66fc99e Initial load
duke
parents:
diff changeset
2827 } // else use entire span
a61af66fc99e Initial load
duke
parents:
diff changeset
2828 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2829 assert(span.is_empty() ||
a61af66fc99e Initial load
duke
parents:
diff changeset
2830 ((uintptr_t)span.start() % CardTableModRefBS::card_size == 0),
a61af66fc99e Initial load
duke
parents:
diff changeset
2831 "span should start at a card boundary");
a61af66fc99e Initial load
duke
parents:
diff changeset
2832 size_t n_tasks = (span.word_size() + task_size - 1)/task_size;
a61af66fc99e Initial load
duke
parents:
diff changeset
2833 assert((n_tasks == 0) == span.is_empty(), "Inconsistency");
a61af66fc99e Initial load
duke
parents:
diff changeset
2834 assert(n_tasks == 0 ||
a61af66fc99e Initial load
duke
parents:
diff changeset
2835 ((span.start() + (n_tasks - 1)*task_size < span.end()) &&
a61af66fc99e Initial load
duke
parents:
diff changeset
2836 (span.start() + n_tasks*task_size >= span.end())),
340
ebeb6490b814 6722116: CMS: Incorrect overflow handling when using parallel concurrent marking
ysr
parents: 269
diff changeset
2837 "n_tasks calculation incorrect");
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2838 SequentialSubTasksDone* pst = conc_par_seq_tasks();
a61af66fc99e Initial load
duke
parents:
diff changeset
2839 assert(!pst->valid(), "Clobbering existing data?");
a61af66fc99e Initial load
duke
parents:
diff changeset
2840 pst->set_par_threads(n_threads);
a61af66fc99e Initial load
duke
parents:
diff changeset
2841 pst->set_n_tasks((int)n_tasks);
a61af66fc99e Initial load
duke
parents:
diff changeset
2842 }