annotate src/share/vm/gc_implementation/parNew/parNewGeneration.cpp @ 453:c96030fff130

6684579: SoftReference processing can be made more efficient Summary: For current soft-ref clearing policies, we can decide at marking time if a soft-reference will definitely not be cleared, postponing the decision of whether it will definitely be cleared to the final reference processing phase. This can be especially beneficial in the case of concurrent collectors where the marking is usually concurrent but reference processing is usually not. Reviewed-by: jmasa
author ysr
date Thu, 20 Nov 2008 16:56:09 -0800
parents 850fdf70db2b
children df4305d4c1a1
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: 167
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/_parNewGeneration.cpp.incl"
a61af66fc99e Initial load
duke
parents:
diff changeset
27
a61af66fc99e Initial load
duke
parents:
diff changeset
28 #ifdef _MSC_VER
a61af66fc99e Initial load
duke
parents:
diff changeset
29 #pragma warning( push )
a61af66fc99e Initial load
duke
parents:
diff changeset
30 #pragma warning( disable:4355 ) // 'this' : used in base member initializer list
a61af66fc99e Initial load
duke
parents:
diff changeset
31 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
32 ParScanThreadState::ParScanThreadState(Space* to_space_,
a61af66fc99e Initial load
duke
parents:
diff changeset
33 ParNewGeneration* gen_,
a61af66fc99e Initial load
duke
parents:
diff changeset
34 Generation* old_gen_,
a61af66fc99e Initial load
duke
parents:
diff changeset
35 int thread_num_,
a61af66fc99e Initial load
duke
parents:
diff changeset
36 ObjToScanQueueSet* work_queue_set_,
a61af66fc99e Initial load
duke
parents:
diff changeset
37 size_t desired_plab_sz_,
a61af66fc99e Initial load
duke
parents:
diff changeset
38 ParallelTaskTerminator& term_) :
a61af66fc99e Initial load
duke
parents:
diff changeset
39 _to_space(to_space_), _old_gen(old_gen_), _thread_num(thread_num_),
a61af66fc99e Initial load
duke
parents:
diff changeset
40 _work_queue(work_queue_set_->queue(thread_num_)), _to_space_full(false),
a61af66fc99e Initial load
duke
parents:
diff changeset
41 _ageTable(false), // false ==> not the global age table, no perf data.
a61af66fc99e Initial load
duke
parents:
diff changeset
42 _to_space_alloc_buffer(desired_plab_sz_),
a61af66fc99e Initial load
duke
parents:
diff changeset
43 _to_space_closure(gen_, this), _old_gen_closure(gen_, this),
a61af66fc99e Initial load
duke
parents:
diff changeset
44 _to_space_root_closure(gen_, this), _old_gen_root_closure(gen_, this),
a61af66fc99e Initial load
duke
parents:
diff changeset
45 _older_gen_closure(gen_, this),
a61af66fc99e Initial load
duke
parents:
diff changeset
46 _evacuate_followers(this, &_to_space_closure, &_old_gen_closure,
a61af66fc99e Initial load
duke
parents:
diff changeset
47 &_to_space_root_closure, gen_, &_old_gen_root_closure,
a61af66fc99e Initial load
duke
parents:
diff changeset
48 work_queue_set_, &term_),
a61af66fc99e Initial load
duke
parents:
diff changeset
49 _is_alive_closure(gen_), _scan_weak_ref_closure(gen_, this),
a61af66fc99e Initial load
duke
parents:
diff changeset
50 _keep_alive_closure(&_scan_weak_ref_closure),
a61af66fc99e Initial load
duke
parents:
diff changeset
51 _pushes(0), _pops(0), _steals(0), _steal_attempts(0), _term_attempts(0),
a61af66fc99e Initial load
duke
parents:
diff changeset
52 _strong_roots_time(0.0), _term_time(0.0)
a61af66fc99e Initial load
duke
parents:
diff changeset
53 {
a61af66fc99e Initial load
duke
parents:
diff changeset
54 _survivor_chunk_array =
a61af66fc99e Initial load
duke
parents:
diff changeset
55 (ChunkArray*) old_gen()->get_data_recorder(thread_num());
a61af66fc99e Initial load
duke
parents:
diff changeset
56 _hash_seed = 17; // Might want to take time-based random value.
a61af66fc99e Initial load
duke
parents:
diff changeset
57 _start = os::elapsedTime();
a61af66fc99e Initial load
duke
parents:
diff changeset
58 _old_gen_closure.set_generation(old_gen_);
a61af66fc99e Initial load
duke
parents:
diff changeset
59 _old_gen_root_closure.set_generation(old_gen_);
a61af66fc99e Initial load
duke
parents:
diff changeset
60 }
a61af66fc99e Initial load
duke
parents:
diff changeset
61 #ifdef _MSC_VER
a61af66fc99e Initial load
duke
parents:
diff changeset
62 #pragma warning( pop )
a61af66fc99e Initial load
duke
parents:
diff changeset
63 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
64
a61af66fc99e Initial load
duke
parents:
diff changeset
65 void ParScanThreadState::record_survivor_plab(HeapWord* plab_start,
a61af66fc99e Initial load
duke
parents:
diff changeset
66 size_t plab_word_size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
67 ChunkArray* sca = survivor_chunk_array();
a61af66fc99e Initial load
duke
parents:
diff changeset
68 if (sca != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
69 // A non-null SCA implies that we want the PLAB data recorded.
a61af66fc99e Initial load
duke
parents:
diff changeset
70 sca->record_sample(plab_start, plab_word_size);
a61af66fc99e Initial load
duke
parents:
diff changeset
71 }
a61af66fc99e Initial load
duke
parents:
diff changeset
72 }
a61af66fc99e Initial load
duke
parents:
diff changeset
73
a61af66fc99e Initial load
duke
parents:
diff changeset
74 bool ParScanThreadState::should_be_partially_scanned(oop new_obj, oop old_obj) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
75 return new_obj->is_objArray() &&
a61af66fc99e Initial load
duke
parents:
diff changeset
76 arrayOop(new_obj)->length() > ParGCArrayScanChunk &&
a61af66fc99e Initial load
duke
parents:
diff changeset
77 new_obj != old_obj;
a61af66fc99e Initial load
duke
parents:
diff changeset
78 }
a61af66fc99e Initial load
duke
parents:
diff changeset
79
a61af66fc99e Initial load
duke
parents:
diff changeset
80 void ParScanThreadState::scan_partial_array_and_push_remainder(oop old) {
a61af66fc99e Initial load
duke
parents:
diff changeset
81 assert(old->is_objArray(), "must be obj array");
a61af66fc99e Initial load
duke
parents:
diff changeset
82 assert(old->is_forwarded(), "must be forwarded");
a61af66fc99e Initial load
duke
parents:
diff changeset
83 assert(Universe::heap()->is_in_reserved(old), "must be in heap.");
a61af66fc99e Initial load
duke
parents:
diff changeset
84 assert(!_old_gen->is_in(old), "must be in young generation.");
a61af66fc99e Initial load
duke
parents:
diff changeset
85
a61af66fc99e Initial load
duke
parents:
diff changeset
86 objArrayOop obj = objArrayOop(old->forwardee());
a61af66fc99e Initial load
duke
parents:
diff changeset
87 // Process ParGCArrayScanChunk elements now
a61af66fc99e Initial load
duke
parents:
diff changeset
88 // and push the remainder back onto queue
a61af66fc99e Initial load
duke
parents:
diff changeset
89 int start = arrayOop(old)->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
90 int end = obj->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
91 int remainder = end - start;
a61af66fc99e Initial load
duke
parents:
diff changeset
92 assert(start <= end, "just checking");
a61af66fc99e Initial load
duke
parents:
diff changeset
93 if (remainder > 2 * ParGCArrayScanChunk) {
a61af66fc99e Initial load
duke
parents:
diff changeset
94 // Test above combines last partial chunk with a full chunk
a61af66fc99e Initial load
duke
parents:
diff changeset
95 end = start + ParGCArrayScanChunk;
a61af66fc99e Initial load
duke
parents:
diff changeset
96 arrayOop(old)->set_length(end);
a61af66fc99e Initial load
duke
parents:
diff changeset
97 // Push remainder.
a61af66fc99e Initial load
duke
parents:
diff changeset
98 bool ok = work_queue()->push(old);
a61af66fc99e Initial load
duke
parents:
diff changeset
99 assert(ok, "just popped, push must be okay");
a61af66fc99e Initial load
duke
parents:
diff changeset
100 note_push();
a61af66fc99e Initial load
duke
parents:
diff changeset
101 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
102 // Restore length so that it can be used if there
a61af66fc99e Initial load
duke
parents:
diff changeset
103 // is a promotion failure and forwarding pointers
a61af66fc99e Initial load
duke
parents:
diff changeset
104 // must be removed.
a61af66fc99e Initial load
duke
parents:
diff changeset
105 arrayOop(old)->set_length(end);
a61af66fc99e Initial load
duke
parents:
diff changeset
106 }
113
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
107
0
a61af66fc99e Initial load
duke
parents:
diff changeset
108 // process our set of indices (include header in first chunk)
113
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
109 // should make sure end is even (aligned to HeapWord in case of compressed oops)
0
a61af66fc99e Initial load
duke
parents:
diff changeset
110 if ((HeapWord *)obj < young_old_boundary()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
111 // object is in to_space
113
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
112 obj->oop_iterate_range(&_to_space_closure, start, end);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
113 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
114 // object is in old generation
113
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
115 obj->oop_iterate_range(&_old_gen_closure, start, end);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
116 }
a61af66fc99e Initial load
duke
parents:
diff changeset
117 }
a61af66fc99e Initial load
duke
parents:
diff changeset
118
a61af66fc99e Initial load
duke
parents:
diff changeset
119
a61af66fc99e Initial load
duke
parents:
diff changeset
120 void ParScanThreadState::trim_queues(int max_size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
121 ObjToScanQueue* queue = work_queue();
a61af66fc99e Initial load
duke
parents:
diff changeset
122 while (queue->size() > (juint)max_size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
123 oop obj_to_scan;
a61af66fc99e Initial load
duke
parents:
diff changeset
124 if (queue->pop_local(obj_to_scan)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
125 note_pop();
a61af66fc99e Initial load
duke
parents:
diff changeset
126
a61af66fc99e Initial load
duke
parents:
diff changeset
127 if ((HeapWord *)obj_to_scan < young_old_boundary()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
128 if (obj_to_scan->is_objArray() &&
a61af66fc99e Initial load
duke
parents:
diff changeset
129 obj_to_scan->is_forwarded() &&
a61af66fc99e Initial load
duke
parents:
diff changeset
130 obj_to_scan->forwardee() != obj_to_scan) {
a61af66fc99e Initial load
duke
parents:
diff changeset
131 scan_partial_array_and_push_remainder(obj_to_scan);
a61af66fc99e Initial load
duke
parents:
diff changeset
132 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
133 // object is in to_space
a61af66fc99e Initial load
duke
parents:
diff changeset
134 obj_to_scan->oop_iterate(&_to_space_closure);
a61af66fc99e Initial load
duke
parents:
diff changeset
135 }
a61af66fc99e Initial load
duke
parents:
diff changeset
136 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
137 // object is in old generation
a61af66fc99e Initial load
duke
parents:
diff changeset
138 obj_to_scan->oop_iterate(&_old_gen_closure);
a61af66fc99e Initial load
duke
parents:
diff changeset
139 }
a61af66fc99e Initial load
duke
parents:
diff changeset
140 }
a61af66fc99e Initial load
duke
parents:
diff changeset
141 }
a61af66fc99e Initial load
duke
parents:
diff changeset
142 }
a61af66fc99e Initial load
duke
parents:
diff changeset
143
a61af66fc99e Initial load
duke
parents:
diff changeset
144 HeapWord* ParScanThreadState::alloc_in_to_space_slow(size_t word_sz) {
a61af66fc99e Initial load
duke
parents:
diff changeset
145
a61af66fc99e Initial load
duke
parents:
diff changeset
146 // Otherwise, if the object is small enough, try to reallocate the
a61af66fc99e Initial load
duke
parents:
diff changeset
147 // buffer.
a61af66fc99e Initial load
duke
parents:
diff changeset
148 HeapWord* obj = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
149 if (!_to_space_full) {
a61af66fc99e Initial load
duke
parents:
diff changeset
150 ParGCAllocBuffer* const plab = to_space_alloc_buffer();
a61af66fc99e Initial load
duke
parents:
diff changeset
151 Space* const sp = to_space();
a61af66fc99e Initial load
duke
parents:
diff changeset
152 if (word_sz * 100 <
a61af66fc99e Initial load
duke
parents:
diff changeset
153 ParallelGCBufferWastePct * plab->word_sz()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
154 // Is small enough; abandon this buffer and start a new one.
a61af66fc99e Initial load
duke
parents:
diff changeset
155 plab->retire(false, false);
a61af66fc99e Initial load
duke
parents:
diff changeset
156 size_t buf_size = plab->word_sz();
a61af66fc99e Initial load
duke
parents:
diff changeset
157 HeapWord* buf_space = sp->par_allocate(buf_size);
a61af66fc99e Initial load
duke
parents:
diff changeset
158 if (buf_space == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
159 const size_t min_bytes =
a61af66fc99e Initial load
duke
parents:
diff changeset
160 ParGCAllocBuffer::min_size() << LogHeapWordSize;
a61af66fc99e Initial load
duke
parents:
diff changeset
161 size_t free_bytes = sp->free();
a61af66fc99e Initial load
duke
parents:
diff changeset
162 while(buf_space == NULL && free_bytes >= min_bytes) {
a61af66fc99e Initial load
duke
parents:
diff changeset
163 buf_size = free_bytes >> LogHeapWordSize;
a61af66fc99e Initial load
duke
parents:
diff changeset
164 assert(buf_size == (size_t)align_object_size(buf_size),
a61af66fc99e Initial load
duke
parents:
diff changeset
165 "Invariant");
a61af66fc99e Initial load
duke
parents:
diff changeset
166 buf_space = sp->par_allocate(buf_size);
a61af66fc99e Initial load
duke
parents:
diff changeset
167 free_bytes = sp->free();
a61af66fc99e Initial load
duke
parents:
diff changeset
168 }
a61af66fc99e Initial load
duke
parents:
diff changeset
169 }
a61af66fc99e Initial load
duke
parents:
diff changeset
170 if (buf_space != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
171 plab->set_word_size(buf_size);
a61af66fc99e Initial load
duke
parents:
diff changeset
172 plab->set_buf(buf_space);
a61af66fc99e Initial load
duke
parents:
diff changeset
173 record_survivor_plab(buf_space, buf_size);
a61af66fc99e Initial load
duke
parents:
diff changeset
174 obj = plab->allocate(word_sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
175 // Note that we cannot compare buf_size < word_sz below
a61af66fc99e Initial load
duke
parents:
diff changeset
176 // because of AlignmentReserve (see ParGCAllocBuffer::allocate()).
a61af66fc99e Initial load
duke
parents:
diff changeset
177 assert(obj != NULL || plab->words_remaining() < word_sz,
a61af66fc99e Initial load
duke
parents:
diff changeset
178 "Else should have been able to allocate");
a61af66fc99e Initial load
duke
parents:
diff changeset
179 // It's conceivable that we may be able to use the
a61af66fc99e Initial load
duke
parents:
diff changeset
180 // buffer we just grabbed for subsequent small requests
a61af66fc99e Initial load
duke
parents:
diff changeset
181 // even if not for this one.
a61af66fc99e Initial load
duke
parents:
diff changeset
182 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
183 // We're used up.
a61af66fc99e Initial load
duke
parents:
diff changeset
184 _to_space_full = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
185 }
a61af66fc99e Initial load
duke
parents:
diff changeset
186
a61af66fc99e Initial load
duke
parents:
diff changeset
187 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
188 // Too large; allocate the object individually.
a61af66fc99e Initial load
duke
parents:
diff changeset
189 obj = sp->par_allocate(word_sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
190 }
a61af66fc99e Initial load
duke
parents:
diff changeset
191 }
a61af66fc99e Initial load
duke
parents:
diff changeset
192 return obj;
a61af66fc99e Initial load
duke
parents:
diff changeset
193 }
a61af66fc99e Initial load
duke
parents:
diff changeset
194
a61af66fc99e Initial load
duke
parents:
diff changeset
195
a61af66fc99e Initial load
duke
parents:
diff changeset
196 void ParScanThreadState::undo_alloc_in_to_space(HeapWord* obj,
a61af66fc99e Initial load
duke
parents:
diff changeset
197 size_t word_sz) {
a61af66fc99e Initial load
duke
parents:
diff changeset
198 // Is the alloc in the current alloc buffer?
a61af66fc99e Initial load
duke
parents:
diff changeset
199 if (to_space_alloc_buffer()->contains(obj)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
200 assert(to_space_alloc_buffer()->contains(obj + word_sz - 1),
a61af66fc99e Initial load
duke
parents:
diff changeset
201 "Should contain whole object.");
a61af66fc99e Initial load
duke
parents:
diff changeset
202 to_space_alloc_buffer()->undo_allocation(obj, word_sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
203 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
204 SharedHeap::fill_region_with_object(MemRegion(obj, word_sz));
a61af66fc99e Initial load
duke
parents:
diff changeset
205 }
a61af66fc99e Initial load
duke
parents:
diff changeset
206 }
a61af66fc99e Initial load
duke
parents:
diff changeset
207
a61af66fc99e Initial load
duke
parents:
diff changeset
208 class ParScanThreadStateSet: private ResourceArray {
a61af66fc99e Initial load
duke
parents:
diff changeset
209 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
210 // Initializes states for the specified number of threads;
a61af66fc99e Initial load
duke
parents:
diff changeset
211 ParScanThreadStateSet(int num_threads,
a61af66fc99e Initial load
duke
parents:
diff changeset
212 Space& to_space,
a61af66fc99e Initial load
duke
parents:
diff changeset
213 ParNewGeneration& gen,
a61af66fc99e Initial load
duke
parents:
diff changeset
214 Generation& old_gen,
a61af66fc99e Initial load
duke
parents:
diff changeset
215 ObjToScanQueueSet& queue_set,
a61af66fc99e Initial load
duke
parents:
diff changeset
216 size_t desired_plab_sz,
a61af66fc99e Initial load
duke
parents:
diff changeset
217 ParallelTaskTerminator& term);
a61af66fc99e Initial load
duke
parents:
diff changeset
218 inline ParScanThreadState& thread_sate(int i);
a61af66fc99e Initial load
duke
parents:
diff changeset
219 int pushes() { return _pushes; }
a61af66fc99e Initial load
duke
parents:
diff changeset
220 int pops() { return _pops; }
a61af66fc99e Initial load
duke
parents:
diff changeset
221 int steals() { return _steals; }
a61af66fc99e Initial load
duke
parents:
diff changeset
222 void reset();
a61af66fc99e Initial load
duke
parents:
diff changeset
223 void flush();
a61af66fc99e Initial load
duke
parents:
diff changeset
224 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
225 ParallelTaskTerminator& _term;
a61af66fc99e Initial load
duke
parents:
diff changeset
226 ParNewGeneration& _gen;
a61af66fc99e Initial load
duke
parents:
diff changeset
227 Generation& _next_gen;
a61af66fc99e Initial load
duke
parents:
diff changeset
228 // staticstics
a61af66fc99e Initial load
duke
parents:
diff changeset
229 int _pushes;
a61af66fc99e Initial load
duke
parents:
diff changeset
230 int _pops;
a61af66fc99e Initial load
duke
parents:
diff changeset
231 int _steals;
a61af66fc99e Initial load
duke
parents:
diff changeset
232 };
a61af66fc99e Initial load
duke
parents:
diff changeset
233
a61af66fc99e Initial load
duke
parents:
diff changeset
234
a61af66fc99e Initial load
duke
parents:
diff changeset
235 ParScanThreadStateSet::ParScanThreadStateSet(
a61af66fc99e Initial load
duke
parents:
diff changeset
236 int num_threads, Space& to_space, ParNewGeneration& gen,
a61af66fc99e Initial load
duke
parents:
diff changeset
237 Generation& old_gen, ObjToScanQueueSet& queue_set,
a61af66fc99e Initial load
duke
parents:
diff changeset
238 size_t desired_plab_sz, ParallelTaskTerminator& term)
a61af66fc99e Initial load
duke
parents:
diff changeset
239 : ResourceArray(sizeof(ParScanThreadState), num_threads),
a61af66fc99e Initial load
duke
parents:
diff changeset
240 _gen(gen), _next_gen(old_gen), _term(term),
a61af66fc99e Initial load
duke
parents:
diff changeset
241 _pushes(0), _pops(0), _steals(0)
a61af66fc99e Initial load
duke
parents:
diff changeset
242 {
a61af66fc99e Initial load
duke
parents:
diff changeset
243 assert(num_threads > 0, "sanity check!");
a61af66fc99e Initial load
duke
parents:
diff changeset
244 // Initialize states.
a61af66fc99e Initial load
duke
parents:
diff changeset
245 for (int i = 0; i < num_threads; ++i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
246 new ((ParScanThreadState*)_data + i)
a61af66fc99e Initial load
duke
parents:
diff changeset
247 ParScanThreadState(&to_space, &gen, &old_gen, i, &queue_set,
a61af66fc99e Initial load
duke
parents:
diff changeset
248 desired_plab_sz, term);
a61af66fc99e Initial load
duke
parents:
diff changeset
249 }
a61af66fc99e Initial load
duke
parents:
diff changeset
250 }
a61af66fc99e Initial load
duke
parents:
diff changeset
251
a61af66fc99e Initial load
duke
parents:
diff changeset
252 inline ParScanThreadState& ParScanThreadStateSet::thread_sate(int i)
a61af66fc99e Initial load
duke
parents:
diff changeset
253 {
a61af66fc99e Initial load
duke
parents:
diff changeset
254 assert(i >= 0 && i < length(), "sanity check!");
a61af66fc99e Initial load
duke
parents:
diff changeset
255 return ((ParScanThreadState*)_data)[i];
a61af66fc99e Initial load
duke
parents:
diff changeset
256 }
a61af66fc99e Initial load
duke
parents:
diff changeset
257
a61af66fc99e Initial load
duke
parents:
diff changeset
258
a61af66fc99e Initial load
duke
parents:
diff changeset
259 void ParScanThreadStateSet::reset()
a61af66fc99e Initial load
duke
parents:
diff changeset
260 {
a61af66fc99e Initial load
duke
parents:
diff changeset
261 _term.reset_for_reuse();
a61af66fc99e Initial load
duke
parents:
diff changeset
262 }
a61af66fc99e Initial load
duke
parents:
diff changeset
263
a61af66fc99e Initial load
duke
parents:
diff changeset
264 void ParScanThreadStateSet::flush()
a61af66fc99e Initial load
duke
parents:
diff changeset
265 {
a61af66fc99e Initial load
duke
parents:
diff changeset
266 for (int i = 0; i < length(); ++i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
267 ParScanThreadState& par_scan_state = thread_sate(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
268
a61af66fc99e Initial load
duke
parents:
diff changeset
269 // Flush stats related to To-space PLAB activity and
a61af66fc99e Initial load
duke
parents:
diff changeset
270 // retire the last buffer.
a61af66fc99e Initial load
duke
parents:
diff changeset
271 par_scan_state.to_space_alloc_buffer()->
a61af66fc99e Initial load
duke
parents:
diff changeset
272 flush_stats_and_retire(_gen.plab_stats(),
a61af66fc99e Initial load
duke
parents:
diff changeset
273 false /* !retain */);
a61af66fc99e Initial load
duke
parents:
diff changeset
274
a61af66fc99e Initial load
duke
parents:
diff changeset
275 // Every thread has its own age table. We need to merge
a61af66fc99e Initial load
duke
parents:
diff changeset
276 // them all into one.
a61af66fc99e Initial load
duke
parents:
diff changeset
277 ageTable *local_table = par_scan_state.age_table();
a61af66fc99e Initial load
duke
parents:
diff changeset
278 _gen.age_table()->merge(local_table);
a61af66fc99e Initial load
duke
parents:
diff changeset
279
a61af66fc99e Initial load
duke
parents:
diff changeset
280 // Inform old gen that we're done.
a61af66fc99e Initial load
duke
parents:
diff changeset
281 _next_gen.par_promote_alloc_done(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
282 _next_gen.par_oop_since_save_marks_iterate_done(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
283
a61af66fc99e Initial load
duke
parents:
diff changeset
284 // Flush stats related to work queue activity (push/pop/steal)
a61af66fc99e Initial load
duke
parents:
diff changeset
285 // This could conceivably become a bottleneck; if so, we'll put the
a61af66fc99e Initial load
duke
parents:
diff changeset
286 // stat's gathering under the flag.
a61af66fc99e Initial load
duke
parents:
diff changeset
287 if (PAR_STATS_ENABLED) {
a61af66fc99e Initial load
duke
parents:
diff changeset
288 _pushes += par_scan_state.pushes();
a61af66fc99e Initial load
duke
parents:
diff changeset
289 _pops += par_scan_state.pops();
a61af66fc99e Initial load
duke
parents:
diff changeset
290 _steals += par_scan_state.steals();
a61af66fc99e Initial load
duke
parents:
diff changeset
291 if (ParallelGCVerbose) {
a61af66fc99e Initial load
duke
parents:
diff changeset
292 gclog_or_tty->print("Thread %d complete:\n"
a61af66fc99e Initial load
duke
parents:
diff changeset
293 " Pushes: %7d Pops: %7d Steals %7d (in %d attempts)\n",
a61af66fc99e Initial load
duke
parents:
diff changeset
294 i, par_scan_state.pushes(), par_scan_state.pops(),
a61af66fc99e Initial load
duke
parents:
diff changeset
295 par_scan_state.steals(), par_scan_state.steal_attempts());
a61af66fc99e Initial load
duke
parents:
diff changeset
296 if (par_scan_state.overflow_pushes() > 0 ||
a61af66fc99e Initial load
duke
parents:
diff changeset
297 par_scan_state.overflow_refills() > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
298 gclog_or_tty->print(" Overflow pushes: %7d "
a61af66fc99e Initial load
duke
parents:
diff changeset
299 "Overflow refills: %7d for %d objs.\n",
a61af66fc99e Initial load
duke
parents:
diff changeset
300 par_scan_state.overflow_pushes(),
a61af66fc99e Initial load
duke
parents:
diff changeset
301 par_scan_state.overflow_refills(),
a61af66fc99e Initial load
duke
parents:
diff changeset
302 par_scan_state.overflow_refill_objs());
a61af66fc99e Initial load
duke
parents:
diff changeset
303 }
a61af66fc99e Initial load
duke
parents:
diff changeset
304
a61af66fc99e Initial load
duke
parents:
diff changeset
305 double elapsed = par_scan_state.elapsed();
a61af66fc99e Initial load
duke
parents:
diff changeset
306 double strong_roots = par_scan_state.strong_roots_time();
a61af66fc99e Initial load
duke
parents:
diff changeset
307 double term = par_scan_state.term_time();
a61af66fc99e Initial load
duke
parents:
diff changeset
308 gclog_or_tty->print(
a61af66fc99e Initial load
duke
parents:
diff changeset
309 " Elapsed: %7.2f ms.\n"
a61af66fc99e Initial load
duke
parents:
diff changeset
310 " Strong roots: %7.2f ms (%6.2f%%)\n"
a61af66fc99e Initial load
duke
parents:
diff changeset
311 " Termination: %7.2f ms (%6.2f%%) (in %d entries)\n",
a61af66fc99e Initial load
duke
parents:
diff changeset
312 elapsed * 1000.0,
a61af66fc99e Initial load
duke
parents:
diff changeset
313 strong_roots * 1000.0, (strong_roots*100.0/elapsed),
a61af66fc99e Initial load
duke
parents:
diff changeset
314 term * 1000.0, (term*100.0/elapsed),
a61af66fc99e Initial load
duke
parents:
diff changeset
315 par_scan_state.term_attempts());
a61af66fc99e Initial load
duke
parents:
diff changeset
316 }
a61af66fc99e Initial load
duke
parents:
diff changeset
317 }
a61af66fc99e Initial load
duke
parents:
diff changeset
318 }
a61af66fc99e Initial load
duke
parents:
diff changeset
319 }
a61af66fc99e Initial load
duke
parents:
diff changeset
320
a61af66fc99e Initial load
duke
parents:
diff changeset
321 ParScanClosure::ParScanClosure(ParNewGeneration* g,
a61af66fc99e Initial load
duke
parents:
diff changeset
322 ParScanThreadState* par_scan_state) :
a61af66fc99e Initial load
duke
parents:
diff changeset
323 OopsInGenClosure(g), _par_scan_state(par_scan_state), _g(g)
a61af66fc99e Initial load
duke
parents:
diff changeset
324 {
a61af66fc99e Initial load
duke
parents:
diff changeset
325 assert(_g->level() == 0, "Optimized for youngest generation");
a61af66fc99e Initial load
duke
parents:
diff changeset
326 _boundary = _g->reserved().end();
a61af66fc99e Initial load
duke
parents:
diff changeset
327 }
a61af66fc99e Initial load
duke
parents:
diff changeset
328
113
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
329 void ParScanWithBarrierClosure::do_oop(oop* p) { ParScanClosure::do_oop_work(p, true, false); }
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
330 void ParScanWithBarrierClosure::do_oop(narrowOop* p) { ParScanClosure::do_oop_work(p, true, false); }
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
331
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
332 void ParScanWithoutBarrierClosure::do_oop(oop* p) { ParScanClosure::do_oop_work(p, false, false); }
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
333 void ParScanWithoutBarrierClosure::do_oop(narrowOop* p) { ParScanClosure::do_oop_work(p, false, false); }
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
334
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
335 void ParRootScanWithBarrierTwoGensClosure::do_oop(oop* p) { ParScanClosure::do_oop_work(p, true, true); }
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
336 void ParRootScanWithBarrierTwoGensClosure::do_oop(narrowOop* p) { ParScanClosure::do_oop_work(p, true, true); }
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
337
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
338 void ParRootScanWithoutBarrierClosure::do_oop(oop* p) { ParScanClosure::do_oop_work(p, false, true); }
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
339 void ParRootScanWithoutBarrierClosure::do_oop(narrowOop* p) { ParScanClosure::do_oop_work(p, false, true); }
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
340
0
a61af66fc99e Initial load
duke
parents:
diff changeset
341 ParScanWeakRefClosure::ParScanWeakRefClosure(ParNewGeneration* g,
a61af66fc99e Initial load
duke
parents:
diff changeset
342 ParScanThreadState* par_scan_state)
a61af66fc99e Initial load
duke
parents:
diff changeset
343 : ScanWeakRefClosure(g), _par_scan_state(par_scan_state)
113
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
344 {}
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
345
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
346 void ParScanWeakRefClosure::do_oop(oop* p) { ParScanWeakRefClosure::do_oop_work(p); }
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
347 void ParScanWeakRefClosure::do_oop(narrowOop* p) { ParScanWeakRefClosure::do_oop_work(p); }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
348
a61af66fc99e Initial load
duke
parents:
diff changeset
349 #ifdef WIN32
a61af66fc99e Initial load
duke
parents:
diff changeset
350 #pragma warning(disable: 4786) /* identifier was truncated to '255' characters in the browser information */
a61af66fc99e Initial load
duke
parents:
diff changeset
351 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
352
a61af66fc99e Initial load
duke
parents:
diff changeset
353 ParEvacuateFollowersClosure::ParEvacuateFollowersClosure(
a61af66fc99e Initial load
duke
parents:
diff changeset
354 ParScanThreadState* par_scan_state_,
a61af66fc99e Initial load
duke
parents:
diff changeset
355 ParScanWithoutBarrierClosure* to_space_closure_,
a61af66fc99e Initial load
duke
parents:
diff changeset
356 ParScanWithBarrierClosure* old_gen_closure_,
a61af66fc99e Initial load
duke
parents:
diff changeset
357 ParRootScanWithoutBarrierClosure* to_space_root_closure_,
a61af66fc99e Initial load
duke
parents:
diff changeset
358 ParNewGeneration* par_gen_,
a61af66fc99e Initial load
duke
parents:
diff changeset
359 ParRootScanWithBarrierTwoGensClosure* old_gen_root_closure_,
a61af66fc99e Initial load
duke
parents:
diff changeset
360 ObjToScanQueueSet* task_queues_,
a61af66fc99e Initial load
duke
parents:
diff changeset
361 ParallelTaskTerminator* terminator_) :
a61af66fc99e Initial load
duke
parents:
diff changeset
362
a61af66fc99e Initial load
duke
parents:
diff changeset
363 _par_scan_state(par_scan_state_),
a61af66fc99e Initial load
duke
parents:
diff changeset
364 _to_space_closure(to_space_closure_),
a61af66fc99e Initial load
duke
parents:
diff changeset
365 _old_gen_closure(old_gen_closure_),
a61af66fc99e Initial load
duke
parents:
diff changeset
366 _to_space_root_closure(to_space_root_closure_),
a61af66fc99e Initial load
duke
parents:
diff changeset
367 _old_gen_root_closure(old_gen_root_closure_),
a61af66fc99e Initial load
duke
parents:
diff changeset
368 _par_gen(par_gen_),
a61af66fc99e Initial load
duke
parents:
diff changeset
369 _task_queues(task_queues_),
a61af66fc99e Initial load
duke
parents:
diff changeset
370 _terminator(terminator_)
a61af66fc99e Initial load
duke
parents:
diff changeset
371 {}
a61af66fc99e Initial load
duke
parents:
diff changeset
372
a61af66fc99e Initial load
duke
parents:
diff changeset
373 void ParEvacuateFollowersClosure::do_void() {
a61af66fc99e Initial load
duke
parents:
diff changeset
374 ObjToScanQueue* work_q = par_scan_state()->work_queue();
a61af66fc99e Initial load
duke
parents:
diff changeset
375
a61af66fc99e Initial load
duke
parents:
diff changeset
376 while (true) {
a61af66fc99e Initial load
duke
parents:
diff changeset
377
a61af66fc99e Initial load
duke
parents:
diff changeset
378 // Scan to-space and old-gen objs until we run out of both.
a61af66fc99e Initial load
duke
parents:
diff changeset
379 oop obj_to_scan;
a61af66fc99e Initial load
duke
parents:
diff changeset
380 par_scan_state()->trim_queues(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
381
a61af66fc99e Initial load
duke
parents:
diff changeset
382 // We have no local work, attempt to steal from other threads.
a61af66fc99e Initial load
duke
parents:
diff changeset
383
a61af66fc99e Initial load
duke
parents:
diff changeset
384 // attempt to steal work from promoted.
a61af66fc99e Initial load
duke
parents:
diff changeset
385 par_scan_state()->note_steal_attempt();
a61af66fc99e Initial load
duke
parents:
diff changeset
386 if (task_queues()->steal(par_scan_state()->thread_num(),
a61af66fc99e Initial load
duke
parents:
diff changeset
387 par_scan_state()->hash_seed(),
a61af66fc99e Initial load
duke
parents:
diff changeset
388 obj_to_scan)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
389 par_scan_state()->note_steal();
a61af66fc99e Initial load
duke
parents:
diff changeset
390 bool res = work_q->push(obj_to_scan);
a61af66fc99e Initial load
duke
parents:
diff changeset
391 assert(res, "Empty queue should have room for a push.");
a61af66fc99e Initial load
duke
parents:
diff changeset
392
a61af66fc99e Initial load
duke
parents:
diff changeset
393 par_scan_state()->note_push();
a61af66fc99e Initial load
duke
parents:
diff changeset
394 // if successful, goto Start.
a61af66fc99e Initial load
duke
parents:
diff changeset
395 continue;
a61af66fc99e Initial load
duke
parents:
diff changeset
396
a61af66fc99e Initial load
duke
parents:
diff changeset
397 // try global overflow list.
a61af66fc99e Initial load
duke
parents:
diff changeset
398 } else if (par_gen()->take_from_overflow_list(par_scan_state())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
399 continue;
a61af66fc99e Initial load
duke
parents:
diff changeset
400 }
a61af66fc99e Initial load
duke
parents:
diff changeset
401
a61af66fc99e Initial load
duke
parents:
diff changeset
402 // Otherwise, offer termination.
a61af66fc99e Initial load
duke
parents:
diff changeset
403 par_scan_state()->start_term_time();
a61af66fc99e Initial load
duke
parents:
diff changeset
404 if (terminator()->offer_termination()) break;
a61af66fc99e Initial load
duke
parents:
diff changeset
405 par_scan_state()->end_term_time();
a61af66fc99e Initial load
duke
parents:
diff changeset
406 }
a61af66fc99e Initial load
duke
parents:
diff changeset
407 // Finish the last termination pause.
a61af66fc99e Initial load
duke
parents:
diff changeset
408 par_scan_state()->end_term_time();
a61af66fc99e Initial load
duke
parents:
diff changeset
409 }
a61af66fc99e Initial load
duke
parents:
diff changeset
410
a61af66fc99e Initial load
duke
parents:
diff changeset
411 ParNewGenTask::ParNewGenTask(ParNewGeneration* gen, Generation* next_gen,
a61af66fc99e Initial load
duke
parents:
diff changeset
412 HeapWord* young_old_boundary, ParScanThreadStateSet* state_set) :
a61af66fc99e Initial load
duke
parents:
diff changeset
413 AbstractGangTask("ParNewGeneration collection"),
a61af66fc99e Initial load
duke
parents:
diff changeset
414 _gen(gen), _next_gen(next_gen),
a61af66fc99e Initial load
duke
parents:
diff changeset
415 _young_old_boundary(young_old_boundary),
a61af66fc99e Initial load
duke
parents:
diff changeset
416 _state_set(state_set)
a61af66fc99e Initial load
duke
parents:
diff changeset
417 {}
a61af66fc99e Initial load
duke
parents:
diff changeset
418
a61af66fc99e Initial load
duke
parents:
diff changeset
419 void ParNewGenTask::work(int i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
420 GenCollectedHeap* gch = GenCollectedHeap::heap();
a61af66fc99e Initial load
duke
parents:
diff changeset
421 // Since this is being done in a separate thread, need new resource
a61af66fc99e Initial load
duke
parents:
diff changeset
422 // and handle marks.
a61af66fc99e Initial load
duke
parents:
diff changeset
423 ResourceMark rm;
a61af66fc99e Initial load
duke
parents:
diff changeset
424 HandleMark hm;
a61af66fc99e Initial load
duke
parents:
diff changeset
425 // We would need multiple old-gen queues otherwise.
a61af66fc99e Initial load
duke
parents:
diff changeset
426 guarantee(gch->n_gens() == 2,
a61af66fc99e Initial load
duke
parents:
diff changeset
427 "Par young collection currently only works with one older gen.");
a61af66fc99e Initial load
duke
parents:
diff changeset
428
a61af66fc99e Initial load
duke
parents:
diff changeset
429 Generation* old_gen = gch->next_gen(_gen);
a61af66fc99e Initial load
duke
parents:
diff changeset
430
a61af66fc99e Initial load
duke
parents:
diff changeset
431 ParScanThreadState& par_scan_state = _state_set->thread_sate(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
432 par_scan_state.set_young_old_boundary(_young_old_boundary);
a61af66fc99e Initial load
duke
parents:
diff changeset
433
a61af66fc99e Initial load
duke
parents:
diff changeset
434 par_scan_state.start_strong_roots();
a61af66fc99e Initial load
duke
parents:
diff changeset
435 gch->gen_process_strong_roots(_gen->level(),
a61af66fc99e Initial load
duke
parents:
diff changeset
436 true, // Process younger gens, if any,
a61af66fc99e Initial load
duke
parents:
diff changeset
437 // as strong roots.
a61af66fc99e Initial load
duke
parents:
diff changeset
438 false,// not collecting perm generation.
a61af66fc99e Initial load
duke
parents:
diff changeset
439 SharedHeap::SO_AllClasses,
a61af66fc99e Initial load
duke
parents:
diff changeset
440 &par_scan_state.older_gen_closure(),
a61af66fc99e Initial load
duke
parents:
diff changeset
441 &par_scan_state.to_space_root_closure());
a61af66fc99e Initial load
duke
parents:
diff changeset
442 par_scan_state.end_strong_roots();
a61af66fc99e Initial load
duke
parents:
diff changeset
443
a61af66fc99e Initial load
duke
parents:
diff changeset
444 // "evacuate followers".
a61af66fc99e Initial load
duke
parents:
diff changeset
445 par_scan_state.evacuate_followers_closure().do_void();
a61af66fc99e Initial load
duke
parents:
diff changeset
446 }
a61af66fc99e Initial load
duke
parents:
diff changeset
447
a61af66fc99e Initial load
duke
parents:
diff changeset
448 #ifdef _MSC_VER
a61af66fc99e Initial load
duke
parents:
diff changeset
449 #pragma warning( push )
a61af66fc99e Initial load
duke
parents:
diff changeset
450 #pragma warning( disable:4355 ) // 'this' : used in base member initializer list
a61af66fc99e Initial load
duke
parents:
diff changeset
451 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
452 ParNewGeneration::
a61af66fc99e Initial load
duke
parents:
diff changeset
453 ParNewGeneration(ReservedSpace rs, size_t initial_byte_size, int level)
a61af66fc99e Initial load
duke
parents:
diff changeset
454 : DefNewGeneration(rs, initial_byte_size, level, "PCopy"),
a61af66fc99e Initial load
duke
parents:
diff changeset
455 _overflow_list(NULL),
a61af66fc99e Initial load
duke
parents:
diff changeset
456 _is_alive_closure(this),
a61af66fc99e Initial load
duke
parents:
diff changeset
457 _plab_stats(YoungPLABSize, PLABWeight)
a61af66fc99e Initial load
duke
parents:
diff changeset
458 {
a61af66fc99e Initial load
duke
parents:
diff changeset
459 _task_queues = new ObjToScanQueueSet(ParallelGCThreads);
a61af66fc99e Initial load
duke
parents:
diff changeset
460 guarantee(_task_queues != NULL, "task_queues allocation failure.");
a61af66fc99e Initial load
duke
parents:
diff changeset
461
a61af66fc99e Initial load
duke
parents:
diff changeset
462 for (uint i1 = 0; i1 < ParallelGCThreads; i1++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
463 ObjToScanQueuePadded *q_padded = new ObjToScanQueuePadded();
a61af66fc99e Initial load
duke
parents:
diff changeset
464 guarantee(q_padded != NULL, "work_queue Allocation failure.");
a61af66fc99e Initial load
duke
parents:
diff changeset
465
a61af66fc99e Initial load
duke
parents:
diff changeset
466 _task_queues->register_queue(i1, &q_padded->work_queue);
a61af66fc99e Initial load
duke
parents:
diff changeset
467 }
a61af66fc99e Initial load
duke
parents:
diff changeset
468
a61af66fc99e Initial load
duke
parents:
diff changeset
469 for (uint i2 = 0; i2 < ParallelGCThreads; i2++)
a61af66fc99e Initial load
duke
parents:
diff changeset
470 _task_queues->queue(i2)->initialize();
a61af66fc99e Initial load
duke
parents:
diff changeset
471
a61af66fc99e Initial load
duke
parents:
diff changeset
472 if (UsePerfData) {
a61af66fc99e Initial load
duke
parents:
diff changeset
473 EXCEPTION_MARK;
a61af66fc99e Initial load
duke
parents:
diff changeset
474 ResourceMark rm;
a61af66fc99e Initial load
duke
parents:
diff changeset
475
a61af66fc99e Initial load
duke
parents:
diff changeset
476 const char* cname =
a61af66fc99e Initial load
duke
parents:
diff changeset
477 PerfDataManager::counter_name(_gen_counters->name_space(), "threads");
a61af66fc99e Initial load
duke
parents:
diff changeset
478 PerfDataManager::create_constant(SUN_GC, cname, PerfData::U_None,
a61af66fc99e Initial load
duke
parents:
diff changeset
479 ParallelGCThreads, CHECK);
a61af66fc99e Initial load
duke
parents:
diff changeset
480 }
a61af66fc99e Initial load
duke
parents:
diff changeset
481 }
a61af66fc99e Initial load
duke
parents:
diff changeset
482 #ifdef _MSC_VER
a61af66fc99e Initial load
duke
parents:
diff changeset
483 #pragma warning( pop )
a61af66fc99e Initial load
duke
parents:
diff changeset
484 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
485
a61af66fc99e Initial load
duke
parents:
diff changeset
486 // ParNewGeneration::
a61af66fc99e Initial load
duke
parents:
diff changeset
487 ParKeepAliveClosure::ParKeepAliveClosure(ParScanWeakRefClosure* cl) :
a61af66fc99e Initial load
duke
parents:
diff changeset
488 DefNewGeneration::KeepAliveClosure(cl), _par_cl(cl) {}
a61af66fc99e Initial load
duke
parents:
diff changeset
489
113
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
490 template <class T>
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
491 void /*ParNewGeneration::*/ParKeepAliveClosure::do_oop_work(T* p) {
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
492 #ifdef ASSERT
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
493 {
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
494 assert(!oopDesc::is_null(*p), "expected non-null ref");
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
495 oop obj = oopDesc::load_decode_heap_oop_not_null(p);
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
496 // We never expect to see a null reference being processed
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
497 // as a weak reference.
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
498 assert(obj->is_oop(), "expected an oop while scanning weak refs");
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
499 }
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
500 #endif // ASSERT
0
a61af66fc99e Initial load
duke
parents:
diff changeset
501
a61af66fc99e Initial load
duke
parents:
diff changeset
502 _par_cl->do_oop_nv(p);
a61af66fc99e Initial load
duke
parents:
diff changeset
503
a61af66fc99e Initial load
duke
parents:
diff changeset
504 if (Universe::heap()->is_in_reserved(p)) {
113
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
505 oop obj = oopDesc::load_decode_heap_oop_not_null(p);
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
506 _rs->write_ref_field_gc_par(p, obj);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
507 }
a61af66fc99e Initial load
duke
parents:
diff changeset
508 }
a61af66fc99e Initial load
duke
parents:
diff changeset
509
113
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
510 void /*ParNewGeneration::*/ParKeepAliveClosure::do_oop(oop* p) { ParKeepAliveClosure::do_oop_work(p); }
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
511 void /*ParNewGeneration::*/ParKeepAliveClosure::do_oop(narrowOop* p) { ParKeepAliveClosure::do_oop_work(p); }
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
512
0
a61af66fc99e Initial load
duke
parents:
diff changeset
513 // ParNewGeneration::
a61af66fc99e Initial load
duke
parents:
diff changeset
514 KeepAliveClosure::KeepAliveClosure(ScanWeakRefClosure* cl) :
a61af66fc99e Initial load
duke
parents:
diff changeset
515 DefNewGeneration::KeepAliveClosure(cl) {}
a61af66fc99e Initial load
duke
parents:
diff changeset
516
113
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
517 template <class T>
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
518 void /*ParNewGeneration::*/KeepAliveClosure::do_oop_work(T* p) {
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
519 #ifdef ASSERT
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
520 {
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
521 assert(!oopDesc::is_null(*p), "expected non-null ref");
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
522 oop obj = oopDesc::load_decode_heap_oop_not_null(p);
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
523 // We never expect to see a null reference being processed
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
524 // as a weak reference.
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
525 assert(obj->is_oop(), "expected an oop while scanning weak refs");
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
526 }
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
527 #endif // ASSERT
0
a61af66fc99e Initial load
duke
parents:
diff changeset
528
a61af66fc99e Initial load
duke
parents:
diff changeset
529 _cl->do_oop_nv(p);
a61af66fc99e Initial load
duke
parents:
diff changeset
530
a61af66fc99e Initial load
duke
parents:
diff changeset
531 if (Universe::heap()->is_in_reserved(p)) {
113
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
532 oop obj = oopDesc::load_decode_heap_oop_not_null(p);
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
533 _rs->write_ref_field_gc_par(p, obj);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
534 }
a61af66fc99e Initial load
duke
parents:
diff changeset
535 }
a61af66fc99e Initial load
duke
parents:
diff changeset
536
113
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
537 void /*ParNewGeneration::*/KeepAliveClosure::do_oop(oop* p) { KeepAliveClosure::do_oop_work(p); }
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
538 void /*ParNewGeneration::*/KeepAliveClosure::do_oop(narrowOop* p) { KeepAliveClosure::do_oop_work(p); }
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
539
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
540 template <class T> void ScanClosureWithParBarrier::do_oop_work(T* p) {
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
541 T heap_oop = oopDesc::load_heap_oop(p);
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
542 if (!oopDesc::is_null(heap_oop)) {
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
543 oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
544 if ((HeapWord*)obj < _boundary) {
a61af66fc99e Initial load
duke
parents:
diff changeset
545 assert(!_g->to()->is_in_reserved(obj), "Scanning field twice?");
113
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
546 oop new_obj = obj->is_forwarded()
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
547 ? obj->forwardee()
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
548 : _g->DefNewGeneration::copy_to_survivor_space(obj);
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
549 oopDesc::encode_store_heap_oop_not_null(p, new_obj);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
550 }
a61af66fc99e Initial load
duke
parents:
diff changeset
551 if (_gc_barrier) {
a61af66fc99e Initial load
duke
parents:
diff changeset
552 // If p points to a younger generation, mark the card.
a61af66fc99e Initial load
duke
parents:
diff changeset
553 if ((HeapWord*)obj < _gen_boundary) {
a61af66fc99e Initial load
duke
parents:
diff changeset
554 _rs->write_ref_field_gc_par(p, obj);
a61af66fc99e Initial load
duke
parents:
diff changeset
555 }
a61af66fc99e Initial load
duke
parents:
diff changeset
556 }
a61af66fc99e Initial load
duke
parents:
diff changeset
557 }
a61af66fc99e Initial load
duke
parents:
diff changeset
558 }
a61af66fc99e Initial load
duke
parents:
diff changeset
559
113
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
560 void ScanClosureWithParBarrier::do_oop(oop* p) { ScanClosureWithParBarrier::do_oop_work(p); }
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
561 void ScanClosureWithParBarrier::do_oop(narrowOop* p) { ScanClosureWithParBarrier::do_oop_work(p); }
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
562
0
a61af66fc99e Initial load
duke
parents:
diff changeset
563 class ParNewRefProcTaskProxy: public AbstractGangTask {
a61af66fc99e Initial load
duke
parents:
diff changeset
564 typedef AbstractRefProcTaskExecutor::ProcessTask ProcessTask;
a61af66fc99e Initial load
duke
parents:
diff changeset
565 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
566 ParNewRefProcTaskProxy(ProcessTask& task, ParNewGeneration& gen,
a61af66fc99e Initial load
duke
parents:
diff changeset
567 Generation& next_gen,
a61af66fc99e Initial load
duke
parents:
diff changeset
568 HeapWord* young_old_boundary,
a61af66fc99e Initial load
duke
parents:
diff changeset
569 ParScanThreadStateSet& state_set);
a61af66fc99e Initial load
duke
parents:
diff changeset
570
a61af66fc99e Initial load
duke
parents:
diff changeset
571 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
572 virtual void work(int i);
a61af66fc99e Initial load
duke
parents:
diff changeset
573
a61af66fc99e Initial load
duke
parents:
diff changeset
574 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
575 ParNewGeneration& _gen;
a61af66fc99e Initial load
duke
parents:
diff changeset
576 ProcessTask& _task;
a61af66fc99e Initial load
duke
parents:
diff changeset
577 Generation& _next_gen;
a61af66fc99e Initial load
duke
parents:
diff changeset
578 HeapWord* _young_old_boundary;
a61af66fc99e Initial load
duke
parents:
diff changeset
579 ParScanThreadStateSet& _state_set;
a61af66fc99e Initial load
duke
parents:
diff changeset
580 };
a61af66fc99e Initial load
duke
parents:
diff changeset
581
a61af66fc99e Initial load
duke
parents:
diff changeset
582 ParNewRefProcTaskProxy::ParNewRefProcTaskProxy(
a61af66fc99e Initial load
duke
parents:
diff changeset
583 ProcessTask& task, ParNewGeneration& gen,
a61af66fc99e Initial load
duke
parents:
diff changeset
584 Generation& next_gen,
a61af66fc99e Initial load
duke
parents:
diff changeset
585 HeapWord* young_old_boundary,
a61af66fc99e Initial load
duke
parents:
diff changeset
586 ParScanThreadStateSet& state_set)
a61af66fc99e Initial load
duke
parents:
diff changeset
587 : AbstractGangTask("ParNewGeneration parallel reference processing"),
a61af66fc99e Initial load
duke
parents:
diff changeset
588 _gen(gen),
a61af66fc99e Initial load
duke
parents:
diff changeset
589 _task(task),
a61af66fc99e Initial load
duke
parents:
diff changeset
590 _next_gen(next_gen),
a61af66fc99e Initial load
duke
parents:
diff changeset
591 _young_old_boundary(young_old_boundary),
a61af66fc99e Initial load
duke
parents:
diff changeset
592 _state_set(state_set)
a61af66fc99e Initial load
duke
parents:
diff changeset
593 {
a61af66fc99e Initial load
duke
parents:
diff changeset
594 }
a61af66fc99e Initial load
duke
parents:
diff changeset
595
a61af66fc99e Initial load
duke
parents:
diff changeset
596 void ParNewRefProcTaskProxy::work(int i)
a61af66fc99e Initial load
duke
parents:
diff changeset
597 {
a61af66fc99e Initial load
duke
parents:
diff changeset
598 ResourceMark rm;
a61af66fc99e Initial load
duke
parents:
diff changeset
599 HandleMark hm;
a61af66fc99e Initial load
duke
parents:
diff changeset
600 ParScanThreadState& par_scan_state = _state_set.thread_sate(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
601 par_scan_state.set_young_old_boundary(_young_old_boundary);
a61af66fc99e Initial load
duke
parents:
diff changeset
602 _task.work(i, par_scan_state.is_alive_closure(),
a61af66fc99e Initial load
duke
parents:
diff changeset
603 par_scan_state.keep_alive_closure(),
a61af66fc99e Initial load
duke
parents:
diff changeset
604 par_scan_state.evacuate_followers_closure());
a61af66fc99e Initial load
duke
parents:
diff changeset
605 }
a61af66fc99e Initial load
duke
parents:
diff changeset
606
a61af66fc99e Initial load
duke
parents:
diff changeset
607 class ParNewRefEnqueueTaskProxy: public AbstractGangTask {
a61af66fc99e Initial load
duke
parents:
diff changeset
608 typedef AbstractRefProcTaskExecutor::EnqueueTask EnqueueTask;
a61af66fc99e Initial load
duke
parents:
diff changeset
609 EnqueueTask& _task;
a61af66fc99e Initial load
duke
parents:
diff changeset
610
a61af66fc99e Initial load
duke
parents:
diff changeset
611 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
612 ParNewRefEnqueueTaskProxy(EnqueueTask& task)
a61af66fc99e Initial load
duke
parents:
diff changeset
613 : AbstractGangTask("ParNewGeneration parallel reference enqueue"),
a61af66fc99e Initial load
duke
parents:
diff changeset
614 _task(task)
a61af66fc99e Initial load
duke
parents:
diff changeset
615 { }
a61af66fc99e Initial load
duke
parents:
diff changeset
616
a61af66fc99e Initial load
duke
parents:
diff changeset
617 virtual void work(int i)
a61af66fc99e Initial load
duke
parents:
diff changeset
618 {
a61af66fc99e Initial load
duke
parents:
diff changeset
619 _task.work(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
620 }
a61af66fc99e Initial load
duke
parents:
diff changeset
621 };
a61af66fc99e Initial load
duke
parents:
diff changeset
622
a61af66fc99e Initial load
duke
parents:
diff changeset
623
a61af66fc99e Initial load
duke
parents:
diff changeset
624 void ParNewRefProcTaskExecutor::execute(ProcessTask& task)
a61af66fc99e Initial load
duke
parents:
diff changeset
625 {
a61af66fc99e Initial load
duke
parents:
diff changeset
626 GenCollectedHeap* gch = GenCollectedHeap::heap();
a61af66fc99e Initial load
duke
parents:
diff changeset
627 assert(gch->kind() == CollectedHeap::GenCollectedHeap,
a61af66fc99e Initial load
duke
parents:
diff changeset
628 "not a generational heap");
a61af66fc99e Initial load
duke
parents:
diff changeset
629 WorkGang* workers = gch->workers();
a61af66fc99e Initial load
duke
parents:
diff changeset
630 assert(workers != NULL, "Need parallel worker threads.");
a61af66fc99e Initial load
duke
parents:
diff changeset
631 ParNewRefProcTaskProxy rp_task(task, _generation, *_generation.next_gen(),
a61af66fc99e Initial load
duke
parents:
diff changeset
632 _generation.reserved().end(), _state_set);
a61af66fc99e Initial load
duke
parents:
diff changeset
633 workers->run_task(&rp_task);
a61af66fc99e Initial load
duke
parents:
diff changeset
634 _state_set.reset();
a61af66fc99e Initial load
duke
parents:
diff changeset
635 }
a61af66fc99e Initial load
duke
parents:
diff changeset
636
a61af66fc99e Initial load
duke
parents:
diff changeset
637 void ParNewRefProcTaskExecutor::execute(EnqueueTask& task)
a61af66fc99e Initial load
duke
parents:
diff changeset
638 {
a61af66fc99e Initial load
duke
parents:
diff changeset
639 GenCollectedHeap* gch = GenCollectedHeap::heap();
a61af66fc99e Initial load
duke
parents:
diff changeset
640 WorkGang* workers = gch->workers();
a61af66fc99e Initial load
duke
parents:
diff changeset
641 assert(workers != NULL, "Need parallel worker threads.");
a61af66fc99e Initial load
duke
parents:
diff changeset
642 ParNewRefEnqueueTaskProxy enq_task(task);
a61af66fc99e Initial load
duke
parents:
diff changeset
643 workers->run_task(&enq_task);
a61af66fc99e Initial load
duke
parents:
diff changeset
644 }
a61af66fc99e Initial load
duke
parents:
diff changeset
645
a61af66fc99e Initial load
duke
parents:
diff changeset
646 void ParNewRefProcTaskExecutor::set_single_threaded_mode()
a61af66fc99e Initial load
duke
parents:
diff changeset
647 {
a61af66fc99e Initial load
duke
parents:
diff changeset
648 _state_set.flush();
a61af66fc99e Initial load
duke
parents:
diff changeset
649 GenCollectedHeap* gch = GenCollectedHeap::heap();
a61af66fc99e Initial load
duke
parents:
diff changeset
650 gch->set_par_threads(0); // 0 ==> non-parallel.
a61af66fc99e Initial load
duke
parents:
diff changeset
651 gch->save_marks();
a61af66fc99e Initial load
duke
parents:
diff changeset
652 }
a61af66fc99e Initial load
duke
parents:
diff changeset
653
a61af66fc99e Initial load
duke
parents:
diff changeset
654 ScanClosureWithParBarrier::
a61af66fc99e Initial load
duke
parents:
diff changeset
655 ScanClosureWithParBarrier(ParNewGeneration* g, bool gc_barrier) :
a61af66fc99e Initial load
duke
parents:
diff changeset
656 ScanClosure(g, gc_barrier) {}
a61af66fc99e Initial load
duke
parents:
diff changeset
657
a61af66fc99e Initial load
duke
parents:
diff changeset
658 EvacuateFollowersClosureGeneral::
a61af66fc99e Initial load
duke
parents:
diff changeset
659 EvacuateFollowersClosureGeneral(GenCollectedHeap* gch, int level,
a61af66fc99e Initial load
duke
parents:
diff changeset
660 OopsInGenClosure* cur,
a61af66fc99e Initial load
duke
parents:
diff changeset
661 OopsInGenClosure* older) :
a61af66fc99e Initial load
duke
parents:
diff changeset
662 _gch(gch), _level(level),
a61af66fc99e Initial load
duke
parents:
diff changeset
663 _scan_cur_or_nonheap(cur), _scan_older(older)
a61af66fc99e Initial load
duke
parents:
diff changeset
664 {}
a61af66fc99e Initial load
duke
parents:
diff changeset
665
a61af66fc99e Initial load
duke
parents:
diff changeset
666 void EvacuateFollowersClosureGeneral::do_void() {
a61af66fc99e Initial load
duke
parents:
diff changeset
667 do {
a61af66fc99e Initial load
duke
parents:
diff changeset
668 // Beware: this call will lead to closure applications via virtual
a61af66fc99e Initial load
duke
parents:
diff changeset
669 // calls.
a61af66fc99e Initial load
duke
parents:
diff changeset
670 _gch->oop_since_save_marks_iterate(_level,
a61af66fc99e Initial load
duke
parents:
diff changeset
671 _scan_cur_or_nonheap,
a61af66fc99e Initial load
duke
parents:
diff changeset
672 _scan_older);
a61af66fc99e Initial load
duke
parents:
diff changeset
673 } while (!_gch->no_allocs_since_save_marks(_level));
a61af66fc99e Initial load
duke
parents:
diff changeset
674 }
a61af66fc99e Initial load
duke
parents:
diff changeset
675
a61af66fc99e Initial load
duke
parents:
diff changeset
676
a61af66fc99e Initial load
duke
parents:
diff changeset
677 bool ParNewGeneration::_avoid_promotion_undo = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
678
a61af66fc99e Initial load
duke
parents:
diff changeset
679 void ParNewGeneration::adjust_desired_tenuring_threshold() {
a61af66fc99e Initial load
duke
parents:
diff changeset
680 // Set the desired survivor size to half the real survivor space
a61af66fc99e Initial load
duke
parents:
diff changeset
681 _tenuring_threshold =
a61af66fc99e Initial load
duke
parents:
diff changeset
682 age_table()->compute_tenuring_threshold(to()->capacity()/HeapWordSize);
a61af66fc99e Initial load
duke
parents:
diff changeset
683 }
a61af66fc99e Initial load
duke
parents:
diff changeset
684
a61af66fc99e Initial load
duke
parents:
diff changeset
685 // A Generation that does parallel young-gen collection.
a61af66fc99e Initial load
duke
parents:
diff changeset
686
a61af66fc99e Initial load
duke
parents:
diff changeset
687 void ParNewGeneration::collect(bool full,
a61af66fc99e Initial load
duke
parents:
diff changeset
688 bool clear_all_soft_refs,
a61af66fc99e Initial load
duke
parents:
diff changeset
689 size_t size,
a61af66fc99e Initial load
duke
parents:
diff changeset
690 bool is_tlab) {
a61af66fc99e Initial load
duke
parents:
diff changeset
691 assert(full || size > 0, "otherwise we don't want to collect");
a61af66fc99e Initial load
duke
parents:
diff changeset
692 GenCollectedHeap* gch = GenCollectedHeap::heap();
a61af66fc99e Initial load
duke
parents:
diff changeset
693 assert(gch->kind() == CollectedHeap::GenCollectedHeap,
a61af66fc99e Initial load
duke
parents:
diff changeset
694 "not a CMS generational heap");
a61af66fc99e Initial load
duke
parents:
diff changeset
695 AdaptiveSizePolicy* size_policy = gch->gen_policy()->size_policy();
a61af66fc99e Initial load
duke
parents:
diff changeset
696 WorkGang* workers = gch->workers();
a61af66fc99e Initial load
duke
parents:
diff changeset
697 _next_gen = gch->next_gen(this);
a61af66fc99e Initial load
duke
parents:
diff changeset
698 assert(_next_gen != NULL,
a61af66fc99e Initial load
duke
parents:
diff changeset
699 "This must be the youngest gen, and not the only gen");
a61af66fc99e Initial load
duke
parents:
diff changeset
700 assert(gch->n_gens() == 2,
a61af66fc99e Initial load
duke
parents:
diff changeset
701 "Par collection currently only works with single older gen.");
a61af66fc99e Initial load
duke
parents:
diff changeset
702 // Do we have to avoid promotion_undo?
a61af66fc99e Initial load
duke
parents:
diff changeset
703 if (gch->collector_policy()->is_concurrent_mark_sweep_policy()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
704 set_avoid_promotion_undo(true);
a61af66fc99e Initial load
duke
parents:
diff changeset
705 }
a61af66fc99e Initial load
duke
parents:
diff changeset
706
a61af66fc99e Initial load
duke
parents:
diff changeset
707 // If the next generation is too full to accomodate worst-case promotion
a61af66fc99e Initial load
duke
parents:
diff changeset
708 // from this generation, pass on collection; let the next generation
a61af66fc99e Initial load
duke
parents:
diff changeset
709 // do it.
a61af66fc99e Initial load
duke
parents:
diff changeset
710 if (!collection_attempt_is_safe()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
711 gch->set_incremental_collection_will_fail();
a61af66fc99e Initial load
duke
parents:
diff changeset
712 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
713 }
a61af66fc99e Initial load
duke
parents:
diff changeset
714 assert(to()->is_empty(), "Else not collection_attempt_is_safe");
a61af66fc99e Initial load
duke
parents:
diff changeset
715
a61af66fc99e Initial load
duke
parents:
diff changeset
716 init_assuming_no_promotion_failure();
a61af66fc99e Initial load
duke
parents:
diff changeset
717
a61af66fc99e Initial load
duke
parents:
diff changeset
718 if (UseAdaptiveSizePolicy) {
a61af66fc99e Initial load
duke
parents:
diff changeset
719 set_survivor_overflow(false);
a61af66fc99e Initial load
duke
parents:
diff changeset
720 size_policy->minor_collection_begin();
a61af66fc99e Initial load
duke
parents:
diff changeset
721 }
a61af66fc99e Initial load
duke
parents:
diff changeset
722
a61af66fc99e Initial load
duke
parents:
diff changeset
723 TraceTime t1("GC", PrintGC && !PrintGCDetails, true, gclog_or_tty);
a61af66fc99e Initial load
duke
parents:
diff changeset
724 // Capture heap used before collection (for printing).
a61af66fc99e Initial load
duke
parents:
diff changeset
725 size_t gch_prev_used = gch->used();
a61af66fc99e Initial load
duke
parents:
diff changeset
726
a61af66fc99e Initial load
duke
parents:
diff changeset
727 SpecializationStats::clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
728
a61af66fc99e Initial load
duke
parents:
diff changeset
729 age_table()->clear();
263
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 167
diff changeset
730 to()->clear(SpaceDecorator::Mangle);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
731
a61af66fc99e Initial load
duke
parents:
diff changeset
732 gch->save_marks();
a61af66fc99e Initial load
duke
parents:
diff changeset
733 assert(workers != NULL, "Need parallel worker threads.");
a61af66fc99e Initial load
duke
parents:
diff changeset
734 ParallelTaskTerminator _term(workers->total_workers(), task_queues());
a61af66fc99e Initial load
duke
parents:
diff changeset
735 ParScanThreadStateSet thread_state_set(workers->total_workers(),
a61af66fc99e Initial load
duke
parents:
diff changeset
736 *to(), *this, *_next_gen, *task_queues(),
a61af66fc99e Initial load
duke
parents:
diff changeset
737 desired_plab_sz(), _term);
a61af66fc99e Initial load
duke
parents:
diff changeset
738
a61af66fc99e Initial load
duke
parents:
diff changeset
739 ParNewGenTask tsk(this, _next_gen, reserved().end(), &thread_state_set);
a61af66fc99e Initial load
duke
parents:
diff changeset
740 int n_workers = workers->total_workers();
a61af66fc99e Initial load
duke
parents:
diff changeset
741 gch->set_par_threads(n_workers);
a61af66fc99e Initial load
duke
parents:
diff changeset
742 gch->change_strong_roots_parity();
a61af66fc99e Initial load
duke
parents:
diff changeset
743 gch->rem_set()->prepare_for_younger_refs_iterate(true);
a61af66fc99e Initial load
duke
parents:
diff changeset
744 // It turns out that even when we're using 1 thread, doing the work in a
a61af66fc99e Initial load
duke
parents:
diff changeset
745 // separate thread causes wide variance in run times. We can't help this
a61af66fc99e Initial load
duke
parents:
diff changeset
746 // in the multi-threaded case, but we special-case n=1 here to get
a61af66fc99e Initial load
duke
parents:
diff changeset
747 // repeatable measurements of the 1-thread overhead of the parallel code.
a61af66fc99e Initial load
duke
parents:
diff changeset
748 if (n_workers > 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
749 workers->run_task(&tsk);
a61af66fc99e Initial load
duke
parents:
diff changeset
750 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
751 tsk.work(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
752 }
a61af66fc99e Initial load
duke
parents:
diff changeset
753 thread_state_set.reset();
a61af66fc99e Initial load
duke
parents:
diff changeset
754
a61af66fc99e Initial load
duke
parents:
diff changeset
755 if (PAR_STATS_ENABLED && ParallelGCVerbose) {
a61af66fc99e Initial load
duke
parents:
diff changeset
756 gclog_or_tty->print("Thread totals:\n"
a61af66fc99e Initial load
duke
parents:
diff changeset
757 " Pushes: %7d Pops: %7d Steals %7d (sum = %7d).\n",
a61af66fc99e Initial load
duke
parents:
diff changeset
758 thread_state_set.pushes(), thread_state_set.pops(),
a61af66fc99e Initial load
duke
parents:
diff changeset
759 thread_state_set.steals(),
a61af66fc99e Initial load
duke
parents:
diff changeset
760 thread_state_set.pops()+thread_state_set.steals());
a61af66fc99e Initial load
duke
parents:
diff changeset
761 }
453
c96030fff130 6684579: SoftReference processing can be made more efficient
ysr
parents: 269
diff changeset
762 assert(thread_state_set.pushes() == thread_state_set.pops()
c96030fff130 6684579: SoftReference processing can be made more efficient
ysr
parents: 269
diff changeset
763 + thread_state_set.steals(),
0
a61af66fc99e Initial load
duke
parents:
diff changeset
764 "Or else the queues are leaky.");
a61af66fc99e Initial load
duke
parents:
diff changeset
765
a61af66fc99e Initial load
duke
parents:
diff changeset
766 // Process (weak) reference objects found during scavenge.
453
c96030fff130 6684579: SoftReference processing can be made more efficient
ysr
parents: 269
diff changeset
767 ReferenceProcessor* rp = ref_processor();
0
a61af66fc99e Initial load
duke
parents:
diff changeset
768 IsAliveClosure is_alive(this);
a61af66fc99e Initial load
duke
parents:
diff changeset
769 ScanWeakRefClosure scan_weak_ref(this);
a61af66fc99e Initial load
duke
parents:
diff changeset
770 KeepAliveClosure keep_alive(&scan_weak_ref);
a61af66fc99e Initial load
duke
parents:
diff changeset
771 ScanClosure scan_without_gc_barrier(this, false);
a61af66fc99e Initial load
duke
parents:
diff changeset
772 ScanClosureWithParBarrier scan_with_gc_barrier(this, true);
a61af66fc99e Initial load
duke
parents:
diff changeset
773 set_promo_failure_scan_stack_closure(&scan_without_gc_barrier);
a61af66fc99e Initial load
duke
parents:
diff changeset
774 EvacuateFollowersClosureGeneral evacuate_followers(gch, _level,
a61af66fc99e Initial load
duke
parents:
diff changeset
775 &scan_without_gc_barrier, &scan_with_gc_barrier);
453
c96030fff130 6684579: SoftReference processing can be made more efficient
ysr
parents: 269
diff changeset
776 rp->snap_policy(clear_all_soft_refs);
c96030fff130 6684579: SoftReference processing can be made more efficient
ysr
parents: 269
diff changeset
777 if (rp->processing_is_mt()) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
778 ParNewRefProcTaskExecutor task_executor(*this, thread_state_set);
453
c96030fff130 6684579: SoftReference processing can be made more efficient
ysr
parents: 269
diff changeset
779 rp->process_discovered_references(&is_alive, &keep_alive,
c96030fff130 6684579: SoftReference processing can be made more efficient
ysr
parents: 269
diff changeset
780 &evacuate_followers, &task_executor);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
781 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
782 thread_state_set.flush();
a61af66fc99e Initial load
duke
parents:
diff changeset
783 gch->set_par_threads(0); // 0 ==> non-parallel.
a61af66fc99e Initial load
duke
parents:
diff changeset
784 gch->save_marks();
453
c96030fff130 6684579: SoftReference processing can be made more efficient
ysr
parents: 269
diff changeset
785 rp->process_discovered_references(&is_alive, &keep_alive,
c96030fff130 6684579: SoftReference processing can be made more efficient
ysr
parents: 269
diff changeset
786 &evacuate_followers, NULL);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
787 }
a61af66fc99e Initial load
duke
parents:
diff changeset
788 if (!promotion_failed()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
789 // Swap the survivor spaces.
263
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 167
diff changeset
790 eden()->clear(SpaceDecorator::Mangle);
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 167
diff changeset
791 from()->clear(SpaceDecorator::Mangle);
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 167
diff changeset
792 if (ZapUnusedHeapArea) {
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 167
diff changeset
793 // This is now done here because of the piece-meal mangling which
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 167
diff changeset
794 // can check for valid mangling at intermediate points in the
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 167
diff changeset
795 // collection(s). When a minor collection fails to collect
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 167
diff changeset
796 // sufficient space resizing of the young generation can occur
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 167
diff changeset
797 // an redistribute the spaces in the young generation. Mangle
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 167
diff changeset
798 // here so that unzapped regions don't get distributed to
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 167
diff changeset
799 // other spaces.
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 167
diff changeset
800 to()->mangle_unused_area();
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 167
diff changeset
801 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
802 swap_spaces();
a61af66fc99e Initial load
duke
parents:
diff changeset
803
a61af66fc99e Initial load
duke
parents:
diff changeset
804 assert(to()->is_empty(), "to space should be empty now");
a61af66fc99e Initial load
duke
parents:
diff changeset
805 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
806 assert(HandlePromotionFailure,
a61af66fc99e Initial load
duke
parents:
diff changeset
807 "Should only be here if promotion failure handling is on");
a61af66fc99e Initial load
duke
parents:
diff changeset
808 if (_promo_failure_scan_stack != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
809 // Can be non-null because of reference processing.
a61af66fc99e Initial load
duke
parents:
diff changeset
810 // Free stack with its elements.
a61af66fc99e Initial load
duke
parents:
diff changeset
811 delete _promo_failure_scan_stack;
a61af66fc99e Initial load
duke
parents:
diff changeset
812 _promo_failure_scan_stack = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
813 }
a61af66fc99e Initial load
duke
parents:
diff changeset
814 remove_forwarding_pointers();
a61af66fc99e Initial load
duke
parents:
diff changeset
815 if (PrintGCDetails) {
a61af66fc99e Initial load
duke
parents:
diff changeset
816 gclog_or_tty->print(" (promotion failed)");
a61af66fc99e Initial load
duke
parents:
diff changeset
817 }
a61af66fc99e Initial load
duke
parents:
diff changeset
818 // All the spaces are in play for mark-sweep.
a61af66fc99e Initial load
duke
parents:
diff changeset
819 swap_spaces(); // Make life simpler for CMS || rescan; see 6483690.
a61af66fc99e Initial load
duke
parents:
diff changeset
820 from()->set_next_compaction_space(to());
a61af66fc99e Initial load
duke
parents:
diff changeset
821 gch->set_incremental_collection_will_fail();
6
73e96e5c30df 6624765: Guarantee failure "Unexpected dirty card found"
jmasa
parents: 0
diff changeset
822
73e96e5c30df 6624765: Guarantee failure "Unexpected dirty card found"
jmasa
parents: 0
diff changeset
823 // Reset the PromotionFailureALot counters.
73e96e5c30df 6624765: Guarantee failure "Unexpected dirty card found"
jmasa
parents: 0
diff changeset
824 NOT_PRODUCT(Universe::heap()->reset_promotion_should_fail();)
0
a61af66fc99e Initial load
duke
parents:
diff changeset
825 }
a61af66fc99e Initial load
duke
parents:
diff changeset
826 // set new iteration safe limit for the survivor spaces
a61af66fc99e Initial load
duke
parents:
diff changeset
827 from()->set_concurrent_iteration_safe_limit(from()->top());
a61af66fc99e Initial load
duke
parents:
diff changeset
828 to()->set_concurrent_iteration_safe_limit(to()->top());
a61af66fc99e Initial load
duke
parents:
diff changeset
829
a61af66fc99e Initial load
duke
parents:
diff changeset
830 adjust_desired_tenuring_threshold();
a61af66fc99e Initial load
duke
parents:
diff changeset
831 if (ResizePLAB) {
a61af66fc99e Initial load
duke
parents:
diff changeset
832 plab_stats()->adjust_desired_plab_sz();
a61af66fc99e Initial load
duke
parents:
diff changeset
833 }
a61af66fc99e Initial load
duke
parents:
diff changeset
834
a61af66fc99e Initial load
duke
parents:
diff changeset
835 if (PrintGC && !PrintGCDetails) {
a61af66fc99e Initial load
duke
parents:
diff changeset
836 gch->print_heap_change(gch_prev_used);
a61af66fc99e Initial load
duke
parents:
diff changeset
837 }
a61af66fc99e Initial load
duke
parents:
diff changeset
838
a61af66fc99e Initial load
duke
parents:
diff changeset
839 if (UseAdaptiveSizePolicy) {
a61af66fc99e Initial load
duke
parents:
diff changeset
840 size_policy->minor_collection_end(gch->gc_cause());
a61af66fc99e Initial load
duke
parents:
diff changeset
841 size_policy->avg_survived()->sample(from()->used());
a61af66fc99e Initial load
duke
parents:
diff changeset
842 }
a61af66fc99e Initial load
duke
parents:
diff changeset
843
a61af66fc99e Initial load
duke
parents:
diff changeset
844 update_time_of_last_gc(os::javaTimeMillis());
a61af66fc99e Initial load
duke
parents:
diff changeset
845
a61af66fc99e Initial load
duke
parents:
diff changeset
846 SpecializationStats::print();
a61af66fc99e Initial load
duke
parents:
diff changeset
847
453
c96030fff130 6684579: SoftReference processing can be made more efficient
ysr
parents: 269
diff changeset
848 rp->set_enqueuing_is_done(true);
c96030fff130 6684579: SoftReference processing can be made more efficient
ysr
parents: 269
diff changeset
849 if (rp->processing_is_mt()) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
850 ParNewRefProcTaskExecutor task_executor(*this, thread_state_set);
453
c96030fff130 6684579: SoftReference processing can be made more efficient
ysr
parents: 269
diff changeset
851 rp->enqueue_discovered_references(&task_executor);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
852 } else {
453
c96030fff130 6684579: SoftReference processing can be made more efficient
ysr
parents: 269
diff changeset
853 rp->enqueue_discovered_references(NULL);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
854 }
453
c96030fff130 6684579: SoftReference processing can be made more efficient
ysr
parents: 269
diff changeset
855 rp->verify_no_references_recorded();
0
a61af66fc99e Initial load
duke
parents:
diff changeset
856 }
a61af66fc99e Initial load
duke
parents:
diff changeset
857
a61af66fc99e Initial load
duke
parents:
diff changeset
858 static int sum;
a61af66fc99e Initial load
duke
parents:
diff changeset
859 void ParNewGeneration::waste_some_time() {
a61af66fc99e Initial load
duke
parents:
diff changeset
860 for (int i = 0; i < 100; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
861 sum += i;
a61af66fc99e Initial load
duke
parents:
diff changeset
862 }
a61af66fc99e Initial load
duke
parents:
diff changeset
863 }
a61af66fc99e Initial load
duke
parents:
diff changeset
864
a61af66fc99e Initial load
duke
parents:
diff changeset
865 static const oop ClaimedForwardPtr = oop(0x4);
a61af66fc99e Initial load
duke
parents:
diff changeset
866
a61af66fc99e Initial load
duke
parents:
diff changeset
867 // Because of concurrency, there are times where an object for which
a61af66fc99e Initial load
duke
parents:
diff changeset
868 // "is_forwarded()" is true contains an "interim" forwarding pointer
a61af66fc99e Initial load
duke
parents:
diff changeset
869 // value. Such a value will soon be overwritten with a real value.
a61af66fc99e Initial load
duke
parents:
diff changeset
870 // This method requires "obj" to have a forwarding pointer, and waits, if
a61af66fc99e Initial load
duke
parents:
diff changeset
871 // necessary for a real one to be inserted, and returns it.
a61af66fc99e Initial load
duke
parents:
diff changeset
872
a61af66fc99e Initial load
duke
parents:
diff changeset
873 oop ParNewGeneration::real_forwardee(oop obj) {
a61af66fc99e Initial load
duke
parents:
diff changeset
874 oop forward_ptr = obj->forwardee();
a61af66fc99e Initial load
duke
parents:
diff changeset
875 if (forward_ptr != ClaimedForwardPtr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
876 return forward_ptr;
a61af66fc99e Initial load
duke
parents:
diff changeset
877 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
878 return real_forwardee_slow(obj);
a61af66fc99e Initial load
duke
parents:
diff changeset
879 }
a61af66fc99e Initial load
duke
parents:
diff changeset
880 }
a61af66fc99e Initial load
duke
parents:
diff changeset
881
a61af66fc99e Initial load
duke
parents:
diff changeset
882 oop ParNewGeneration::real_forwardee_slow(oop obj) {
a61af66fc99e Initial load
duke
parents:
diff changeset
883 // Spin-read if it is claimed but not yet written by another thread.
a61af66fc99e Initial load
duke
parents:
diff changeset
884 oop forward_ptr = obj->forwardee();
a61af66fc99e Initial load
duke
parents:
diff changeset
885 while (forward_ptr == ClaimedForwardPtr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
886 waste_some_time();
a61af66fc99e Initial load
duke
parents:
diff changeset
887 assert(obj->is_forwarded(), "precondition");
a61af66fc99e Initial load
duke
parents:
diff changeset
888 forward_ptr = obj->forwardee();
a61af66fc99e Initial load
duke
parents:
diff changeset
889 }
a61af66fc99e Initial load
duke
parents:
diff changeset
890 return forward_ptr;
a61af66fc99e Initial load
duke
parents:
diff changeset
891 }
a61af66fc99e Initial load
duke
parents:
diff changeset
892
a61af66fc99e Initial load
duke
parents:
diff changeset
893 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
894 bool ParNewGeneration::is_legal_forward_ptr(oop p) {
a61af66fc99e Initial load
duke
parents:
diff changeset
895 return
a61af66fc99e Initial load
duke
parents:
diff changeset
896 (_avoid_promotion_undo && p == ClaimedForwardPtr)
a61af66fc99e Initial load
duke
parents:
diff changeset
897 || Universe::heap()->is_in_reserved(p);
a61af66fc99e Initial load
duke
parents:
diff changeset
898 }
a61af66fc99e Initial load
duke
parents:
diff changeset
899 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
900
a61af66fc99e Initial load
duke
parents:
diff changeset
901 void ParNewGeneration::preserve_mark_if_necessary(oop obj, markOop m) {
a61af66fc99e Initial load
duke
parents:
diff changeset
902 if ((m != markOopDesc::prototype()) &&
a61af66fc99e Initial load
duke
parents:
diff changeset
903 (!UseBiasedLocking || (m != markOopDesc::biased_locking_prototype()))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
904 MutexLocker ml(ParGCRareEvent_lock);
a61af66fc99e Initial load
duke
parents:
diff changeset
905 DefNewGeneration::preserve_mark_if_necessary(obj, m);
a61af66fc99e Initial load
duke
parents:
diff changeset
906 }
a61af66fc99e Initial load
duke
parents:
diff changeset
907 }
a61af66fc99e Initial load
duke
parents:
diff changeset
908
a61af66fc99e Initial load
duke
parents:
diff changeset
909 // Multiple GC threads may try to promote an object. If the object
a61af66fc99e Initial load
duke
parents:
diff changeset
910 // is successfully promoted, a forwarding pointer will be installed in
a61af66fc99e Initial load
duke
parents:
diff changeset
911 // the object in the young generation. This method claims the right
a61af66fc99e Initial load
duke
parents:
diff changeset
912 // to install the forwarding pointer before it copies the object,
a61af66fc99e Initial load
duke
parents:
diff changeset
913 // thus avoiding the need to undo the copy as in
a61af66fc99e Initial load
duke
parents:
diff changeset
914 // copy_to_survivor_space_avoiding_with_undo.
a61af66fc99e Initial load
duke
parents:
diff changeset
915
a61af66fc99e Initial load
duke
parents:
diff changeset
916 oop ParNewGeneration::copy_to_survivor_space_avoiding_promotion_undo(
a61af66fc99e Initial load
duke
parents:
diff changeset
917 ParScanThreadState* par_scan_state, oop old, size_t sz, markOop m) {
a61af66fc99e Initial load
duke
parents:
diff changeset
918 // In the sequential version, this assert also says that the object is
a61af66fc99e Initial load
duke
parents:
diff changeset
919 // not forwarded. That might not be the case here. It is the case that
a61af66fc99e Initial load
duke
parents:
diff changeset
920 // the caller observed it to be not forwarded at some time in the past.
a61af66fc99e Initial load
duke
parents:
diff changeset
921 assert(is_in_reserved(old), "shouldn't be scavenging this oop");
a61af66fc99e Initial load
duke
parents:
diff changeset
922
a61af66fc99e Initial load
duke
parents:
diff changeset
923 // The sequential code read "old->age()" below. That doesn't work here,
a61af66fc99e Initial load
duke
parents:
diff changeset
924 // since the age is in the mark word, and that might be overwritten with
a61af66fc99e Initial load
duke
parents:
diff changeset
925 // a forwarding pointer by a parallel thread. So we must save the mark
a61af66fc99e Initial load
duke
parents:
diff changeset
926 // word in a local and then analyze it.
a61af66fc99e Initial load
duke
parents:
diff changeset
927 oopDesc dummyOld;
a61af66fc99e Initial load
duke
parents:
diff changeset
928 dummyOld.set_mark(m);
a61af66fc99e Initial load
duke
parents:
diff changeset
929 assert(!dummyOld.is_forwarded(),
a61af66fc99e Initial load
duke
parents:
diff changeset
930 "should not be called with forwarding pointer mark word.");
a61af66fc99e Initial load
duke
parents:
diff changeset
931
a61af66fc99e Initial load
duke
parents:
diff changeset
932 oop new_obj = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
933 oop forward_ptr;
a61af66fc99e Initial load
duke
parents:
diff changeset
934
a61af66fc99e Initial load
duke
parents:
diff changeset
935 // Try allocating obj in to-space (unless too old)
a61af66fc99e Initial load
duke
parents:
diff changeset
936 if (dummyOld.age() < tenuring_threshold()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
937 new_obj = (oop)par_scan_state->alloc_in_to_space(sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
938 if (new_obj == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
939 set_survivor_overflow(true);
a61af66fc99e Initial load
duke
parents:
diff changeset
940 }
a61af66fc99e Initial load
duke
parents:
diff changeset
941 }
a61af66fc99e Initial load
duke
parents:
diff changeset
942
a61af66fc99e Initial load
duke
parents:
diff changeset
943 if (new_obj == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
944 // Either to-space is full or we decided to promote
a61af66fc99e Initial load
duke
parents:
diff changeset
945 // try allocating obj tenured
a61af66fc99e Initial load
duke
parents:
diff changeset
946
a61af66fc99e Initial load
duke
parents:
diff changeset
947 // Attempt to install a null forwarding pointer (atomically),
a61af66fc99e Initial load
duke
parents:
diff changeset
948 // to claim the right to install the real forwarding pointer.
a61af66fc99e Initial load
duke
parents:
diff changeset
949 forward_ptr = old->forward_to_atomic(ClaimedForwardPtr);
a61af66fc99e Initial load
duke
parents:
diff changeset
950 if (forward_ptr != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
951 // someone else beat us to it.
a61af66fc99e Initial load
duke
parents:
diff changeset
952 return real_forwardee(old);
a61af66fc99e Initial load
duke
parents:
diff changeset
953 }
a61af66fc99e Initial load
duke
parents:
diff changeset
954
a61af66fc99e Initial load
duke
parents:
diff changeset
955 new_obj = _next_gen->par_promote(par_scan_state->thread_num(),
a61af66fc99e Initial load
duke
parents:
diff changeset
956 old, m, sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
957
a61af66fc99e Initial load
duke
parents:
diff changeset
958 if (new_obj == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
959 if (!HandlePromotionFailure) {
a61af66fc99e Initial load
duke
parents:
diff changeset
960 // A failed promotion likely means the MaxLiveObjectEvacuationRatio flag
a61af66fc99e Initial load
duke
parents:
diff changeset
961 // is incorrectly set. In any case, its seriously wrong to be here!
a61af66fc99e Initial load
duke
parents:
diff changeset
962 vm_exit_out_of_memory(sz*wordSize, "promotion");
a61af66fc99e Initial load
duke
parents:
diff changeset
963 }
a61af66fc99e Initial load
duke
parents:
diff changeset
964 // promotion failed, forward to self
a61af66fc99e Initial load
duke
parents:
diff changeset
965 _promotion_failed = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
966 new_obj = old;
a61af66fc99e Initial load
duke
parents:
diff changeset
967
a61af66fc99e Initial load
duke
parents:
diff changeset
968 preserve_mark_if_necessary(old, m);
a61af66fc99e Initial load
duke
parents:
diff changeset
969 }
a61af66fc99e Initial load
duke
parents:
diff changeset
970
a61af66fc99e Initial load
duke
parents:
diff changeset
971 old->forward_to(new_obj);
a61af66fc99e Initial load
duke
parents:
diff changeset
972 forward_ptr = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
973 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
974 // Is in to-space; do copying ourselves.
a61af66fc99e Initial load
duke
parents:
diff changeset
975 Copy::aligned_disjoint_words((HeapWord*)old, (HeapWord*)new_obj, sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
976 forward_ptr = old->forward_to_atomic(new_obj);
a61af66fc99e Initial load
duke
parents:
diff changeset
977 // Restore the mark word copied above.
a61af66fc99e Initial load
duke
parents:
diff changeset
978 new_obj->set_mark(m);
a61af66fc99e Initial load
duke
parents:
diff changeset
979 // Increment age if obj still in new generation
a61af66fc99e Initial load
duke
parents:
diff changeset
980 new_obj->incr_age();
a61af66fc99e Initial load
duke
parents:
diff changeset
981 par_scan_state->age_table()->add(new_obj, sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
982 }
a61af66fc99e Initial load
duke
parents:
diff changeset
983 assert(new_obj != NULL, "just checking");
a61af66fc99e Initial load
duke
parents:
diff changeset
984
a61af66fc99e Initial load
duke
parents:
diff changeset
985 if (forward_ptr == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
986 oop obj_to_push = new_obj;
a61af66fc99e Initial load
duke
parents:
diff changeset
987 if (par_scan_state->should_be_partially_scanned(obj_to_push, old)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
988 // Length field used as index of next element to be scanned.
a61af66fc99e Initial load
duke
parents:
diff changeset
989 // Real length can be obtained from real_forwardee()
a61af66fc99e Initial load
duke
parents:
diff changeset
990 arrayOop(old)->set_length(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
991 obj_to_push = old;
a61af66fc99e Initial load
duke
parents:
diff changeset
992 assert(obj_to_push->is_forwarded() && obj_to_push->forwardee() != obj_to_push,
a61af66fc99e Initial load
duke
parents:
diff changeset
993 "push forwarded object");
a61af66fc99e Initial load
duke
parents:
diff changeset
994 }
a61af66fc99e Initial load
duke
parents:
diff changeset
995 // Push it on one of the queues of to-be-scanned objects.
a61af66fc99e Initial load
duke
parents:
diff changeset
996 if (!par_scan_state->work_queue()->push(obj_to_push)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
997 // Add stats for overflow pushes.
a61af66fc99e Initial load
duke
parents:
diff changeset
998 if (Verbose && PrintGCDetails) {
a61af66fc99e Initial load
duke
parents:
diff changeset
999 gclog_or_tty->print("queue overflow!\n");
a61af66fc99e Initial load
duke
parents:
diff changeset
1000 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1001 push_on_overflow_list(old);
a61af66fc99e Initial load
duke
parents:
diff changeset
1002 par_scan_state->note_overflow_push();
a61af66fc99e Initial load
duke
parents:
diff changeset
1003 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1004 par_scan_state->note_push();
a61af66fc99e Initial load
duke
parents:
diff changeset
1005
a61af66fc99e Initial load
duke
parents:
diff changeset
1006 return new_obj;
a61af66fc99e Initial load
duke
parents:
diff changeset
1007 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1008
a61af66fc99e Initial load
duke
parents:
diff changeset
1009 // Oops. Someone beat us to it. Undo the allocation. Where did we
a61af66fc99e Initial load
duke
parents:
diff changeset
1010 // allocate it?
a61af66fc99e Initial load
duke
parents:
diff changeset
1011 if (is_in_reserved(new_obj)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1012 // Must be in to_space.
a61af66fc99e Initial load
duke
parents:
diff changeset
1013 assert(to()->is_in_reserved(new_obj), "Checking");
a61af66fc99e Initial load
duke
parents:
diff changeset
1014 if (forward_ptr == ClaimedForwardPtr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1015 // Wait to get the real forwarding pointer value.
a61af66fc99e Initial load
duke
parents:
diff changeset
1016 forward_ptr = real_forwardee(old);
a61af66fc99e Initial load
duke
parents:
diff changeset
1017 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1018 par_scan_state->undo_alloc_in_to_space((HeapWord*)new_obj, sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
1019 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1020
a61af66fc99e Initial load
duke
parents:
diff changeset
1021 return forward_ptr;
a61af66fc99e Initial load
duke
parents:
diff changeset
1022 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1023
a61af66fc99e Initial load
duke
parents:
diff changeset
1024
a61af66fc99e Initial load
duke
parents:
diff changeset
1025 // Multiple GC threads may try to promote the same object. If two
a61af66fc99e Initial load
duke
parents:
diff changeset
1026 // or more GC threads copy the object, only one wins the race to install
a61af66fc99e Initial load
duke
parents:
diff changeset
1027 // the forwarding pointer. The other threads have to undo their copy.
a61af66fc99e Initial load
duke
parents:
diff changeset
1028
a61af66fc99e Initial load
duke
parents:
diff changeset
1029 oop ParNewGeneration::copy_to_survivor_space_with_undo(
a61af66fc99e Initial load
duke
parents:
diff changeset
1030 ParScanThreadState* par_scan_state, oop old, size_t sz, markOop m) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1031
a61af66fc99e Initial load
duke
parents:
diff changeset
1032 // In the sequential version, this assert also says that the object is
a61af66fc99e Initial load
duke
parents:
diff changeset
1033 // not forwarded. That might not be the case here. It is the case that
a61af66fc99e Initial load
duke
parents:
diff changeset
1034 // the caller observed it to be not forwarded at some time in the past.
a61af66fc99e Initial load
duke
parents:
diff changeset
1035 assert(is_in_reserved(old), "shouldn't be scavenging this oop");
a61af66fc99e Initial load
duke
parents:
diff changeset
1036
a61af66fc99e Initial load
duke
parents:
diff changeset
1037 // The sequential code read "old->age()" below. That doesn't work here,
a61af66fc99e Initial load
duke
parents:
diff changeset
1038 // since the age is in the mark word, and that might be overwritten with
a61af66fc99e Initial load
duke
parents:
diff changeset
1039 // a forwarding pointer by a parallel thread. So we must save the mark
a61af66fc99e Initial load
duke
parents:
diff changeset
1040 // word here, install it in a local oopDesc, and then analyze it.
a61af66fc99e Initial load
duke
parents:
diff changeset
1041 oopDesc dummyOld;
a61af66fc99e Initial load
duke
parents:
diff changeset
1042 dummyOld.set_mark(m);
a61af66fc99e Initial load
duke
parents:
diff changeset
1043 assert(!dummyOld.is_forwarded(),
a61af66fc99e Initial load
duke
parents:
diff changeset
1044 "should not be called with forwarding pointer mark word.");
a61af66fc99e Initial load
duke
parents:
diff changeset
1045
a61af66fc99e Initial load
duke
parents:
diff changeset
1046 bool failed_to_promote = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
1047 oop new_obj = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
1048 oop forward_ptr;
a61af66fc99e Initial load
duke
parents:
diff changeset
1049
a61af66fc99e Initial load
duke
parents:
diff changeset
1050 // Try allocating obj in to-space (unless too old)
a61af66fc99e Initial load
duke
parents:
diff changeset
1051 if (dummyOld.age() < tenuring_threshold()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1052 new_obj = (oop)par_scan_state->alloc_in_to_space(sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
1053 if (new_obj == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1054 set_survivor_overflow(true);
a61af66fc99e Initial load
duke
parents:
diff changeset
1055 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1056 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1057
a61af66fc99e Initial load
duke
parents:
diff changeset
1058 if (new_obj == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1059 // Either to-space is full or we decided to promote
a61af66fc99e Initial load
duke
parents:
diff changeset
1060 // try allocating obj tenured
a61af66fc99e Initial load
duke
parents:
diff changeset
1061 new_obj = _next_gen->par_promote(par_scan_state->thread_num(),
a61af66fc99e Initial load
duke
parents:
diff changeset
1062 old, m, sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
1063
a61af66fc99e Initial load
duke
parents:
diff changeset
1064 if (new_obj == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1065 if (!HandlePromotionFailure) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1066 // A failed promotion likely means the MaxLiveObjectEvacuationRatio
a61af66fc99e Initial load
duke
parents:
diff changeset
1067 // flag is incorrectly set. In any case, its seriously wrong to be
a61af66fc99e Initial load
duke
parents:
diff changeset
1068 // here!
a61af66fc99e Initial load
duke
parents:
diff changeset
1069 vm_exit_out_of_memory(sz*wordSize, "promotion");
a61af66fc99e Initial load
duke
parents:
diff changeset
1070 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1071 // promotion failed, forward to self
a61af66fc99e Initial load
duke
parents:
diff changeset
1072 forward_ptr = old->forward_to_atomic(old);
a61af66fc99e Initial load
duke
parents:
diff changeset
1073 new_obj = old;
a61af66fc99e Initial load
duke
parents:
diff changeset
1074
a61af66fc99e Initial load
duke
parents:
diff changeset
1075 if (forward_ptr != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1076 return forward_ptr; // someone else succeeded
a61af66fc99e Initial load
duke
parents:
diff changeset
1077 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1078
a61af66fc99e Initial load
duke
parents:
diff changeset
1079 _promotion_failed = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
1080 failed_to_promote = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
1081
a61af66fc99e Initial load
duke
parents:
diff changeset
1082 preserve_mark_if_necessary(old, m);
a61af66fc99e Initial load
duke
parents:
diff changeset
1083 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1084 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1085 // Is in to-space; do copying ourselves.
a61af66fc99e Initial load
duke
parents:
diff changeset
1086 Copy::aligned_disjoint_words((HeapWord*)old, (HeapWord*)new_obj, sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
1087 // Restore the mark word copied above.
a61af66fc99e Initial load
duke
parents:
diff changeset
1088 new_obj->set_mark(m);
a61af66fc99e Initial load
duke
parents:
diff changeset
1089 // Increment age if new_obj still in new generation
a61af66fc99e Initial load
duke
parents:
diff changeset
1090 new_obj->incr_age();
a61af66fc99e Initial load
duke
parents:
diff changeset
1091 par_scan_state->age_table()->add(new_obj, sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
1092 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1093 assert(new_obj != NULL, "just checking");
a61af66fc99e Initial load
duke
parents:
diff changeset
1094
a61af66fc99e Initial load
duke
parents:
diff changeset
1095 // Now attempt to install the forwarding pointer (atomically).
a61af66fc99e Initial load
duke
parents:
diff changeset
1096 // We have to copy the mark word before overwriting with forwarding
a61af66fc99e Initial load
duke
parents:
diff changeset
1097 // ptr, so we can restore it below in the copy.
a61af66fc99e Initial load
duke
parents:
diff changeset
1098 if (!failed_to_promote) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1099 forward_ptr = old->forward_to_atomic(new_obj);
a61af66fc99e Initial load
duke
parents:
diff changeset
1100 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1101
a61af66fc99e Initial load
duke
parents:
diff changeset
1102 if (forward_ptr == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1103 oop obj_to_push = new_obj;
a61af66fc99e Initial load
duke
parents:
diff changeset
1104 if (par_scan_state->should_be_partially_scanned(obj_to_push, old)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1105 // Length field used as index of next element to be scanned.
a61af66fc99e Initial load
duke
parents:
diff changeset
1106 // Real length can be obtained from real_forwardee()
a61af66fc99e Initial load
duke
parents:
diff changeset
1107 arrayOop(old)->set_length(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1108 obj_to_push = old;
a61af66fc99e Initial load
duke
parents:
diff changeset
1109 assert(obj_to_push->is_forwarded() && obj_to_push->forwardee() != obj_to_push,
a61af66fc99e Initial load
duke
parents:
diff changeset
1110 "push forwarded object");
a61af66fc99e Initial load
duke
parents:
diff changeset
1111 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1112 // Push it on one of the queues of to-be-scanned objects.
a61af66fc99e Initial load
duke
parents:
diff changeset
1113 if (!par_scan_state->work_queue()->push(obj_to_push)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1114 // Add stats for overflow pushes.
a61af66fc99e Initial load
duke
parents:
diff changeset
1115 push_on_overflow_list(old);
a61af66fc99e Initial load
duke
parents:
diff changeset
1116 par_scan_state->note_overflow_push();
a61af66fc99e Initial load
duke
parents:
diff changeset
1117 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1118 par_scan_state->note_push();
a61af66fc99e Initial load
duke
parents:
diff changeset
1119
a61af66fc99e Initial load
duke
parents:
diff changeset
1120 return new_obj;
a61af66fc99e Initial load
duke
parents:
diff changeset
1121 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1122
a61af66fc99e Initial load
duke
parents:
diff changeset
1123 // Oops. Someone beat us to it. Undo the allocation. Where did we
a61af66fc99e Initial load
duke
parents:
diff changeset
1124 // allocate it?
a61af66fc99e Initial load
duke
parents:
diff changeset
1125 if (is_in_reserved(new_obj)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1126 // Must be in to_space.
a61af66fc99e Initial load
duke
parents:
diff changeset
1127 assert(to()->is_in_reserved(new_obj), "Checking");
a61af66fc99e Initial load
duke
parents:
diff changeset
1128 par_scan_state->undo_alloc_in_to_space((HeapWord*)new_obj, sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
1129 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1130 assert(!_avoid_promotion_undo, "Should not be here if avoiding.");
a61af66fc99e Initial load
duke
parents:
diff changeset
1131 _next_gen->par_promote_alloc_undo(par_scan_state->thread_num(),
a61af66fc99e Initial load
duke
parents:
diff changeset
1132 (HeapWord*)new_obj, sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
1133 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1134
a61af66fc99e Initial load
duke
parents:
diff changeset
1135 return forward_ptr;
a61af66fc99e Initial load
duke
parents:
diff changeset
1136 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1137
a61af66fc99e Initial load
duke
parents:
diff changeset
1138 void ParNewGeneration::push_on_overflow_list(oop from_space_obj) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1139 oop cur_overflow_list = _overflow_list;
a61af66fc99e Initial load
duke
parents:
diff changeset
1140 // if the object has been forwarded to itself, then we cannot
a61af66fc99e Initial load
duke
parents:
diff changeset
1141 // use the klass pointer for the linked list. Instead we have
a61af66fc99e Initial load
duke
parents:
diff changeset
1142 // to allocate an oopDesc in the C-Heap and use that for the linked list.
a61af66fc99e Initial load
duke
parents:
diff changeset
1143 if (from_space_obj->forwardee() == from_space_obj) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1144 oopDesc* listhead = NEW_C_HEAP_ARRAY(oopDesc, 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1145 listhead->forward_to(from_space_obj);
a61af66fc99e Initial load
duke
parents:
diff changeset
1146 from_space_obj = listhead;
a61af66fc99e Initial load
duke
parents:
diff changeset
1147 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1148 while (true) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1149 from_space_obj->set_klass_to_list_ptr(cur_overflow_list);
a61af66fc99e Initial load
duke
parents:
diff changeset
1150 oop observed_overflow_list =
a61af66fc99e Initial load
duke
parents:
diff changeset
1151 (oop)Atomic::cmpxchg_ptr(from_space_obj, &_overflow_list, cur_overflow_list);
a61af66fc99e Initial load
duke
parents:
diff changeset
1152 if (observed_overflow_list == cur_overflow_list) break;
a61af66fc99e Initial load
duke
parents:
diff changeset
1153 // Otherwise...
a61af66fc99e Initial load
duke
parents:
diff changeset
1154 cur_overflow_list = observed_overflow_list;
a61af66fc99e Initial load
duke
parents:
diff changeset
1155 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1156 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1157
a61af66fc99e Initial load
duke
parents:
diff changeset
1158 bool
a61af66fc99e Initial load
duke
parents:
diff changeset
1159 ParNewGeneration::take_from_overflow_list(ParScanThreadState* par_scan_state) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1160 ObjToScanQueue* work_q = par_scan_state->work_queue();
a61af66fc99e Initial load
duke
parents:
diff changeset
1161 // How many to take?
a61af66fc99e Initial load
duke
parents:
diff changeset
1162 int objsFromOverflow = MIN2(work_q->max_elems()/4,
a61af66fc99e Initial load
duke
parents:
diff changeset
1163 (juint)ParGCDesiredObjsFromOverflowList);
a61af66fc99e Initial load
duke
parents:
diff changeset
1164
a61af66fc99e Initial load
duke
parents:
diff changeset
1165 if (_overflow_list == NULL) return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
1166
a61af66fc99e Initial load
duke
parents:
diff changeset
1167 // Otherwise, there was something there; try claiming the list.
a61af66fc99e Initial load
duke
parents:
diff changeset
1168 oop prefix = (oop)Atomic::xchg_ptr(NULL, &_overflow_list);
a61af66fc99e Initial load
duke
parents:
diff changeset
1169
a61af66fc99e Initial load
duke
parents:
diff changeset
1170 if (prefix == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1171 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
1172 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1173 // Trim off a prefix of at most objsFromOverflow items
a61af66fc99e Initial load
duke
parents:
diff changeset
1174 int i = 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
1175 oop cur = prefix;
167
feeb96a45707 6696264: assert("narrow oop can never be zero") for GCBasher & ParNewGC
coleenp
parents: 113
diff changeset
1176 while (i < objsFromOverflow && cur->klass_or_null() != NULL) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1177 i++; cur = oop(cur->klass());
a61af66fc99e Initial load
duke
parents:
diff changeset
1178 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1179
a61af66fc99e Initial load
duke
parents:
diff changeset
1180 // Reattach remaining (suffix) to overflow list
167
feeb96a45707 6696264: assert("narrow oop can never be zero") for GCBasher & ParNewGC
coleenp
parents: 113
diff changeset
1181 if (cur->klass_or_null() != NULL) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1182 oop suffix = oop(cur->klass());
a61af66fc99e Initial load
duke
parents:
diff changeset
1183 cur->set_klass_to_list_ptr(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
1184
a61af66fc99e Initial load
duke
parents:
diff changeset
1185 // Find last item of suffix list
a61af66fc99e Initial load
duke
parents:
diff changeset
1186 oop last = suffix;
167
feeb96a45707 6696264: assert("narrow oop can never be zero") for GCBasher & ParNewGC
coleenp
parents: 113
diff changeset
1187 while (last->klass_or_null() != NULL) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1188 last = oop(last->klass());
a61af66fc99e Initial load
duke
parents:
diff changeset
1189 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1190 // Atomically prepend suffix to current overflow list
a61af66fc99e Initial load
duke
parents:
diff changeset
1191 oop cur_overflow_list = _overflow_list;
a61af66fc99e Initial load
duke
parents:
diff changeset
1192 while (true) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1193 last->set_klass_to_list_ptr(cur_overflow_list);
a61af66fc99e Initial load
duke
parents:
diff changeset
1194 oop observed_overflow_list =
a61af66fc99e Initial load
duke
parents:
diff changeset
1195 (oop)Atomic::cmpxchg_ptr(suffix, &_overflow_list, cur_overflow_list);
a61af66fc99e Initial load
duke
parents:
diff changeset
1196 if (observed_overflow_list == cur_overflow_list) break;
a61af66fc99e Initial load
duke
parents:
diff changeset
1197 // Otherwise...
a61af66fc99e Initial load
duke
parents:
diff changeset
1198 cur_overflow_list = observed_overflow_list;
a61af66fc99e Initial load
duke
parents:
diff changeset
1199 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1200 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1201
a61af66fc99e Initial load
duke
parents:
diff changeset
1202 // Push objects on prefix list onto this thread's work queue
a61af66fc99e Initial load
duke
parents:
diff changeset
1203 assert(cur != NULL, "program logic");
a61af66fc99e Initial load
duke
parents:
diff changeset
1204 cur = prefix;
a61af66fc99e Initial load
duke
parents:
diff changeset
1205 int n = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1206 while (cur != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1207 oop obj_to_push = cur->forwardee();
a61af66fc99e Initial load
duke
parents:
diff changeset
1208 oop next = oop(cur->klass());
a61af66fc99e Initial load
duke
parents:
diff changeset
1209 cur->set_klass(obj_to_push->klass());
a61af66fc99e Initial load
duke
parents:
diff changeset
1210 if (par_scan_state->should_be_partially_scanned(obj_to_push, cur)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1211 obj_to_push = cur;
a61af66fc99e Initial load
duke
parents:
diff changeset
1212 assert(arrayOop(cur)->length() == 0, "entire array remaining to be scanned");
a61af66fc99e Initial load
duke
parents:
diff changeset
1213 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1214 work_q->push(obj_to_push);
a61af66fc99e Initial load
duke
parents:
diff changeset
1215 cur = next;
a61af66fc99e Initial load
duke
parents:
diff changeset
1216 n++;
a61af66fc99e Initial load
duke
parents:
diff changeset
1217 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1218 par_scan_state->note_overflow_refill(n);
a61af66fc99e Initial load
duke
parents:
diff changeset
1219 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
1220 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1221
a61af66fc99e Initial load
duke
parents:
diff changeset
1222 void ParNewGeneration::ref_processor_init()
a61af66fc99e Initial load
duke
parents:
diff changeset
1223 {
a61af66fc99e Initial load
duke
parents:
diff changeset
1224 if (_ref_processor == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1225 // Allocate and initialize a reference processor
a61af66fc99e Initial load
duke
parents:
diff changeset
1226 _ref_processor = ReferenceProcessor::create_ref_processor(
a61af66fc99e Initial load
duke
parents:
diff changeset
1227 _reserved, // span
a61af66fc99e Initial load
duke
parents:
diff changeset
1228 refs_discovery_is_atomic(), // atomic_discovery
a61af66fc99e Initial load
duke
parents:
diff changeset
1229 refs_discovery_is_mt(), // mt_discovery
a61af66fc99e Initial load
duke
parents:
diff changeset
1230 NULL, // is_alive_non_header
a61af66fc99e Initial load
duke
parents:
diff changeset
1231 ParallelGCThreads,
a61af66fc99e Initial load
duke
parents:
diff changeset
1232 ParallelRefProcEnabled);
a61af66fc99e Initial load
duke
parents:
diff changeset
1233 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1234 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1235
a61af66fc99e Initial load
duke
parents:
diff changeset
1236 const char* ParNewGeneration::name() const {
a61af66fc99e Initial load
duke
parents:
diff changeset
1237 return "par new generation";
a61af66fc99e Initial load
duke
parents:
diff changeset
1238 }