287 VoidClosure* complete_gc) { |
287 VoidClosure* complete_gc) { |
288 JNIHandles::weak_oops_do(is_alive, keep_alive); |
288 JNIHandles::weak_oops_do(is_alive, keep_alive); |
289 complete_gc->do_void(); |
289 complete_gc->do_void(); |
290 } |
290 } |
291 |
291 |
292 |
292 void ReferenceProcessor::enqueue_discovered_references(AbstractRefProcTaskExecutor* task_executor) { |
293 template <class T> |
|
294 bool enqueue_discovered_ref_helper(ReferenceProcessor* ref, |
|
295 AbstractRefProcTaskExecutor* task_executor) { |
|
296 |
|
297 // Remember old value of pending references list |
|
298 T* pending_list_addr = (T*)java_lang_ref_Reference::pending_list_addr(); |
|
299 T old_pending_list_value = *pending_list_addr; |
|
300 |
|
301 // Enqueue references that are not made active again, and |
293 // Enqueue references that are not made active again, and |
302 // clear the decks for the next collection (cycle). |
294 // clear the decks for the next collection (cycle). |
303 ref->enqueue_discovered_reflists((HeapWord*)pending_list_addr, task_executor); |
295 enqueue_discovered_reflists(task_executor); |
304 // Do the post-barrier on pending_list_addr missed in |
|
305 // enqueue_discovered_reflist. |
|
306 oopDesc::bs()->write_ref_field(pending_list_addr, oopDesc::load_decode_heap_oop(pending_list_addr)); |
|
307 |
296 |
308 // Stop treating discovered references specially. |
297 // Stop treating discovered references specially. |
309 ref->disable_discovery(); |
298 disable_discovery(); |
310 |
299 } |
311 // Return true if new pending references were added |
300 |
312 return old_pending_list_value != *pending_list_addr; |
301 void ReferenceProcessor::enqueue_discovered_reflist(DiscoveredList& refs_list) { |
313 } |
|
314 |
|
315 bool ReferenceProcessor::enqueue_discovered_references(AbstractRefProcTaskExecutor* task_executor) { |
|
316 if (UseCompressedOops) { |
|
317 return enqueue_discovered_ref_helper<narrowOop>(this, task_executor); |
|
318 } else { |
|
319 return enqueue_discovered_ref_helper<oop>(this, task_executor); |
|
320 } |
|
321 } |
|
322 |
|
323 void ReferenceProcessor::enqueue_discovered_reflist(DiscoveredList& refs_list, |
|
324 HeapWord* pending_list_addr) { |
|
325 // Given a list of refs linked through the "discovered" field |
302 // Given a list of refs linked through the "discovered" field |
326 // (java.lang.ref.Reference.discovered), self-loop their "next" field |
303 // (java.lang.ref.Reference.discovered), self-loop their "next" field |
327 // thus distinguishing them from active References, then |
304 // thus distinguishing them from active References, then |
328 // prepend them to the pending list. |
305 // prepend them to the pending list. |
329 // |
306 // |
352 java_lang_ref_Reference::set_next_raw(obj, obj); |
329 java_lang_ref_Reference::set_next_raw(obj, obj); |
353 if (next_d != obj) { |
330 if (next_d != obj) { |
354 oopDesc::bs()->write_ref_field(java_lang_ref_Reference::discovered_addr(obj), next_d); |
331 oopDesc::bs()->write_ref_field(java_lang_ref_Reference::discovered_addr(obj), next_d); |
355 } else { |
332 } else { |
356 // This is the last object. |
333 // This is the last object. |
357 // Swap refs_list into pending_list_addr and |
334 // Swap refs_list into pending list and set obj's |
358 // set obj's discovered to what we read from pending_list_addr. |
335 // discovered to what we read from the pending list. |
359 oop old = oopDesc::atomic_exchange_oop(refs_list.head(), pending_list_addr); |
336 oop old = Universe::swap_reference_pending_list(refs_list.head()); |
360 // Need post-barrier on pending_list_addr. See enqueue_discovered_ref_helper() above. |
|
361 java_lang_ref_Reference::set_discovered_raw(obj, old); // old may be NULL |
337 java_lang_ref_Reference::set_discovered_raw(obj, old); // old may be NULL |
362 oopDesc::bs()->write_ref_field(java_lang_ref_Reference::discovered_addr(obj), old); |
338 oopDesc::bs()->write_ref_field(java_lang_ref_Reference::discovered_addr(obj), old); |
363 } |
339 } |
364 } |
340 } |
365 } |
341 } |
367 // Parallel enqueue task |
343 // Parallel enqueue task |
368 class RefProcEnqueueTask: public AbstractRefProcTaskExecutor::EnqueueTask { |
344 class RefProcEnqueueTask: public AbstractRefProcTaskExecutor::EnqueueTask { |
369 public: |
345 public: |
370 RefProcEnqueueTask(ReferenceProcessor& ref_processor, |
346 RefProcEnqueueTask(ReferenceProcessor& ref_processor, |
371 DiscoveredList discovered_refs[], |
347 DiscoveredList discovered_refs[], |
372 HeapWord* pending_list_addr, |
|
373 int n_queues) |
348 int n_queues) |
374 : EnqueueTask(ref_processor, discovered_refs, |
349 : EnqueueTask(ref_processor, discovered_refs, n_queues) |
375 pending_list_addr, n_queues) |
|
376 { } |
350 { } |
377 |
351 |
378 virtual void work(unsigned int work_id) { |
352 virtual void work(unsigned int work_id) { |
379 assert(work_id < (unsigned int)_ref_processor.max_num_q(), "Index out-of-bounds"); |
353 assert(work_id < (unsigned int)_ref_processor.max_num_q(), "Index out-of-bounds"); |
380 // Simplest first cut: static partitioning. |
354 // Simplest first cut: static partitioning. |
385 // allocated and are indexed into. |
359 // allocated and are indexed into. |
386 assert(_n_queues == (int) _ref_processor.max_num_q(), "Different number not expected"); |
360 assert(_n_queues == (int) _ref_processor.max_num_q(), "Different number not expected"); |
387 for (int j = 0; |
361 for (int j = 0; |
388 j < ReferenceProcessor::number_of_subclasses_of_ref(); |
362 j < ReferenceProcessor::number_of_subclasses_of_ref(); |
389 j++, index += _n_queues) { |
363 j++, index += _n_queues) { |
390 _ref_processor.enqueue_discovered_reflist( |
364 _ref_processor.enqueue_discovered_reflist(_refs_lists[index]); |
391 _refs_lists[index], _pending_list_addr); |
|
392 _refs_lists[index].set_head(NULL); |
365 _refs_lists[index].set_head(NULL); |
393 _refs_lists[index].set_length(0); |
366 _refs_lists[index].set_length(0); |
394 } |
367 } |
395 } |
368 } |
396 }; |
369 }; |
397 |
370 |
398 // Enqueue references that are not made active again |
371 // Enqueue references that are not made active again |
399 void ReferenceProcessor::enqueue_discovered_reflists(HeapWord* pending_list_addr, |
372 void ReferenceProcessor::enqueue_discovered_reflists(AbstractRefProcTaskExecutor* task_executor) { |
400 AbstractRefProcTaskExecutor* task_executor) { |
|
401 if (_processing_is_mt && task_executor != NULL) { |
373 if (_processing_is_mt && task_executor != NULL) { |
402 // Parallel code |
374 // Parallel code |
403 RefProcEnqueueTask tsk(*this, _discovered_refs, |
375 RefProcEnqueueTask tsk(*this, _discovered_refs, _max_num_q); |
404 pending_list_addr, _max_num_q); |
|
405 task_executor->execute(tsk); |
376 task_executor->execute(tsk); |
406 } else { |
377 } else { |
407 // Serial code: call the parent class's implementation |
378 // Serial code: call the parent class's implementation |
408 for (uint i = 0; i < _max_num_q * number_of_subclasses_of_ref(); i++) { |
379 for (uint i = 0; i < _max_num_q * number_of_subclasses_of_ref(); i++) { |
409 enqueue_discovered_reflist(_discovered_refs[i], pending_list_addr); |
380 enqueue_discovered_reflist(_discovered_refs[i]); |
410 _discovered_refs[i].set_head(NULL); |
381 _discovered_refs[i].set_head(NULL); |
411 _discovered_refs[i].set_length(0); |
382 _discovered_refs[i].set_length(0); |
412 } |
383 } |
413 } |
384 } |
414 } |
385 } |