src/share/vm/oops/instanceRefKlass.cpp

Wed, 07 Sep 2011 13:55:42 -0700

author
ysr
date
Wed, 07 Sep 2011 13:55:42 -0700
changeset 3117
eca1193ca245
parent 2909
2aa9ddbb9e60
child 3128
f94227b6117b
permissions
-rw-r--r--

4965777: GC changes to support use of discovered field for pending references
Summary: If and when the reference handler thread is able to use the discovered field to link reference objects in its pending list, so will GC. In that case, GC will scan through this field once a reference object has been placed on the pending list, but not scan that field before that stage, as the field is used by the concurrent GC thread to link discovered objects. When ReferenceHandleR thread does not use the discovered field for the purpose of linking the elements in the pending list, as would be the case in older JDKs, the JVM will fall back to the old behaviour of using the next field for that purpose.
Reviewed-by: jcoomes, mchung, stefank

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

mercurial