< prev index next >

src/share/vm/gc/shared/referenceProcessor.cpp

Print this page
rev 11747 : [mq]: per.hotspot.patch


 272     size_t _count;
 273   public:
 274     CountHandleClosure(): _count(0) {}
 275     void do_oop(oop* unused)       { _count++; }
 276     void do_oop(narrowOop* unused) { ShouldNotReachHere(); }
 277     size_t count() { return _count; }
 278   };
 279   CountHandleClosure global_handle_count;
 280   JNIHandles::weak_oops_do(&global_handle_count);
 281   return global_handle_count.count();
 282 }
 283 #endif
 284 
 285 void ReferenceProcessor::process_phaseJNI(BoolObjectClosure* is_alive,
 286                                           OopClosure*        keep_alive,
 287                                           VoidClosure*       complete_gc) {
 288   JNIHandles::weak_oops_do(is_alive, keep_alive);
 289   complete_gc->do_void();
 290 }
 291 
 292 
 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
 302   // clear the decks for the next collection (cycle).
 303   ref->enqueue_discovered_reflists((HeapWord*)pending_list_addr, 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 
 308   // Stop treating discovered references specially.
 309   ref->disable_discovery();
 310 
 311   // Return true if new pending references were added
 312   return old_pending_list_value != *pending_list_addr;
 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
 326   // (java.lang.ref.Reference.discovered), self-loop their "next" field
 327   // thus distinguishing them from active References, then
 328   // prepend them to the pending list.
 329   //
 330   // The Java threads will see the Reference objects linked together through
 331   // the discovered field. Instead of trying to do the write barrier updates
 332   // in all places in the reference processor where we manipulate the discovered
 333   // field we make sure to do the barrier here where we anyway iterate through
 334   // all linked Reference objects. Note that it is important to not dirty any
 335   // cards during reference processing since this will cause card table
 336   // verification to fail for G1.
 337   log_develop_trace(gc, ref)("ReferenceProcessor::enqueue_discovered_reflist list " INTPTR_FORMAT, p2i(&refs_list));
 338 
 339   oop obj = NULL;
 340   oop next_d = refs_list.head();
 341   // Walk down the list, self-looping the next field
 342   // so that the References are not considered active.
 343   while (obj != next_d) {
 344     obj = next_d;
 345     assert(obj->is_instance(), "should be an instance object");
 346     assert(InstanceKlass::cast(obj->klass())->is_reference_instance_klass(), "should be reference object");
 347     next_d = java_lang_ref_Reference::discovered(obj);
 348     log_develop_trace(gc, ref)("        obj " INTPTR_FORMAT "/next_d " INTPTR_FORMAT, p2i(obj), p2i(next_d));
 349     assert(java_lang_ref_Reference::next(obj) == NULL,
 350            "Reference not active; should not be discovered");
 351     // Self-loop next, so as to make Ref not active.
 352     java_lang_ref_Reference::set_next_raw(obj, obj);
 353     if (next_d != obj) {
 354       oopDesc::bs()->write_ref_field(java_lang_ref_Reference::discovered_addr(obj), next_d);
 355     } else {
 356       // This is the last object.
 357       // Swap refs_list into pending_list_addr and
 358       // set obj's discovered to what we read from pending_list_addr.
 359       oop old = oopDesc::atomic_exchange_oop(refs_list.head(), pending_list_addr);
 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
 362       oopDesc::bs()->write_ref_field(java_lang_ref_Reference::discovered_addr(obj), old);
 363     }
 364   }
 365 }
 366 
 367 // Parallel enqueue task
 368 class RefProcEnqueueTask: public AbstractRefProcTaskExecutor::EnqueueTask {
 369 public:
 370   RefProcEnqueueTask(ReferenceProcessor& ref_processor,
 371                      DiscoveredList      discovered_refs[],
 372                      HeapWord*           pending_list_addr,
 373                      int                 n_queues)
 374     : EnqueueTask(ref_processor, discovered_refs,
 375                   pending_list_addr, n_queues)
 376   { }
 377 
 378   virtual void work(unsigned int work_id) {
 379     assert(work_id < (unsigned int)_ref_processor.max_num_q(), "Index out-of-bounds");
 380     // Simplest first cut: static partitioning.
 381     int index = work_id;
 382     // The increment on "index" must correspond to the maximum number of queues
 383     // (n_queues) with which that ReferenceProcessor was created.  That
 384     // is because of the "clever" way the discovered references lists were
 385     // allocated and are indexed into.
 386     assert(_n_queues == (int) _ref_processor.max_num_q(), "Different number not expected");
 387     for (int j = 0;
 388          j < ReferenceProcessor::number_of_subclasses_of_ref();
 389          j++, index += _n_queues) {
 390       _ref_processor.enqueue_discovered_reflist(
 391         _refs_lists[index], _pending_list_addr);
 392       _refs_lists[index].set_head(NULL);
 393       _refs_lists[index].set_length(0);
 394     }
 395   }
 396 };
 397 
 398 // Enqueue references that are not made active again
 399 void ReferenceProcessor::enqueue_discovered_reflists(HeapWord* pending_list_addr,
 400   AbstractRefProcTaskExecutor* task_executor) {
 401   if (_processing_is_mt && task_executor != NULL) {
 402     // Parallel code
 403     RefProcEnqueueTask tsk(*this, _discovered_refs,
 404                            pending_list_addr, _max_num_q);
 405     task_executor->execute(tsk);
 406   } else {
 407     // Serial code: call the parent class's implementation
 408     for (uint i = 0; i < _max_num_q * number_of_subclasses_of_ref(); i++) {
 409       enqueue_discovered_reflist(_discovered_refs[i], pending_list_addr);
 410       _discovered_refs[i].set_head(NULL);
 411       _discovered_refs[i].set_length(0);
 412     }
 413   }
 414 }
 415 
 416 void DiscoveredListIterator::load_ptrs(DEBUG_ONLY(bool allow_null_referent)) {
 417   _discovered_addr = java_lang_ref_Reference::discovered_addr(_ref);
 418   oop discovered = java_lang_ref_Reference::discovered(_ref);
 419   assert(_discovered_addr && discovered->is_oop_or_null(),
 420          "Expected an oop or NULL for discovered field at " PTR_FORMAT, p2i(discovered));
 421   _next = discovered;
 422   _referent_addr = java_lang_ref_Reference::referent_addr(_ref);
 423   _referent = java_lang_ref_Reference::referent(_ref);
 424   assert(Universe::heap()->is_in_reserved_or_null(_referent),
 425          "Wrong oop found in java.lang.Reference object");
 426   assert(allow_null_referent ?
 427              _referent->is_oop_or_null()
 428            : _referent->is_oop(),
 429          "Expected an oop%s for referent field at " PTR_FORMAT,




 272     size_t _count;
 273   public:
 274     CountHandleClosure(): _count(0) {}
 275     void do_oop(oop* unused)       { _count++; }
 276     void do_oop(narrowOop* unused) { ShouldNotReachHere(); }
 277     size_t count() { return _count; }
 278   };
 279   CountHandleClosure global_handle_count;
 280   JNIHandles::weak_oops_do(&global_handle_count);
 281   return global_handle_count.count();
 282 }
 283 #endif
 284 
 285 void ReferenceProcessor::process_phaseJNI(BoolObjectClosure* is_alive,
 286                                           OopClosure*        keep_alive,
 287                                           VoidClosure*       complete_gc) {
 288   JNIHandles::weak_oops_do(is_alive, keep_alive);
 289   complete_gc->do_void();
 290 }
 291 
 292 void ReferenceProcessor::enqueue_discovered_references(AbstractRefProcTaskExecutor* task_executor) {








 293   // Enqueue references that are not made active again, and
 294   // clear the decks for the next collection (cycle).
 295   enqueue_discovered_reflists(task_executor);



 296 
 297   // Stop treating discovered references specially.
 298   disable_discovery();











 299 }
 300 
 301 void ReferenceProcessor::enqueue_discovered_reflist(DiscoveredList& refs_list) {

 302   // Given a list of refs linked through the "discovered" field
 303   // (java.lang.ref.Reference.discovered), self-loop their "next" field
 304   // thus distinguishing them from active References, then
 305   // prepend them to the pending list.
 306   //
 307   // The Java threads will see the Reference objects linked together through
 308   // the discovered field. Instead of trying to do the write barrier updates
 309   // in all places in the reference processor where we manipulate the discovered
 310   // field we make sure to do the barrier here where we anyway iterate through
 311   // all linked Reference objects. Note that it is important to not dirty any
 312   // cards during reference processing since this will cause card table
 313   // verification to fail for G1.
 314   log_develop_trace(gc, ref)("ReferenceProcessor::enqueue_discovered_reflist list " INTPTR_FORMAT, p2i(&refs_list));
 315 
 316   oop obj = NULL;
 317   oop next_d = refs_list.head();
 318   // Walk down the list, self-looping the next field
 319   // so that the References are not considered active.
 320   while (obj != next_d) {
 321     obj = next_d;
 322     assert(obj->is_instance(), "should be an instance object");
 323     assert(InstanceKlass::cast(obj->klass())->is_reference_instance_klass(), "should be reference object");
 324     next_d = java_lang_ref_Reference::discovered(obj);
 325     log_develop_trace(gc, ref)("        obj " INTPTR_FORMAT "/next_d " INTPTR_FORMAT, p2i(obj), p2i(next_d));
 326     assert(java_lang_ref_Reference::next(obj) == NULL,
 327            "Reference not active; should not be discovered");
 328     // Self-loop next, so as to make Ref not active.
 329     java_lang_ref_Reference::set_next_raw(obj, obj);
 330     if (next_d != obj) {
 331       oopDesc::bs()->write_ref_field(java_lang_ref_Reference::discovered_addr(obj), next_d);
 332     } else {
 333       // This is the last object.
 334       // Swap refs_list into pending list and set obj's
 335       // discovered to what we read from the pending list.
 336       oop old = Universe::swap_reference_pending_list(refs_list.head());

 337       java_lang_ref_Reference::set_discovered_raw(obj, old); // old may be NULL
 338       oopDesc::bs()->write_ref_field(java_lang_ref_Reference::discovered_addr(obj), old);
 339     }
 340   }
 341 }
 342 
 343 // Parallel enqueue task
 344 class RefProcEnqueueTask: public AbstractRefProcTaskExecutor::EnqueueTask {
 345 public:
 346   RefProcEnqueueTask(ReferenceProcessor& ref_processor,
 347                      DiscoveredList      discovered_refs[],

 348                      int                 n_queues)
 349     : EnqueueTask(ref_processor, discovered_refs, n_queues)

 350   { }
 351 
 352   virtual void work(unsigned int work_id) {
 353     assert(work_id < (unsigned int)_ref_processor.max_num_q(), "Index out-of-bounds");
 354     // Simplest first cut: static partitioning.
 355     int index = work_id;
 356     // The increment on "index" must correspond to the maximum number of queues
 357     // (n_queues) with which that ReferenceProcessor was created.  That
 358     // is because of the "clever" way the discovered references lists were
 359     // allocated and are indexed into.
 360     assert(_n_queues == (int) _ref_processor.max_num_q(), "Different number not expected");
 361     for (int j = 0;
 362          j < ReferenceProcessor::number_of_subclasses_of_ref();
 363          j++, index += _n_queues) {
 364       _ref_processor.enqueue_discovered_reflist(_refs_lists[index]);

 365       _refs_lists[index].set_head(NULL);
 366       _refs_lists[index].set_length(0);
 367     }
 368   }
 369 };
 370 
 371 // Enqueue references that are not made active again
 372 void ReferenceProcessor::enqueue_discovered_reflists(AbstractRefProcTaskExecutor* task_executor) {

 373   if (_processing_is_mt && task_executor != NULL) {
 374     // Parallel code
 375     RefProcEnqueueTask tsk(*this, _discovered_refs, _max_num_q);

 376     task_executor->execute(tsk);
 377   } else {
 378     // Serial code: call the parent class's implementation
 379     for (uint i = 0; i < _max_num_q * number_of_subclasses_of_ref(); i++) {
 380       enqueue_discovered_reflist(_discovered_refs[i]);
 381       _discovered_refs[i].set_head(NULL);
 382       _discovered_refs[i].set_length(0);
 383     }
 384   }
 385 }
 386 
 387 void DiscoveredListIterator::load_ptrs(DEBUG_ONLY(bool allow_null_referent)) {
 388   _discovered_addr = java_lang_ref_Reference::discovered_addr(_ref);
 389   oop discovered = java_lang_ref_Reference::discovered(_ref);
 390   assert(_discovered_addr && discovered->is_oop_or_null(),
 391          "Expected an oop or NULL for discovered field at " PTR_FORMAT, p2i(discovered));
 392   _next = discovered;
 393   _referent_addr = java_lang_ref_Reference::referent_addr(_ref);
 394   _referent = java_lang_ref_Reference::referent(_ref);
 395   assert(Universe::heap()->is_in_reserved_or_null(_referent),
 396          "Wrong oop found in java.lang.Reference object");
 397   assert(allow_null_referent ?
 398              _referent->is_oop_or_null()
 399            : _referent->is_oop(),
 400          "Expected an oop%s for referent field at " PTR_FORMAT,


< prev index next >