1 /*
   2  * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #include "precompiled.hpp"
  26 #include "classfile/javaClasses.hpp"
  27 #include "classfile/systemDictionary.hpp"
  28 #include "gc_implementation/shared/markSweep.inline.hpp"
  29 #include "gc_interface/collectedHeap.hpp"
  30 #include "gc_interface/collectedHeap.inline.hpp"
  31 #include "memory/genCollectedHeap.hpp"
  32 #include "memory/genOopClosures.inline.hpp"
  33 #include "oops/instanceRefKlass.hpp"
  34 #include "oops/oop.inline.hpp"
  35 #include "utilities/preserveException.hpp"
  36 #include "utilities/macros.hpp"
  37 #if INCLUDE_ALL_GCS
  38 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
  39 #include "gc_implementation/g1/g1OopClosures.inline.hpp"
  40 #include "gc_implementation/g1/g1RemSet.inline.hpp"
  41 #include "gc_implementation/g1/heapRegionManager.inline.hpp"
  42 #include "gc_implementation/parNew/parOopClosures.inline.hpp"
  43 #include "gc_implementation/parallelScavenge/psPromotionManager.inline.hpp"
  44 #include "gc_implementation/parallelScavenge/psScavenge.inline.hpp"
  45 #include "gc_implementation/shenandoah/shenandoahOopClosures.inline.hpp"
  46 #include "oops/oop.pcgc.inline.hpp"
  47 #endif // INCLUDE_ALL_GCS
  48 
  49 PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
  50 
  51 template <class T>
  52 void specialized_oop_follow_contents(InstanceRefKlass* ref, oop obj) {
  53   T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj);
  54   T heap_oop = oopDesc::load_heap_oop(referent_addr);
  55   debug_only(
  56     if(TraceReferenceGC && PrintGCDetails) {
  57       gclog_or_tty->print_cr("InstanceRefKlass::oop_follow_contents " INTPTR_FORMAT, (void *)obj);
  58     }
  59   )
  60   if (!oopDesc::is_null(heap_oop)) {
  61     oop referent = oopDesc::decode_heap_oop_not_null(heap_oop);
  62     if (!referent->is_gc_marked() &&
  63         MarkSweep::ref_processor()->discover_reference(obj, ref->reference_type())) {
  64       // reference was discovered, referent will be traversed later
  65       ref->InstanceKlass::oop_follow_contents(obj);
  66       debug_only(
  67         if(TraceReferenceGC && PrintGCDetails) {
  68           gclog_or_tty->print_cr("       Non NULL enqueued " INTPTR_FORMAT, (void *)obj);
  69         }
  70       )
  71       return;
  72     } else {
  73       // treat referent as normal oop
  74       debug_only(
  75         if(TraceReferenceGC && PrintGCDetails) {
  76           gclog_or_tty->print_cr("       Non NULL normal " INTPTR_FORMAT, (void *)obj);
  77         }
  78       )
  79       MarkSweep::mark_and_push(referent_addr);
  80     }
  81   }
  82   T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj);
  83   if (ReferenceProcessor::pending_list_uses_discovered_field()) {
  84     // Treat discovered as normal oop, if ref is not "active",
  85     // i.e. if next is non-NULL.
  86     T  next_oop = oopDesc::load_heap_oop(next_addr);
  87     if (!oopDesc::is_null(next_oop)) { // i.e. ref is not "active"
  88       T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj);
  89       debug_only(
  90         if(TraceReferenceGC && PrintGCDetails) {
  91           gclog_or_tty->print_cr("   Process discovered as normal "
  92                                  INTPTR_FORMAT, discovered_addr);
  93         }
  94       )
  95       MarkSweep::mark_and_push(discovered_addr);
  96     }
  97   } else {
  98 #ifdef ASSERT
  99     // In the case of older JDKs which do not use the discovered
 100     // field for the pending list, an inactive ref (next != NULL)
 101     // must always have a NULL discovered field.
 102     oop next = oopDesc::load_decode_heap_oop(next_addr);
 103     oop discovered = java_lang_ref_Reference::discovered(obj);
 104     assert(oopDesc::is_null(next) || oopDesc::is_null(discovered),
 105            err_msg("Found an inactive reference " PTR_FORMAT " with a non-NULL discovered field",
 106                    (oopDesc*)obj));
 107 #endif
 108   }
 109   // treat next as normal oop.  next is a link in the reference queue.
 110   debug_only(
 111     if(TraceReferenceGC && PrintGCDetails) {
 112       gclog_or_tty->print_cr("   Process next as normal " INTPTR_FORMAT, next_addr);
 113     }
 114   )
 115   MarkSweep::mark_and_push(next_addr);
 116   ref->InstanceKlass::oop_follow_contents(obj);
 117 }
 118 
 119 void InstanceRefKlass::oop_follow_contents(oop obj) {
 120   if (UseCompressedOops) {
 121     specialized_oop_follow_contents<narrowOop>(this, obj);
 122   } else {
 123     specialized_oop_follow_contents<oop>(this, obj);
 124   }
 125 }
 126 
 127 #if INCLUDE_ALL_GCS
 128 template <class T>
 129 void specialized_oop_follow_contents(InstanceRefKlass* ref,
 130                                      ParCompactionManager* cm,
 131                                      oop obj) {
 132   T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj);
 133   T heap_oop = oopDesc::load_heap_oop(referent_addr);
 134   debug_only(
 135     if(TraceReferenceGC && PrintGCDetails) {
 136       gclog_or_tty->print_cr("InstanceRefKlass::oop_follow_contents " INTPTR_FORMAT, (void *)obj);
 137     }
 138   )
 139   if (!oopDesc::is_null(heap_oop)) {
 140     oop referent = oopDesc::decode_heap_oop_not_null(heap_oop);
 141     if (PSParallelCompact::mark_bitmap()->is_unmarked(referent) &&
 142         PSParallelCompact::ref_processor()->
 143           discover_reference(obj, ref->reference_type())) {
 144       // reference already enqueued, referent will be traversed later
 145       ref->InstanceKlass::oop_follow_contents(cm, obj);
 146       debug_only(
 147         if(TraceReferenceGC && PrintGCDetails) {
 148           gclog_or_tty->print_cr("       Non NULL enqueued " INTPTR_FORMAT, (void *)obj);
 149         }
 150       )
 151       return;
 152     } else {
 153       // treat referent as normal oop
 154       debug_only(
 155         if(TraceReferenceGC && PrintGCDetails) {
 156           gclog_or_tty->print_cr("       Non NULL normal " INTPTR_FORMAT, (void *)obj);
 157         }
 158       )
 159       PSParallelCompact::mark_and_push(cm, referent_addr);
 160     }
 161   }
 162   T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj);
 163   if (ReferenceProcessor::pending_list_uses_discovered_field()) {
 164     // Treat discovered as normal oop, if ref is not "active",
 165     // i.e. if next is non-NULL.
 166     T  next_oop = oopDesc::load_heap_oop(next_addr);
 167     if (!oopDesc::is_null(next_oop)) { // i.e. ref is not "active"
 168       T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj);
 169       debug_only(
 170         if(TraceReferenceGC && PrintGCDetails) {
 171           gclog_or_tty->print_cr("   Process discovered as normal "
 172                                  INTPTR_FORMAT, discovered_addr);
 173         }
 174       )
 175       PSParallelCompact::mark_and_push(cm, discovered_addr);
 176     }
 177   } else {
 178 #ifdef ASSERT
 179     // In the case of older JDKs which do not use the discovered
 180     // field for the pending list, an inactive ref (next != NULL)
 181     // must always have a NULL discovered field.
 182     T next = oopDesc::load_heap_oop(next_addr);
 183     oop discovered = java_lang_ref_Reference::discovered(obj);
 184     assert(oopDesc::is_null(next) || oopDesc::is_null(discovered),
 185            err_msg("Found an inactive reference " PTR_FORMAT " with a non-NULL discovered field",
 186                    (oopDesc*)obj));
 187 #endif
 188   }
 189   PSParallelCompact::mark_and_push(cm, next_addr);
 190   ref->InstanceKlass::oop_follow_contents(cm, obj);
 191 }
 192 
 193 void InstanceRefKlass::oop_follow_contents(ParCompactionManager* cm,
 194                                            oop obj) {
 195   if (UseCompressedOops) {
 196     specialized_oop_follow_contents<narrowOop>(this, cm, obj);
 197   } else {
 198     specialized_oop_follow_contents<oop>(this, cm, obj);
 199   }
 200 }
 201 #endif // INCLUDE_ALL_GCS
 202 
 203 #ifdef ASSERT
 204 template <class T> void trace_reference_gc(const char *s, oop obj,
 205                                            T* referent_addr,
 206                                            T* next_addr,
 207                                            T* discovered_addr) {
 208   if(TraceReferenceGC && PrintGCDetails) {
 209     gclog_or_tty->print_cr("%s obj " INTPTR_FORMAT, s, (address)obj);
 210     gclog_or_tty->print_cr("     referent_addr/* " INTPTR_FORMAT " / "
 211          INTPTR_FORMAT, referent_addr,
 212          referent_addr ?
 213            (address)oopDesc::load_decode_heap_oop(referent_addr) : NULL);
 214     gclog_or_tty->print_cr("     next_addr/* " INTPTR_FORMAT " / "
 215          INTPTR_FORMAT, next_addr,
 216          next_addr ? (address)oopDesc::load_decode_heap_oop(next_addr) : NULL);
 217     gclog_or_tty->print_cr("     discovered_addr/* " INTPTR_FORMAT " / "
 218          INTPTR_FORMAT, discovered_addr,
 219          discovered_addr ?
 220            (address)oopDesc::load_decode_heap_oop(discovered_addr) : NULL);
 221   }
 222 }
 223 #endif
 224 
 225 template <class T> void specialized_oop_adjust_pointers(InstanceRefKlass *ref, oop obj) {
 226   T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj);
 227   MarkSweep::adjust_pointer(referent_addr);
 228   T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj);
 229   MarkSweep::adjust_pointer(next_addr);
 230   T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj);
 231   MarkSweep::adjust_pointer(discovered_addr);
 232   debug_only(trace_reference_gc("InstanceRefKlass::oop_adjust_pointers", obj,
 233                                 referent_addr, next_addr, discovered_addr);)
 234 }
 235 
 236 int InstanceRefKlass::oop_adjust_pointers(oop obj) {
 237   int size = size_helper();
 238   InstanceKlass::oop_adjust_pointers(obj);
 239 
 240   if (UseCompressedOops) {
 241     specialized_oop_adjust_pointers<narrowOop>(this, obj);
 242   } else {
 243     specialized_oop_adjust_pointers<oop>(this, obj);
 244   }
 245   return size;
 246 }
 247 
 248 #define InstanceRefKlass_SPECIALIZED_OOP_ITERATE(T, nv_suffix, contains)        \
 249   T* disc_addr = (T*)java_lang_ref_Reference::discovered_addr(obj);             \
 250   if (closure->apply_to_weak_ref_discovered_field()) {                          \
 251     closure->do_oop##nv_suffix(disc_addr);                                      \
 252   }                                                                             \
 253                                                                                 \
 254   T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj);           \
 255   T heap_oop = oopDesc::load_heap_oop(referent_addr);                           \
 256   ReferenceProcessor* rp = closure->_ref_processor;                             \
 257   if (!oopDesc::is_null(heap_oop)) {                                            \
 258     oop referent = oopDesc::decode_heap_oop_not_null(heap_oop);                 \
 259     if (!referent->is_gc_marked() && (rp != NULL) &&                            \
 260         rp->discover_reference(obj, reference_type())) {                        \
 261       return size;                                                              \
 262     } else if (contains(referent_addr)) {                                       \
 263       /* treat referent as normal oop */                                        \
 264       SpecializationStats::record_do_oop_call##nv_suffix(SpecializationStats::irk);\
 265       closure->do_oop##nv_suffix(referent_addr);                                \
 266     }                                                                           \
 267   }                                                                             \
 268   T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj);                   \
 269   if (ReferenceProcessor::pending_list_uses_discovered_field()) {               \
 270     T next_oop  = oopDesc::load_heap_oop(next_addr);                            \
 271     /* Treat discovered as normal oop, if ref is not "active" (next non-NULL) */\
 272     if (!oopDesc::is_null(next_oop) && contains(disc_addr)) {                   \
 273         /* i.e. ref is not "active" */                                          \
 274       debug_only(                                                               \
 275         if(TraceReferenceGC && PrintGCDetails) {                                \
 276           gclog_or_tty->print_cr("   Process discovered as normal "             \
 277                                  INTPTR_FORMAT, disc_addr);                     \
 278         }                                                                       \
 279       )                                                                         \
 280       SpecializationStats::record_do_oop_call##nv_suffix(SpecializationStats::irk);\
 281       closure->do_oop##nv_suffix(disc_addr);                                    \
 282     }                                                                           \
 283   } else {                                                                      \
 284     /* In the case of older JDKs which do not use the discovered field for  */  \
 285     /* the pending list, an inactive ref (next != NULL) must always have a  */  \
 286     /* NULL discovered field. */                                                \
 287     debug_only(                                                                 \
 288       T next_oop = oopDesc::load_heap_oop(next_addr);                           \
 289       T disc_oop = oopDesc::load_heap_oop(disc_addr);                           \
 290       assert(oopDesc::is_null(next_oop) || oopDesc::is_null(disc_oop),          \
 291            err_msg("Found an inactive reference " PTR_FORMAT " with a non-NULL" \
 292                    "discovered field", (oopDesc*)obj));                                   \
 293     )                                                                           \
 294   }                                                                             \
 295   /* treat next as normal oop */                                                \
 296   if (contains(next_addr)) {                                                    \
 297     SpecializationStats::record_do_oop_call##nv_suffix(SpecializationStats::irk); \
 298     closure->do_oop##nv_suffix(next_addr);                                      \
 299   }                                                                             \
 300   return size;                                                                  \
 301 
 302 
 303 template <class T> bool contains(T *t) { return true; }
 304 
 305 // Macro to define InstanceRefKlass::oop_oop_iterate for virtual/nonvirtual for
 306 // all closures.  Macros calling macros above for each oop size.
 307 
 308 #define InstanceRefKlass_OOP_OOP_ITERATE_DEFN(OopClosureType, nv_suffix)        \
 309                                                                                 \
 310 int InstanceRefKlass::                                                          \
 311 oop_oop_iterate##nv_suffix(oop obj, OopClosureType* closure) {                  \
 312   /* Get size before changing pointers */                                       \
 313   SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::irk);\
 314                                                                                 \
 315   int size = InstanceKlass::oop_oop_iterate##nv_suffix(obj, closure);           \
 316                                                                                 \
 317   if (UseCompressedOops) {                                                      \
 318     InstanceRefKlass_SPECIALIZED_OOP_ITERATE(narrowOop, nv_suffix, contains);   \
 319   } else {                                                                      \
 320     InstanceRefKlass_SPECIALIZED_OOP_ITERATE(oop, nv_suffix, contains);         \
 321   }                                                                             \
 322 }
 323 
 324 #if INCLUDE_ALL_GCS
 325 #define InstanceRefKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN(OopClosureType, nv_suffix) \
 326                                                                                 \
 327 int InstanceRefKlass::                                                          \
 328 oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* closure) {        \
 329   /* Get size before changing pointers */                                       \
 330   SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::irk);\
 331                                                                                 \
 332   int size = InstanceKlass::oop_oop_iterate_backwards##nv_suffix(obj, closure); \
 333                                                                                 \
 334   if (UseCompressedOops) {                                                      \
 335     InstanceRefKlass_SPECIALIZED_OOP_ITERATE(narrowOop, nv_suffix, contains);   \
 336   } else {                                                                      \
 337     InstanceRefKlass_SPECIALIZED_OOP_ITERATE(oop, nv_suffix, contains);         \
 338   }                                                                             \
 339 }
 340 #endif // INCLUDE_ALL_GCS
 341 
 342 
 343 #define InstanceRefKlass_OOP_OOP_ITERATE_DEFN_m(OopClosureType, nv_suffix)      \
 344                                                                                 \
 345 int InstanceRefKlass::                                                          \
 346 oop_oop_iterate##nv_suffix##_m(oop obj,                                         \
 347                                OopClosureType* closure,                         \
 348                                MemRegion mr) {                                  \
 349   SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::irk);\
 350                                                                                 \
 351   int size = InstanceKlass::oop_oop_iterate##nv_suffix##_m(obj, closure, mr);   \
 352   if (UseCompressedOops) {                                                      \
 353     InstanceRefKlass_SPECIALIZED_OOP_ITERATE(narrowOop, nv_suffix, mr.contains); \
 354   } else {                                                                      \
 355     InstanceRefKlass_SPECIALIZED_OOP_ITERATE(oop, nv_suffix, mr.contains);      \
 356   }                                                                             \
 357 }
 358 
 359 ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceRefKlass_OOP_OOP_ITERATE_DEFN)
 360 ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceRefKlass_OOP_OOP_ITERATE_DEFN)
 361 #if INCLUDE_ALL_GCS
 362 ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceRefKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN)
 363 ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceRefKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN)
 364 #endif // INCLUDE_ALL_GCS
 365 ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceRefKlass_OOP_OOP_ITERATE_DEFN_m)
 366 ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceRefKlass_OOP_OOP_ITERATE_DEFN_m)
 367 
 368 #if INCLUDE_ALL_GCS
 369 template <class T>
 370 void specialized_oop_push_contents(InstanceRefKlass *ref,
 371                                    PSPromotionManager* pm, oop obj) {
 372   T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj);
 373   if (PSScavenge::should_scavenge(referent_addr)) {
 374     ReferenceProcessor* rp = PSScavenge::reference_processor();
 375     if (rp->discover_reference(obj, ref->reference_type())) {
 376       // reference already enqueued, referent and next will be traversed later
 377       ref->InstanceKlass::oop_push_contents(pm, obj);
 378       return;
 379     } else {
 380       // treat referent as normal oop
 381       pm->claim_or_forward_depth(referent_addr);
 382     }
 383   }
 384   // Treat discovered as normal oop, if ref is not "active",
 385   // i.e. if next is non-NULL.
 386   T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj);
 387   if (ReferenceProcessor::pending_list_uses_discovered_field()) {
 388     T  next_oop = oopDesc::load_heap_oop(next_addr);
 389     if (!oopDesc::is_null(next_oop)) { // i.e. ref is not "active"
 390       T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj);
 391       debug_only(
 392         if(TraceReferenceGC && PrintGCDetails) {
 393           gclog_or_tty->print_cr("   Process discovered as normal "
 394                                  INTPTR_FORMAT, discovered_addr);
 395         }
 396       )
 397       if (PSScavenge::should_scavenge(discovered_addr)) {
 398         pm->claim_or_forward_depth(discovered_addr);
 399       }
 400     }
 401   } else {
 402 #ifdef ASSERT
 403     // In the case of older JDKs which do not use the discovered
 404     // field for the pending list, an inactive ref (next != NULL)
 405     // must always have a NULL discovered field.
 406     oop next = oopDesc::load_decode_heap_oop(next_addr);
 407     oop discovered = java_lang_ref_Reference::discovered(obj);
 408     assert(oopDesc::is_null(next) || oopDesc::is_null(discovered),
 409            err_msg("Found an inactive reference " PTR_FORMAT " with a non-NULL discovered field",
 410                    (oopDesc*)obj));
 411 #endif
 412   }
 413 
 414   // Treat next as normal oop;  next is a link in the reference queue.
 415   if (PSScavenge::should_scavenge(next_addr)) {
 416     pm->claim_or_forward_depth(next_addr);
 417   }
 418   ref->InstanceKlass::oop_push_contents(pm, obj);
 419 }
 420 
 421 void InstanceRefKlass::oop_push_contents(PSPromotionManager* pm, oop obj) {
 422   if (UseCompressedOops) {
 423     specialized_oop_push_contents<narrowOop>(this, pm, obj);
 424   } else {
 425     specialized_oop_push_contents<oop>(this, pm, obj);
 426   }
 427 }
 428 
 429 template <class T>
 430 void specialized_oop_update_pointers(InstanceRefKlass *ref,
 431                                     ParCompactionManager* cm, oop obj) {
 432   T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj);
 433   PSParallelCompact::adjust_pointer(referent_addr);
 434   T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj);
 435   PSParallelCompact::adjust_pointer(next_addr);
 436   T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj);
 437   PSParallelCompact::adjust_pointer(discovered_addr);
 438   debug_only(trace_reference_gc("InstanceRefKlass::oop_update_ptrs", obj,
 439                                 referent_addr, next_addr, discovered_addr);)
 440 }
 441 
 442 int InstanceRefKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) {
 443   InstanceKlass::oop_update_pointers(cm, obj);
 444   if (UseCompressedOops) {
 445     specialized_oop_update_pointers<narrowOop>(this, cm, obj);
 446   } else {
 447     specialized_oop_update_pointers<oop>(this, cm, obj);
 448   }
 449   return size_helper();
 450 }
 451 #endif // INCLUDE_ALL_GCS
 452 
 453 void InstanceRefKlass::update_nonstatic_oop_maps(Klass* k) {
 454   // Clear the nonstatic oop-map entries corresponding to referent
 455   // and nextPending field.  They are treated specially by the
 456   // garbage collector.
 457   // The discovered field is used only by the garbage collector
 458   // and is also treated specially.
 459   InstanceKlass* ik = InstanceKlass::cast(k);
 460 
 461   // Check that we have the right class
 462   debug_only(static bool first_time = true);
 463   assert(k == SystemDictionary::Reference_klass() && first_time,
 464          "Invalid update of maps");
 465   debug_only(first_time = false);
 466   assert(ik->nonstatic_oop_map_count() == 1, "just checking");
 467 
 468   OopMapBlock* map = ik->start_of_nonstatic_oop_maps();
 469 
 470   // Check that the current map is (2,4) - currently points at field with
 471   // offset 2 (words) and has 4 map entries.
 472   debug_only(int offset = java_lang_ref_Reference::referent_offset);
 473   debug_only(unsigned int count = ((java_lang_ref_Reference::discovered_offset -
 474     java_lang_ref_Reference::referent_offset)/heapOopSize) + 1);
 475 
 476   if (UseSharedSpaces) {
 477     assert(map->offset() == java_lang_ref_Reference::queue_offset &&
 478            map->count() == 1, "just checking");
 479   } else {
 480     assert(map->offset() == offset && map->count() == count,
 481            "just checking");
 482 
 483     // Update map to (3,1) - point to offset of 3 (words) with 1 map entry.
 484     map->set_offset(java_lang_ref_Reference::queue_offset);
 485     map->set_count(1);
 486   }
 487 }
 488 
 489 
 490 // Verification
 491 
 492 void InstanceRefKlass::oop_verify_on(oop obj, outputStream* st) {
 493   InstanceKlass::oop_verify_on(obj, st);
 494   // Verify referent field
 495   oop referent = java_lang_ref_Reference::referent(obj);
 496 
 497   // We should make this general to all heaps
 498   GenCollectedHeap* gch = NULL;
 499   if (Universe::heap()->kind() == CollectedHeap::GenCollectedHeap)
 500     gch = GenCollectedHeap::heap();
 501 
 502   if (referent != NULL) {
 503     guarantee(referent->is_oop(), "referent field heap failed");
 504   }
 505   // Verify next field
 506   oop next = java_lang_ref_Reference::next(obj);
 507   if (next != NULL) {
 508     guarantee(next->is_oop(), "next field verify failed");
 509     guarantee(next->is_instanceRef(), "next field verify failed");
 510   }
 511 }
 512 
 513 bool InstanceRefKlass::owns_pending_list_lock(JavaThread* thread) {
 514   if (java_lang_ref_Reference::pending_list_lock() == NULL) return false;
 515   Handle h_lock(thread, java_lang_ref_Reference::pending_list_lock());
 516   return ObjectSynchronizer::current_thread_holds_lock(thread, h_lock);
 517 }
 518 
 519 void InstanceRefKlass::acquire_pending_list_lock(BasicLock *pending_list_basic_lock) {
 520   // we may enter this with pending exception set
 521   PRESERVE_EXCEPTION_MARK;  // exceptions are never thrown, needed for TRAPS argument
 522 
 523   // Create a HandleMark in case we retry a GC multiple times.
 524   // Each time we attempt the GC, we allocate the handle below
 525   // to hold the pending list lock. We want to free this handle.
 526   HandleMark hm;
 527 
 528   Handle h_lock(THREAD, java_lang_ref_Reference::pending_list_lock());
 529   ObjectSynchronizer::fast_enter(h_lock, pending_list_basic_lock, false, THREAD);
 530   assert(ObjectSynchronizer::current_thread_holds_lock(
 531            JavaThread::current(), h_lock),
 532          "Locking should have succeeded");
 533   if (HAS_PENDING_EXCEPTION) CLEAR_PENDING_EXCEPTION;
 534 }
 535 
 536 void InstanceRefKlass::release_and_notify_pending_list_lock(
 537   BasicLock *pending_list_basic_lock) {
 538   // we may enter this with pending exception set
 539   PRESERVE_EXCEPTION_MARK;  // exceptions are never thrown, needed for TRAPS argument
 540 
 541   // Create a HandleMark in case we retry a GC multiple times.
 542   // Each time we attempt the GC, we allocate the handle below
 543   // to hold the pending list lock. We want to free this handle.
 544   HandleMark hm;
 545 
 546   Handle h_lock(THREAD, java_lang_ref_Reference::pending_list_lock());
 547   assert(ObjectSynchronizer::current_thread_holds_lock(
 548            JavaThread::current(), h_lock),
 549          "Lock should be held");
 550   // Notify waiters on pending lists lock if there is any reference.
 551   if (java_lang_ref_Reference::pending_list() != NULL) {
 552     ObjectSynchronizer::notifyall(h_lock, THREAD);
 553   }
 554   ObjectSynchronizer::fast_exit(h_lock(), pending_list_basic_lock, THREAD);
 555   if (HAS_PENDING_EXCEPTION) CLEAR_PENDING_EXCEPTION;
 556 }
--- EOF ---