52 #include "runtime/handles.inline.hpp"
53 #include "runtime/java.hpp"
54 #include "runtime/thread.inline.hpp"
55 #include "utilities/copy.hpp"
56 #include "utilities/globalDefinitions.hpp"
57 #include "utilities/workgroup.hpp"
58
59 PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
60
61 #ifdef _MSC_VER
62 #pragma warning( push )
63 #pragma warning( disable:4355 ) // 'this' : used in base member initializer list
64 #endif
65 ParScanThreadState::ParScanThreadState(Space* to_space_,
66 ParNewGeneration* gen_,
67 Generation* old_gen_,
68 int thread_num_,
69 ObjToScanQueueSet* work_queue_set_,
70 Stack<oop, mtGC>* overflow_stacks_,
71 size_t desired_plab_sz_,
72 ParallelTaskTerminator& term_) :
73 _to_space(to_space_), _old_gen(old_gen_), _young_gen(gen_), _thread_num(thread_num_),
74 _work_queue(work_queue_set_->queue(thread_num_)), _to_space_full(false),
75 _overflow_stack(overflow_stacks_ ? overflow_stacks_ + thread_num_ : NULL),
76 _ageTable(false), // false ==> not the global age table, no perf data.
77 _to_space_alloc_buffer(desired_plab_sz_),
78 _to_space_closure(gen_, this), _old_gen_closure(gen_, this),
79 _to_space_root_closure(gen_, this), _old_gen_root_closure(gen_, this),
80 _older_gen_closure(gen_, this),
81 _evacuate_followers(this, &_to_space_closure, &_old_gen_closure,
82 &_to_space_root_closure, gen_, &_old_gen_root_closure,
83 work_queue_set_, &term_),
84 _is_alive_closure(gen_), _scan_weak_ref_closure(gen_, this),
85 _keep_alive_closure(&_scan_weak_ref_closure),
86 _strong_roots_time(0.0), _term_time(0.0)
87 {
88 #if TASKQUEUE_STATS
89 _term_attempts = 0;
90 _overflow_refills = 0;
91 _overflow_refill_objs = 0;
92 #endif // TASKQUEUE_STATS
93
94 _survivor_chunk_array =
95 (ChunkArray*) old_gen()->get_data_recorder(thread_num());
96 _hash_seed = 17; // Might want to take time-based random value.
97 _start = os::elapsedTime();
205 assert(Universe::heap()->is_in_reserved(cur), "Should be in heap");
206 assert(!old_gen()->is_in_reserved(cur), "Should be in young gen");
207 assert(Universe::heap()->is_in_reserved(obj_to_push), "Should be in heap");
208 if (should_be_partially_scanned(obj_to_push, cur)) {
209 assert(arrayOop(cur)->length() == 0, "entire array remaining to be scanned");
210 obj_to_push = cur;
211 }
212 bool ok = queue->push(obj_to_push);
213 assert(ok, "Should have succeeded");
214 }
215 assert(young_gen()->overflow_list() == NULL, "Error");
216 return num_take_elems > 0; // was something transferred?
217 }
218
219 void ParScanThreadState::push_on_overflow_stack(oop p) {
220 assert(ParGCUseLocalOverflow, "Else should not call");
221 overflow_stack()->push(p);
222 assert(young_gen()->overflow_list() == NULL, "Error");
223 }
224
225 HeapWord* ParScanThreadState::alloc_in_to_space_slow(size_t word_sz) {
226
227 // Otherwise, if the object is small enough, try to reallocate the
228 // buffer.
229 HeapWord* obj = NULL;
230 if (!_to_space_full) {
231 ParGCAllocBuffer* const plab = to_space_alloc_buffer();
232 Space* const sp = to_space();
233 if (word_sz * 100 <
234 ParallelGCBufferWastePct * plab->word_sz()) {
235 // Is small enough; abandon this buffer and start a new one.
236 plab->retire(false, false);
237 size_t buf_size = plab->word_sz();
238 HeapWord* buf_space = sp->par_allocate(buf_size);
239 if (buf_space == NULL) {
240 const size_t min_bytes =
241 ParGCAllocBuffer::min_size() << LogHeapWordSize;
242 size_t free_bytes = sp->free();
243 while(buf_space == NULL && free_bytes >= min_bytes) {
244 buf_size = free_bytes >> LogHeapWordSize;
245 assert(buf_size == (size_t)align_object_size(buf_size),
246 "Invariant");
247 buf_space = sp->par_allocate(buf_size);
248 free_bytes = sp->free();
249 }
250 }
251 if (buf_space != NULL) {
252 plab->set_word_size(buf_size);
253 plab->set_buf(buf_space);
254 record_survivor_plab(buf_space, buf_size);
255 obj = plab->allocate_aligned(word_sz, SurvivorAlignmentInBytes);
256 // Note that we cannot compare buf_size < word_sz below
257 // because of AlignmentReserve (see ParGCAllocBuffer::allocate()).
258 assert(obj != NULL || plab->words_remaining() < word_sz,
259 "Else should have been able to allocate");
260 // It's conceivable that we may be able to use the
261 // buffer we just grabbed for subsequent small requests
262 // even if not for this one.
263 } else {
264 // We're used up.
265 _to_space_full = true;
266 }
267
268 } else {
269 // Too large; allocate the object individually.
270 obj = sp->par_allocate(word_sz);
271 }
272 }
273 return obj;
274 }
275
276
277 void ParScanThreadState::undo_alloc_in_to_space(HeapWord* obj,
278 size_t word_sz) {
279 // Is the alloc in the current alloc buffer?
280 if (to_space_alloc_buffer()->contains(obj)) {
281 assert(to_space_alloc_buffer()->contains(obj + word_sz - 1),
282 "Should contain whole object.");
283 to_space_alloc_buffer()->undo_allocation(obj, word_sz);
284 } else {
285 CollectedHeap::fill_with_object(obj, word_sz);
286 }
287 }
288
289 void ParScanThreadState::print_promotion_failure_size() {
290 if (_promotion_failed_info.has_failed() && PrintPromotionFailure) {
291 gclog_or_tty->print(" (%d: promotion failure size = " SIZE_FORMAT ") ",
292 _thread_num, _promotion_failed_info.first_size());
293 }
294 }
295
296 class ParScanThreadStateSet: private ResourceArray {
297 public:
298 // Initializes states for the specified number of threads;
299 ParScanThreadStateSet(int num_threads,
300 Space& to_space,
301 ParNewGeneration& gen,
302 Generation& old_gen,
303 ObjToScanQueueSet& queue_set,
304 Stack<oop, mtGC>* overflow_stacks_,
305 size_t desired_plab_sz,
306 ParallelTaskTerminator& term);
307
308 ~ParScanThreadStateSet() { TASKQUEUE_STATS_ONLY(reset_stats()); }
309
310 inline ParScanThreadState& thread_state(int i);
311
312 void trace_promotion_failed(YoungGCTracer& gc_tracer);
313 void reset(int active_workers, bool promotion_failed);
314 void flush();
315
316 #if TASKQUEUE_STATS
317 static void
318 print_termination_stats_hdr(outputStream* const st = gclog_or_tty);
319 void print_termination_stats(outputStream* const st = gclog_or_tty);
320 static void
321 print_taskqueue_stats_hdr(outputStream* const st = gclog_or_tty);
322 void print_taskqueue_stats(outputStream* const st = gclog_or_tty);
323 void reset_stats();
324 #endif // TASKQUEUE_STATS
325
326 private:
327 ParallelTaskTerminator& _term;
328 ParNewGeneration& _gen;
329 Generation& _next_gen;
330 public:
331 bool is_valid(int id) const { return id < length(); }
332 ParallelTaskTerminator* terminator() { return &_term; }
333 };
334
335
336 ParScanThreadStateSet::ParScanThreadStateSet(
337 int num_threads, Space& to_space, ParNewGeneration& gen,
338 Generation& old_gen, ObjToScanQueueSet& queue_set,
339 Stack<oop, mtGC>* overflow_stacks,
340 size_t desired_plab_sz, ParallelTaskTerminator& term)
341 : ResourceArray(sizeof(ParScanThreadState), num_threads),
342 _gen(gen), _next_gen(old_gen), _term(term)
343 {
344 assert(num_threads > 0, "sanity check!");
345 assert(ParGCUseLocalOverflow == (overflow_stacks != NULL),
346 "overflow_stack allocation mismatch");
347 // Initialize states.
348 for (int i = 0; i < num_threads; ++i) {
349 new ((ParScanThreadState*)_data + i)
350 ParScanThreadState(&to_space, &gen, &old_gen, i, &queue_set,
351 overflow_stacks, desired_plab_sz, term);
352 }
353 }
354
355 inline ParScanThreadState& ParScanThreadStateSet::thread_state(int i)
356 {
357 assert(i >= 0 && i < length(), "sanity check!");
358 return ((ParScanThreadState*)_data)[i];
359 }
360
361 void ParScanThreadStateSet::trace_promotion_failed(YoungGCTracer& gc_tracer) {
362 for (int i = 0; i < length(); ++i) {
363 if (thread_state(i).promotion_failed()) {
364 gc_tracer.report_promotion_failed(thread_state(i).promotion_failed_info());
365 thread_state(i).promotion_failed_info().reset();
366 }
367 }
368 }
369
370 void ParScanThreadStateSet::reset(int active_threads, bool promotion_failed)
371 {
963 // Capture heap used before collection (for printing).
964 size_t gch_prev_used = gch->used();
965
966 SpecializationStats::clear();
967
968 age_table()->clear();
969 to()->clear(SpaceDecorator::Mangle);
970
971 gch->save_marks();
972 assert(workers != NULL, "Need parallel worker threads.");
973 int n_workers = active_workers;
974
975 // Set the correct parallelism (number of queues) in the reference processor
976 ref_processor()->set_active_mt_degree(n_workers);
977
978 // Always set the terminator for the active number of workers
979 // because only those workers go through the termination protocol.
980 ParallelTaskTerminator _term(n_workers, task_queues());
981 ParScanThreadStateSet thread_state_set(workers->active_workers(),
982 *to(), *this, *_next_gen, *task_queues(),
983 _overflow_stacks, desired_plab_sz(), _term);
984
985 ParNewGenTask tsk(this, _next_gen, reserved().end(), &thread_state_set);
986 gch->set_par_threads(n_workers);
987 gch->rem_set()->prepare_for_younger_refs_iterate(true);
988 // It turns out that even when we're using 1 thread, doing the work in a
989 // separate thread causes wide variance in run times. We can't help this
990 // in the multi-threaded case, but we special-case n=1 here to get
991 // repeatable measurements of the 1-thread overhead of the parallel code.
992 if (n_workers > 1) {
993 GenCollectedHeap::StrongRootsScope srs(gch);
994 workers->run_task(&tsk);
995 } else {
996 GenCollectedHeap::StrongRootsScope srs(gch);
997 tsk.work(0);
998 }
999 thread_state_set.reset(0 /* Bad value in debug if not reset */,
1000 promotion_failed());
1001
1002 // Process (weak) reference objects found during scavenge.
1003 ReferenceProcessor* rp = ref_processor();
1163 ParScanThreadState* par_scan_state, oop old, size_t sz, markOop m) {
1164 // In the sequential version, this assert also says that the object is
1165 // not forwarded. That might not be the case here. It is the case that
1166 // the caller observed it to be not forwarded at some time in the past.
1167 assert(is_in_reserved(old), "shouldn't be scavenging this oop");
1168
1169 // The sequential code read "old->age()" below. That doesn't work here,
1170 // since the age is in the mark word, and that might be overwritten with
1171 // a forwarding pointer by a parallel thread. So we must save the mark
1172 // word in a local and then analyze it.
1173 oopDesc dummyOld;
1174 dummyOld.set_mark(m);
1175 assert(!dummyOld.is_forwarded(),
1176 "should not be called with forwarding pointer mark word.");
1177
1178 oop new_obj = NULL;
1179 oop forward_ptr;
1180
1181 // Try allocating obj in to-space (unless too old)
1182 if (dummyOld.age() < tenuring_threshold()) {
1183 new_obj = (oop)par_scan_state->alloc_in_to_space(sz);
1184 if (new_obj == NULL) {
1185 set_survivor_overflow(true);
1186 }
1187 }
1188
1189 if (new_obj == NULL) {
1190 // Either to-space is full or we decided to promote
1191 // try allocating obj tenured
1192
1193 // Attempt to install a null forwarding pointer (atomically),
1194 // to claim the right to install the real forwarding pointer.
1195 forward_ptr = old->forward_to_atomic(ClaimedForwardPtr);
1196 if (forward_ptr != NULL) {
1197 // someone else beat us to it.
1198 return real_forwardee(old);
1199 }
1200
1201 new_obj = _next_gen->par_promote(par_scan_state->thread_num(),
1202 old, m, sz);
1203
1290 // In the sequential version, this assert also says that the object is
1291 // not forwarded. That might not be the case here. It is the case that
1292 // the caller observed it to be not forwarded at some time in the past.
1293 assert(is_in_reserved(old), "shouldn't be scavenging this oop");
1294
1295 // The sequential code read "old->age()" below. That doesn't work here,
1296 // since the age is in the mark word, and that might be overwritten with
1297 // a forwarding pointer by a parallel thread. So we must save the mark
1298 // word here, install it in a local oopDesc, and then analyze it.
1299 oopDesc dummyOld;
1300 dummyOld.set_mark(m);
1301 assert(!dummyOld.is_forwarded(),
1302 "should not be called with forwarding pointer mark word.");
1303
1304 bool failed_to_promote = false;
1305 oop new_obj = NULL;
1306 oop forward_ptr;
1307
1308 // Try allocating obj in to-space (unless too old)
1309 if (dummyOld.age() < tenuring_threshold()) {
1310 new_obj = (oop)par_scan_state->alloc_in_to_space(sz);
1311 if (new_obj == NULL) {
1312 set_survivor_overflow(true);
1313 }
1314 }
1315
1316 if (new_obj == NULL) {
1317 // Either to-space is full or we decided to promote
1318 // try allocating obj tenured
1319 new_obj = _next_gen->par_promote(par_scan_state->thread_num(),
1320 old, m, sz);
1321
1322 if (new_obj == NULL) {
1323 // promotion failed, forward to self
1324 forward_ptr = old->forward_to_atomic(old);
1325 new_obj = old;
1326
1327 if (forward_ptr != NULL) {
1328 return forward_ptr; // someone else succeeded
1329 }
1330
|
52 #include "runtime/handles.inline.hpp"
53 #include "runtime/java.hpp"
54 #include "runtime/thread.inline.hpp"
55 #include "utilities/copy.hpp"
56 #include "utilities/globalDefinitions.hpp"
57 #include "utilities/workgroup.hpp"
58
59 PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
60
61 #ifdef _MSC_VER
62 #pragma warning( push )
63 #pragma warning( disable:4355 ) // 'this' : used in base member initializer list
64 #endif
65 ParScanThreadState::ParScanThreadState(Space* to_space_,
66 ParNewGeneration* gen_,
67 Generation* old_gen_,
68 int thread_num_,
69 ObjToScanQueueSet* work_queue_set_,
70 Stack<oop, mtGC>* overflow_stacks_,
71 size_t desired_plab_sz_,
72 ParNewTracer* gc_tracer,
73 ParallelTaskTerminator& term_) :
74 _to_space(to_space_), _old_gen(old_gen_), _young_gen(gen_), _thread_num(thread_num_),
75 _work_queue(work_queue_set_->queue(thread_num_)), _to_space_full(false),
76 _overflow_stack(overflow_stacks_ ? overflow_stacks_ + thread_num_ : NULL),
77 _ageTable(false), // false ==> not the global age table, no perf data.
78 _to_space_alloc_buffer(desired_plab_sz_),
79 _gc_tracer(gc_tracer),
80 _to_space_closure(gen_, this), _old_gen_closure(gen_, this),
81 _to_space_root_closure(gen_, this), _old_gen_root_closure(gen_, this),
82 _older_gen_closure(gen_, this),
83 _evacuate_followers(this, &_to_space_closure, &_old_gen_closure,
84 &_to_space_root_closure, gen_, &_old_gen_root_closure,
85 work_queue_set_, &term_),
86 _is_alive_closure(gen_), _scan_weak_ref_closure(gen_, this),
87 _keep_alive_closure(&_scan_weak_ref_closure),
88 _strong_roots_time(0.0), _term_time(0.0)
89 {
90 #if TASKQUEUE_STATS
91 _term_attempts = 0;
92 _overflow_refills = 0;
93 _overflow_refill_objs = 0;
94 #endif // TASKQUEUE_STATS
95
96 _survivor_chunk_array =
97 (ChunkArray*) old_gen()->get_data_recorder(thread_num());
98 _hash_seed = 17; // Might want to take time-based random value.
99 _start = os::elapsedTime();
207 assert(Universe::heap()->is_in_reserved(cur), "Should be in heap");
208 assert(!old_gen()->is_in_reserved(cur), "Should be in young gen");
209 assert(Universe::heap()->is_in_reserved(obj_to_push), "Should be in heap");
210 if (should_be_partially_scanned(obj_to_push, cur)) {
211 assert(arrayOop(cur)->length() == 0, "entire array remaining to be scanned");
212 obj_to_push = cur;
213 }
214 bool ok = queue->push(obj_to_push);
215 assert(ok, "Should have succeeded");
216 }
217 assert(young_gen()->overflow_list() == NULL, "Error");
218 return num_take_elems > 0; // was something transferred?
219 }
220
221 void ParScanThreadState::push_on_overflow_stack(oop p) {
222 assert(ParGCUseLocalOverflow, "Else should not call");
223 overflow_stack()->push(p);
224 assert(young_gen()->overflow_list() == NULL, "Error");
225 }
226
227 HeapWord* ParScanThreadState::alloc_in_to_space_slow(size_t word_sz, oop const old, uint age) {
228
229 // Otherwise, if the object is small enough, try to reallocate the
230 // buffer.
231 HeapWord* obj = NULL;
232 if (!_to_space_full) {
233 ParGCAllocBuffer* const plab = to_space_alloc_buffer();
234 Space* const sp = to_space();
235 if (word_sz * 100 <
236 ParallelGCBufferWastePct * plab->word_sz()) {
237 // Is small enough; abandon this buffer and start a new one.
238 plab->retire(false, false);
239 size_t buf_size = plab->word_sz();
240 HeapWord* buf_space = sp->par_allocate(buf_size);
241 if (buf_space == NULL) {
242 const size_t min_bytes =
243 ParGCAllocBuffer::min_size() << LogHeapWordSize;
244 size_t free_bytes = sp->free();
245 while(buf_space == NULL && free_bytes >= min_bytes) {
246 buf_size = free_bytes >> LogHeapWordSize;
247 assert(buf_size == (size_t)align_object_size(buf_size),
248 "Invariant");
249 buf_space = sp->par_allocate(buf_size);
250 free_bytes = sp->free();
251 }
252 }
253 if (buf_space != NULL) {
254 plab->set_word_size(buf_size);
255 plab->set_buf(buf_space);
256 record_survivor_plab(buf_space, buf_size);
257 gc_tracer()->report_promotion_to_new_plab(old, age, false, buf_size);
258 obj = plab->allocate_aligned(word_sz, SurvivorAlignmentInBytes);
259 // Note that we cannot compare buf_size < word_sz below
260 // because of AlignmentReserve (see ParGCAllocBuffer::allocate()).
261 assert(obj != NULL || plab->words_remaining() < word_sz,
262 "Else should have been able to allocate");
263 // It's conceivable that we may be able to use the
264 // buffer we just grabbed for subsequent small requests
265 // even if not for this one.
266 } else {
267 // We're used up.
268 _to_space_full = true;
269 }
270
271 } else {
272 // Too large; allocate the object individually.
273 gc_tracer()->report_promotion_to_new_plab(old, age, false, old->size());
274 obj = sp->par_allocate(word_sz);
275 }
276 }
277 return obj;
278 }
279
280
281 void ParScanThreadState::undo_alloc_in_to_space(HeapWord* obj,
282 size_t word_sz) {
283 // Is the alloc in the current alloc buffer?
284 if (to_space_alloc_buffer()->contains(obj)) {
285 assert(to_space_alloc_buffer()->contains(obj + word_sz - 1),
286 "Should contain whole object.");
287 to_space_alloc_buffer()->undo_allocation(obj, word_sz);
288 } else {
289 CollectedHeap::fill_with_object(obj, word_sz);
290 }
291 }
292
293 void ParScanThreadState::print_promotion_failure_size() {
294 if (_promotion_failed_info.has_failed() && PrintPromotionFailure) {
295 gclog_or_tty->print(" (%d: promotion failure size = " SIZE_FORMAT ") ",
296 _thread_num, _promotion_failed_info.first_size());
297 }
298 }
299
300 class ParScanThreadStateSet: private ResourceArray {
301 public:
302 // Initializes states for the specified number of threads;
303 ParScanThreadStateSet(int num_threads,
304 Space& to_space,
305 ParNewGeneration& gen,
306 Generation& old_gen,
307 ObjToScanQueueSet& queue_set,
308 Stack<oop, mtGC>* overflow_stacks_,
309 size_t desired_plab_sz,
310 ParNewTracer* gc_tracer,
311 ParallelTaskTerminator& term);
312
313 ~ParScanThreadStateSet() { TASKQUEUE_STATS_ONLY(reset_stats()); }
314
315 inline ParScanThreadState& thread_state(int i);
316
317 void trace_promotion_failed(YoungGCTracer& gc_tracer);
318 void reset(int active_workers, bool promotion_failed);
319 void flush();
320
321 #if TASKQUEUE_STATS
322 static void
323 print_termination_stats_hdr(outputStream* const st = gclog_or_tty);
324 void print_termination_stats(outputStream* const st = gclog_or_tty);
325 static void
326 print_taskqueue_stats_hdr(outputStream* const st = gclog_or_tty);
327 void print_taskqueue_stats(outputStream* const st = gclog_or_tty);
328 void reset_stats();
329 #endif // TASKQUEUE_STATS
330
331 private:
332 ParallelTaskTerminator& _term;
333 ParNewGeneration& _gen;
334 Generation& _next_gen;
335 public:
336 bool is_valid(int id) const { return id < length(); }
337 ParallelTaskTerminator* terminator() { return &_term; }
338 };
339
340
341 ParScanThreadStateSet::ParScanThreadStateSet(
342 int num_threads, Space& to_space, ParNewGeneration& gen,
343 Generation& old_gen, ObjToScanQueueSet& queue_set,
344 Stack<oop, mtGC>* overflow_stacks,
345 size_t desired_plab_sz,
346 ParNewTracer* gc_tracer, ParallelTaskTerminator& term)
347 : ResourceArray(sizeof(ParScanThreadState), num_threads),
348 _gen(gen), _next_gen(old_gen), _term(term)
349 {
350 assert(num_threads > 0, "sanity check!");
351 assert(ParGCUseLocalOverflow == (overflow_stacks != NULL),
352 "overflow_stack allocation mismatch");
353 // Initialize states.
354 for (int i = 0; i < num_threads; ++i) {
355 new ((ParScanThreadState*)_data + i)
356 ParScanThreadState(&to_space, &gen, &old_gen, i, &queue_set,
357 overflow_stacks, desired_plab_sz, gc_tracer, term);
358 }
359 }
360
361 inline ParScanThreadState& ParScanThreadStateSet::thread_state(int i)
362 {
363 assert(i >= 0 && i < length(), "sanity check!");
364 return ((ParScanThreadState*)_data)[i];
365 }
366
367 void ParScanThreadStateSet::trace_promotion_failed(YoungGCTracer& gc_tracer) {
368 for (int i = 0; i < length(); ++i) {
369 if (thread_state(i).promotion_failed()) {
370 gc_tracer.report_promotion_failed(thread_state(i).promotion_failed_info());
371 thread_state(i).promotion_failed_info().reset();
372 }
373 }
374 }
375
376 void ParScanThreadStateSet::reset(int active_threads, bool promotion_failed)
377 {
969 // Capture heap used before collection (for printing).
970 size_t gch_prev_used = gch->used();
971
972 SpecializationStats::clear();
973
974 age_table()->clear();
975 to()->clear(SpaceDecorator::Mangle);
976
977 gch->save_marks();
978 assert(workers != NULL, "Need parallel worker threads.");
979 int n_workers = active_workers;
980
981 // Set the correct parallelism (number of queues) in the reference processor
982 ref_processor()->set_active_mt_degree(n_workers);
983
984 // Always set the terminator for the active number of workers
985 // because only those workers go through the termination protocol.
986 ParallelTaskTerminator _term(n_workers, task_queues());
987 ParScanThreadStateSet thread_state_set(workers->active_workers(),
988 *to(), *this, *_next_gen, *task_queues(),
989 _overflow_stacks, desired_plab_sz(), &gc_tracer, _term);
990
991 ParNewGenTask tsk(this, _next_gen, reserved().end(), &thread_state_set);
992 gch->set_par_threads(n_workers);
993 gch->rem_set()->prepare_for_younger_refs_iterate(true);
994 // It turns out that even when we're using 1 thread, doing the work in a
995 // separate thread causes wide variance in run times. We can't help this
996 // in the multi-threaded case, but we special-case n=1 here to get
997 // repeatable measurements of the 1-thread overhead of the parallel code.
998 if (n_workers > 1) {
999 GenCollectedHeap::StrongRootsScope srs(gch);
1000 workers->run_task(&tsk);
1001 } else {
1002 GenCollectedHeap::StrongRootsScope srs(gch);
1003 tsk.work(0);
1004 }
1005 thread_state_set.reset(0 /* Bad value in debug if not reset */,
1006 promotion_failed());
1007
1008 // Process (weak) reference objects found during scavenge.
1009 ReferenceProcessor* rp = ref_processor();
1169 ParScanThreadState* par_scan_state, oop old, size_t sz, markOop m) {
1170 // In the sequential version, this assert also says that the object is
1171 // not forwarded. That might not be the case here. It is the case that
1172 // the caller observed it to be not forwarded at some time in the past.
1173 assert(is_in_reserved(old), "shouldn't be scavenging this oop");
1174
1175 // The sequential code read "old->age()" below. That doesn't work here,
1176 // since the age is in the mark word, and that might be overwritten with
1177 // a forwarding pointer by a parallel thread. So we must save the mark
1178 // word in a local and then analyze it.
1179 oopDesc dummyOld;
1180 dummyOld.set_mark(m);
1181 assert(!dummyOld.is_forwarded(),
1182 "should not be called with forwarding pointer mark word.");
1183
1184 oop new_obj = NULL;
1185 oop forward_ptr;
1186
1187 // Try allocating obj in to-space (unless too old)
1188 if (dummyOld.age() < tenuring_threshold()) {
1189 new_obj = (oop)par_scan_state->alloc_in_to_space(sz, old, dummyOld.age());
1190 if (new_obj == NULL) {
1191 set_survivor_overflow(true);
1192 }
1193 }
1194
1195 if (new_obj == NULL) {
1196 // Either to-space is full or we decided to promote
1197 // try allocating obj tenured
1198
1199 // Attempt to install a null forwarding pointer (atomically),
1200 // to claim the right to install the real forwarding pointer.
1201 forward_ptr = old->forward_to_atomic(ClaimedForwardPtr);
1202 if (forward_ptr != NULL) {
1203 // someone else beat us to it.
1204 return real_forwardee(old);
1205 }
1206
1207 new_obj = _next_gen->par_promote(par_scan_state->thread_num(),
1208 old, m, sz);
1209
1296 // In the sequential version, this assert also says that the object is
1297 // not forwarded. That might not be the case here. It is the case that
1298 // the caller observed it to be not forwarded at some time in the past.
1299 assert(is_in_reserved(old), "shouldn't be scavenging this oop");
1300
1301 // The sequential code read "old->age()" below. That doesn't work here,
1302 // since the age is in the mark word, and that might be overwritten with
1303 // a forwarding pointer by a parallel thread. So we must save the mark
1304 // word here, install it in a local oopDesc, and then analyze it.
1305 oopDesc dummyOld;
1306 dummyOld.set_mark(m);
1307 assert(!dummyOld.is_forwarded(),
1308 "should not be called with forwarding pointer mark word.");
1309
1310 bool failed_to_promote = false;
1311 oop new_obj = NULL;
1312 oop forward_ptr;
1313
1314 // Try allocating obj in to-space (unless too old)
1315 if (dummyOld.age() < tenuring_threshold()) {
1316 new_obj = (oop)par_scan_state->alloc_in_to_space(sz, old, dummyOld.age());
1317 if (new_obj == NULL) {
1318 set_survivor_overflow(true);
1319 }
1320 }
1321
1322 if (new_obj == NULL) {
1323 // Either to-space is full or we decided to promote
1324 // try allocating obj tenured
1325 new_obj = _next_gen->par_promote(par_scan_state->thread_num(),
1326 old, m, sz);
1327
1328 if (new_obj == NULL) {
1329 // promotion failed, forward to self
1330 forward_ptr = old->forward_to_atomic(old);
1331 new_obj = old;
1332
1333 if (forward_ptr != NULL) {
1334 return forward_ptr; // someone else succeeded
1335 }
1336
|