1 #ifdef USE_PRAGMA_IDENT_SRC
   2 #pragma ident "@(#)instanceRefKlass.cpp 1.90 07/05/29 09:44:20 JVM"
   3 #endif
   4 /*
   5  * Copyright 1997-2006 Sun Microsystems, Inc.  All Rights Reserved.
   6  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   7  *
   8  * This code is free software; you can redistribute it and/or modify it
   9  * under the terms of the GNU General Public License version 2 only, as
  10  * published by the Free Software Foundation.
  11  *
  12  * This code is distributed in the hope that it will be useful, but WITHOUT
  13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  15  * version 2 for more details (a copy is included in the LICENSE file that
  16  * accompanied this code).
  17  *
  18  * You should have received a copy of the GNU General Public License version
  19  * 2 along with this work; if not, write to the Free Software Foundation,
  20  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  21  *
  22  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  23  * CA 95054 USA or visit www.sun.com if you need additional information or
  24  * have any questions.
  25  *  
  26  */
  27 
  28 # include "incls/_precompiled.incl"
  29 # include "incls/_instanceRefKlass.cpp.incl"
  30 
  31 void instanceRefKlass::oop_follow_contents(oop obj) {
  32   oop* referent_addr = java_lang_ref_Reference::referent_addr(obj);
  33   oop referent = *referent_addr;
  34   debug_only(
  35     if(TraceReferenceGC && PrintGCDetails) {
  36       gclog_or_tty->print_cr("instanceRefKlass::oop_follow_contents " INTPTR_FORMAT, (address)obj);
  37     }
  38   )
  39   if (referent != NULL) {
  40     if (!referent->is_gc_marked() &&
  41         MarkSweep::ref_processor()->
  42           discover_reference(obj, reference_type())) {
  43       // reference already enqueued, referent will be traversed later
  44       instanceKlass::oop_follow_contents(obj);
  45       debug_only( 
  46         if(TraceReferenceGC && PrintGCDetails) {
  47           gclog_or_tty->print_cr("       Non NULL enqueued " INTPTR_FORMAT, (address)obj); 
  48         }
  49       )
  50       return;
  51     } else {
  52       // treat referent as normal oop      
  53       debug_only(
  54         if(TraceReferenceGC && PrintGCDetails) {
  55           gclog_or_tty->print_cr("       Non NULL normal " INTPTR_FORMAT, (address)obj);
  56         }
  57       )
  58       MarkSweep::mark_and_push(referent_addr);
  59     }
  60   }
  61   // treat next as normal oop.  next is a link in the pending list.
  62   oop* next_addr = java_lang_ref_Reference::next_addr(obj);
  63   debug_only(
  64     if(TraceReferenceGC && PrintGCDetails) {
  65       gclog_or_tty->print_cr("   Process next as normal " INTPTR_FORMAT, next_addr);
  66     }
  67   )
  68   MarkSweep::mark_and_push(next_addr);
  69   instanceKlass::oop_follow_contents(obj);
  70 }
  71 
  72 #ifndef SERIALGC
  73 void instanceRefKlass::oop_follow_contents(ParCompactionManager* cm,
  74                                            oop obj) {
  75   oop* referent_addr = java_lang_ref_Reference::referent_addr(obj);
  76   oop referent = *referent_addr;
  77   debug_only(
  78     if(TraceReferenceGC && PrintGCDetails) {
  79       gclog_or_tty->print_cr("instanceRefKlass::oop_follow_contents " INTPTR_FORMAT, (address)obj);
  80     }
  81   )
  82   if (referent != NULL) {
  83     if (PSParallelCompact::mark_bitmap()->is_unmarked(referent) &&
  84         PSParallelCompact::ref_processor()->
  85           discover_reference(obj, reference_type())) {
  86       // reference already enqueued, referent will be traversed later
  87       instanceKlass::oop_follow_contents(cm, obj);
  88       debug_only( 
  89         if(TraceReferenceGC && PrintGCDetails) {
  90           gclog_or_tty->print_cr("       Non NULL enqueued " INTPTR_FORMAT, (address)obj); 
  91         }
  92       )
  93       return;
  94     } else {
  95       // treat referent as normal oop      
  96       debug_only(
  97         if(TraceReferenceGC && PrintGCDetails) {
  98           gclog_or_tty->print_cr("       Non NULL normal " INTPTR_FORMAT, (address)obj);
  99         }
 100       )
 101       PSParallelCompact::mark_and_push(cm, referent_addr);
 102     }
 103   }
 104   // treat next as normal oop.  next is a link in the pending list.
 105   oop* next_addr = java_lang_ref_Reference::next_addr(obj);
 106   debug_only(
 107     if(TraceReferenceGC && PrintGCDetails) {
 108       gclog_or_tty->print_cr("   Process next as normal " INTPTR_FORMAT, next_addr);
 109     }
 110   )
 111   PSParallelCompact::mark_and_push(cm, next_addr);
 112   instanceKlass::oop_follow_contents(cm, obj);
 113 }
 114 #endif // SERIALGC
 115 
 116 
 117 int instanceRefKlass::oop_adjust_pointers(oop obj) {
 118   int size = size_helper();
 119   instanceKlass::oop_adjust_pointers(obj);
 120   
 121   oop* referent_addr = java_lang_ref_Reference::referent_addr(obj);
 122   MarkSweep::adjust_pointer(referent_addr);
 123   oop* next_addr = java_lang_ref_Reference::next_addr(obj);
 124   MarkSweep::adjust_pointer(next_addr);
 125   oop* discovered_addr = java_lang_ref_Reference::discovered_addr(obj);
 126   MarkSweep::adjust_pointer(discovered_addr);
 127 
 128 #ifdef ASSERT
 129   if(TraceReferenceGC && PrintGCDetails) {
 130     gclog_or_tty->print_cr("instanceRefKlass::oop_adjust_pointers obj "
 131                            INTPTR_FORMAT, (address)obj);
 132     gclog_or_tty->print_cr("     referent_addr/* " INTPTR_FORMAT " / "
 133                            INTPTR_FORMAT, referent_addr,
 134                            referent_addr ? (address)*referent_addr : NULL);
 135     gclog_or_tty->print_cr("     next_addr/* " INTPTR_FORMAT " / "
 136                            INTPTR_FORMAT, next_addr,
 137                            next_addr ? (address)*next_addr : NULL);
 138     gclog_or_tty->print_cr("     discovered_addr/* " INTPTR_FORMAT " / "
 139                            INTPTR_FORMAT, discovered_addr,
 140                            discovered_addr ? (address)*discovered_addr : NULL);
 141   }
 142 #endif
 143 
 144   return size;
 145 }
 146 
 147 #define InstanceRefKlass_OOP_OOP_ITERATE_DEFN(OopClosureType, nv_suffix)        \
 148                                                                                 \
 149 int instanceRefKlass::                                                          \
 150 oop_oop_iterate##nv_suffix(oop obj, OopClosureType* closure) {                  \
 151   /* Get size before changing pointers */                                       \
 152   SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::irk);\
 153                                                                                 \
 154   int size = instanceKlass::oop_oop_iterate##nv_suffix(obj, closure);           \
 155                                                                                 \
 156   oop* referent_addr = java_lang_ref_Reference::referent_addr(obj);             \
 157   oop referent = *referent_addr;                                                \
 158   if (referent != NULL) {                                                       \
 159     ReferenceProcessor* rp = closure->_ref_processor;                           \
 160     if (!referent->is_gc_marked() && (rp != NULL) &&                            \
 161         rp->discover_reference(obj, reference_type())) {              \
 162       return size;                                                              \
 163     } else {                                                                    \
 164       /* treat referent as normal oop */                                        \
 165       SpecializationStats::record_do_oop_call##nv_suffix(SpecializationStats::irk);\
 166       closure->do_oop##nv_suffix(referent_addr);                                \
 167     }                                                                           \
 168   }                                                                             \
 169                                                                                 \
 170   /* treat next as normal oop */                                                \
 171   oop* next_addr = java_lang_ref_Reference::next_addr(obj);                     \
 172   SpecializationStats::record_do_oop_call##nv_suffix(SpecializationStats::irk); \
 173   closure->do_oop##nv_suffix(next_addr);                                        \
 174   return size;                                                                  \
 175 }
 176 
 177 #define InstanceRefKlass_OOP_OOP_ITERATE_DEFN_m(OopClosureType, nv_suffix)      \
 178                                                                                 \
 179 int instanceRefKlass::                                                          \
 180 oop_oop_iterate##nv_suffix##_m(oop obj,                                         \
 181                                OopClosureType* closure,                         \
 182                                MemRegion mr) {                                  \
 183   SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::irk);\
 184                                                                                 \
 185   int size = instanceKlass::oop_oop_iterate##nv_suffix##_m(obj, closure, mr);   \
 186                                                                                 \
 187   oop* referent_addr = java_lang_ref_Reference::referent_addr(obj);             \
 188   oop referent = *referent_addr;                                                \
 189   if (referent != NULL && mr.contains(referent_addr)) {                         \
 190     ReferenceProcessor* rp = closure->_ref_processor;                           \
 191     if (!referent->is_gc_marked() && (rp != NULL) &&                            \
 192         rp->discover_reference(obj, reference_type())) {              \
 193       return size;                                                              \
 194     } else {                                                                    \
 195       /* treat referent as normal oop */                                        \
 196       SpecializationStats::record_do_oop_call##nv_suffix(SpecializationStats::irk);\
 197       closure->do_oop##nv_suffix(referent_addr);                                \
 198     }                                                                           \
 199   }                                                                             \
 200                                                                                 \
 201   /* treat next as normal oop */                                                \
 202   oop* next_addr = java_lang_ref_Reference::next_addr(obj);                     \
 203   if (mr.contains(next_addr)) {                                                 \
 204     SpecializationStats::record_do_oop_call##nv_suffix(SpecializationStats::irk);\
 205     closure->do_oop##nv_suffix(next_addr);                                      \
 206   }                                                                             \
 207   return size;                                                                  \
 208 }
 209 
 210 ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceRefKlass_OOP_OOP_ITERATE_DEFN)
 211 ALL_OOP_OOP_ITERATE_CLOSURES_3(InstanceRefKlass_OOP_OOP_ITERATE_DEFN)
 212 ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceRefKlass_OOP_OOP_ITERATE_DEFN_m)
 213 ALL_OOP_OOP_ITERATE_CLOSURES_3(InstanceRefKlass_OOP_OOP_ITERATE_DEFN_m)
 214 
 215 
 216 #ifndef SERIALGC
 217 void instanceRefKlass::oop_copy_contents(PSPromotionManager* pm, oop obj) {
 218   assert(!pm->depth_first(), "invariant");
 219   oop* referent_addr = java_lang_ref_Reference::referent_addr(obj);
 220   if (PSScavenge::should_scavenge(*referent_addr)) {
 221     ReferenceProcessor* rp = PSScavenge::reference_processor();
 222     if (rp->discover_reference(obj, reference_type())) {
 223       // reference already enqueued, referent and next will be traversed later
 224       instanceKlass::oop_copy_contents(pm, obj);
 225       return;
 226     } else {
 227       // treat referent as normal oop
 228       pm->claim_or_forward_breadth(referent_addr);
 229     }
 230   }
 231   // treat next as normal oop
 232   oop* next_addr = java_lang_ref_Reference::next_addr(obj);
 233   if (PSScavenge::should_scavenge(*next_addr)) {
 234     pm->claim_or_forward_breadth(next_addr);
 235   }
 236   instanceKlass::oop_copy_contents(pm, obj);
 237 }
 238 
 239 void instanceRefKlass::oop_push_contents(PSPromotionManager* pm, oop obj) {
 240   assert(pm->depth_first(), "invariant");
 241   oop* referent_addr = java_lang_ref_Reference::referent_addr(obj);
 242   if (PSScavenge::should_scavenge(*referent_addr)) {
 243     ReferenceProcessor* rp = PSScavenge::reference_processor();
 244     if (rp->discover_reference(obj, reference_type())) {
 245       // reference already enqueued, referent and next will be traversed later
 246       instanceKlass::oop_push_contents(pm, obj);
 247       return;
 248     } else {
 249       // treat referent as normal oop
 250       pm->claim_or_forward_depth(referent_addr);
 251     }
 252   }
 253   // treat next as normal oop
 254   oop* next_addr = java_lang_ref_Reference::next_addr(obj);
 255   if (PSScavenge::should_scavenge(*next_addr)) {
 256     pm->claim_or_forward_depth(next_addr);
 257   }
 258   instanceKlass::oop_push_contents(pm, obj);
 259 }
 260 
 261 int instanceRefKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) {
 262   instanceKlass::oop_update_pointers(cm, obj);
 263   
 264   oop* referent_addr = java_lang_ref_Reference::referent_addr(obj);
 265   PSParallelCompact::adjust_pointer(referent_addr);
 266   oop* next_addr = java_lang_ref_Reference::next_addr(obj);
 267   PSParallelCompact::adjust_pointer(next_addr);
 268   oop* discovered_addr = java_lang_ref_Reference::discovered_addr(obj);
 269   PSParallelCompact::adjust_pointer(discovered_addr);
 270 
 271 #ifdef ASSERT
 272   if(TraceReferenceGC && PrintGCDetails) {
 273     gclog_or_tty->print_cr("instanceRefKlass::oop_update_pointers obj "
 274                            INTPTR_FORMAT, (oopDesc*) obj);
 275     gclog_or_tty->print_cr("     referent_addr/* " INTPTR_FORMAT " / "
 276                            INTPTR_FORMAT, referent_addr,
 277                            referent_addr ? (oopDesc*) *referent_addr : NULL);
 278     gclog_or_tty->print_cr("     next_addr/* " INTPTR_FORMAT " / "
 279                            INTPTR_FORMAT, next_addr,
 280                            next_addr ? (oopDesc*) *next_addr : NULL);
 281     gclog_or_tty->print_cr("     discovered_addr/* " INTPTR_FORMAT " / "
 282                    INTPTR_FORMAT, discovered_addr,
 283                    discovered_addr ? (oopDesc*) *discovered_addr : NULL);
 284   }
 285 #endif
 286 
 287   return size_helper();
 288 }
 289 
 290 int
 291 instanceRefKlass::oop_update_pointers(ParCompactionManager* cm, oop obj,
 292                                       HeapWord* beg_addr, HeapWord* end_addr) {
 293   instanceKlass::oop_update_pointers(cm, obj, beg_addr, end_addr);
 294   
 295   oop* p;
 296   oop* referent_addr = p = java_lang_ref_Reference::referent_addr(obj);
 297   PSParallelCompact::adjust_pointer(p, beg_addr, end_addr);
 298   oop* next_addr = p = java_lang_ref_Reference::next_addr(obj);
 299   PSParallelCompact::adjust_pointer(p, beg_addr, end_addr);
 300   oop* discovered_addr = p = java_lang_ref_Reference::discovered_addr(obj);
 301   PSParallelCompact::adjust_pointer(p, beg_addr, end_addr);
 302 
 303 #ifdef ASSERT
 304   if(TraceReferenceGC && PrintGCDetails) {
 305     gclog_or_tty->print_cr("instanceRefKlass::oop_update_pointers obj "
 306                            INTPTR_FORMAT, (oopDesc*) obj);
 307     gclog_or_tty->print_cr("     referent_addr/* " INTPTR_FORMAT " / "
 308                            INTPTR_FORMAT, referent_addr,
 309                            referent_addr ? (oopDesc*) *referent_addr : NULL);
 310     gclog_or_tty->print_cr("     next_addr/* " INTPTR_FORMAT " / "
 311                            INTPTR_FORMAT, next_addr,
 312                            next_addr ? (oopDesc*) *next_addr : NULL);
 313     gclog_or_tty->print_cr("     discovered_addr/* " INTPTR_FORMAT " / "
 314                    INTPTR_FORMAT, discovered_addr,
 315                    discovered_addr ? (oopDesc*) *discovered_addr : NULL);
 316   }
 317 #endif
 318 
 319   return size_helper();
 320 }
 321 #endif // SERIALGC
 322 
 323 void instanceRefKlass::update_nonstatic_oop_maps(klassOop k) {
 324   // Clear the nonstatic oop-map entries corresponding to referent
 325   // and nextPending field.  They are treated specially by the 
 326   // garbage collector.
 327   // The discovered field is used only by the garbage collector
 328   // and is also treated specially.
 329   instanceKlass* ik = instanceKlass::cast(k);
 330 
 331   // Check that we have the right class
 332   debug_only(static bool first_time = true);
 333   assert(k == SystemDictionary::reference_klass() && first_time,
 334          "Invalid update of maps");
 335   debug_only(first_time = false);
 336   assert(ik->nonstatic_oop_map_size() == 1, "just checking");
 337 
 338   OopMapBlock* map = ik->start_of_nonstatic_oop_maps();
 339 
 340   // Check that the current map is (2,4) - currently points at field with
 341   // offset 2 (words) and has 4 map entries.
 342   debug_only(int offset = java_lang_ref_Reference::referent_offset);
 343   debug_only(int length = ((java_lang_ref_Reference::discovered_offset - 
 344     java_lang_ref_Reference::referent_offset)/wordSize) + 1);
 345 
 346   if (UseSharedSpaces) {
 347     assert(map->offset() == java_lang_ref_Reference::queue_offset &&
 348            map->length() == 1, "just checking");
 349   } else {
 350     assert(map->offset() == offset && map->length() == length,
 351            "just checking");
 352 
 353     // Update map to (3,1) - point to offset of 3 (words) with 1 map entry.
 354     map->set_offset(java_lang_ref_Reference::queue_offset);
 355     map->set_length(1);
 356   }
 357 }
 358 
 359 
 360 // Verification
 361 
 362 void instanceRefKlass::oop_verify_on(oop obj, outputStream* st) {
 363   instanceKlass::oop_verify_on(obj, st);
 364   // Verify referent field
 365   oop referent = java_lang_ref_Reference::referent(obj);
 366 
 367   // We should make this general to all heaps
 368   GenCollectedHeap* gch = NULL;
 369   if (Universe::heap()->kind() == CollectedHeap::GenCollectedHeap)
 370     gch = GenCollectedHeap::heap();
 371   
 372   if (referent != NULL) {
 373     guarantee(referent->is_oop(), "referent field heap failed");
 374     if (gch != NULL && !gch->is_in_youngest(obj))
 375       // We do a specific remembered set check here since the referent
 376       // field is not part of the oop mask and therefore skipped by the
 377       // regular verify code.
 378       obj->verify_old_oop(java_lang_ref_Reference::referent_addr(obj), true);
 379   }
 380   // Verify next field
 381   oop next = java_lang_ref_Reference::next(obj);
 382   if (next != NULL) {
 383     guarantee(next->is_oop(), "next field verify failed");    
 384     guarantee(next->is_instanceRef(), "next field verify failed");
 385     if (gch != NULL && !gch->is_in_youngest(obj)) {
 386       // We do a specific remembered set check here since the next field is
 387       // not part of the oop mask and therefore skipped by the regular
 388       // verify code.
 389       obj->verify_old_oop(java_lang_ref_Reference::next_addr(obj), true);
 390     }
 391   }
 392 }
 393 
 394 void instanceRefKlass::acquire_pending_list_lock(BasicLock *pending_list_basic_lock) {
 395   // we may enter this with pending exception set
 396   PRESERVE_EXCEPTION_MARK;  // exceptions are never thrown, needed for TRAPS argument
 397   Handle h_lock(THREAD, java_lang_ref_Reference::pending_list_lock());
 398   ObjectSynchronizer::fast_enter(h_lock, pending_list_basic_lock, false, THREAD);
 399   assert(ObjectSynchronizer::current_thread_holds_lock(
 400            JavaThread::current(), h_lock),
 401          "Locking should have succeeded");
 402   if (HAS_PENDING_EXCEPTION) CLEAR_PENDING_EXCEPTION;
 403 }
 404 
 405 void instanceRefKlass::release_and_notify_pending_list_lock(
 406   BasicLock *pending_list_basic_lock) {
 407   // we may enter this with pending exception set
 408   PRESERVE_EXCEPTION_MARK;  // exceptions are never thrown, needed for TRAPS argument
 409   //
 410   Handle h_lock(THREAD, java_lang_ref_Reference::pending_list_lock());
 411   assert(ObjectSynchronizer::current_thread_holds_lock(
 412            JavaThread::current(), h_lock),
 413          "Lock should be held");
 414   // Notify waiters on pending lists lock if there is any reference.
 415   if (java_lang_ref_Reference::pending_list() != NULL) {
 416     ObjectSynchronizer::notifyall(h_lock, THREAD);
 417   }
 418   ObjectSynchronizer::fast_exit(h_lock(), pending_list_basic_lock, THREAD);
 419   if (HAS_PENDING_EXCEPTION) CLEAR_PENDING_EXCEPTION;
 420 }