1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/vm/oops/instanceRefKlass.cpp Sat Dec 01 00:00:00 2007 +0000 1.3 @@ -0,0 +1,417 @@ 1.4 +/* 1.5 + * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 1.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 1.24 + * have any questions. 1.25 + * 1.26 + */ 1.27 + 1.28 +# include "incls/_precompiled.incl" 1.29 +# include "incls/_instanceRefKlass.cpp.incl" 1.30 + 1.31 +void instanceRefKlass::oop_follow_contents(oop obj) { 1.32 + oop* referent_addr = java_lang_ref_Reference::referent_addr(obj); 1.33 + oop referent = *referent_addr; 1.34 + debug_only( 1.35 + if(TraceReferenceGC && PrintGCDetails) { 1.36 + gclog_or_tty->print_cr("instanceRefKlass::oop_follow_contents " INTPTR_FORMAT, (address)obj); 1.37 + } 1.38 + ) 1.39 + if (referent != NULL) { 1.40 + if (!referent->is_gc_marked() && 1.41 + MarkSweep::ref_processor()-> 1.42 + discover_reference(obj, reference_type())) { 1.43 + // reference already enqueued, referent will be traversed later 1.44 + instanceKlass::oop_follow_contents(obj); 1.45 + debug_only( 1.46 + if(TraceReferenceGC && PrintGCDetails) { 1.47 + gclog_or_tty->print_cr(" Non NULL enqueued " INTPTR_FORMAT, (address)obj); 1.48 + } 1.49 + ) 1.50 + return; 1.51 + } else { 1.52 + // treat referent as normal oop 1.53 + debug_only( 1.54 + if(TraceReferenceGC && PrintGCDetails) { 1.55 + gclog_or_tty->print_cr(" Non NULL normal " INTPTR_FORMAT, (address)obj); 1.56 + } 1.57 + ) 1.58 + MarkSweep::mark_and_push(referent_addr); 1.59 + } 1.60 + } 1.61 + // treat next as normal oop. next is a link in the pending list. 1.62 + oop* next_addr = java_lang_ref_Reference::next_addr(obj); 1.63 + debug_only( 1.64 + if(TraceReferenceGC && PrintGCDetails) { 1.65 + gclog_or_tty->print_cr(" Process next as normal " INTPTR_FORMAT, next_addr); 1.66 + } 1.67 + ) 1.68 + MarkSweep::mark_and_push(next_addr); 1.69 + instanceKlass::oop_follow_contents(obj); 1.70 +} 1.71 + 1.72 +#ifndef SERIALGC 1.73 +void instanceRefKlass::oop_follow_contents(ParCompactionManager* cm, 1.74 + oop obj) { 1.75 + oop* referent_addr = java_lang_ref_Reference::referent_addr(obj); 1.76 + oop referent = *referent_addr; 1.77 + debug_only( 1.78 + if(TraceReferenceGC && PrintGCDetails) { 1.79 + gclog_or_tty->print_cr("instanceRefKlass::oop_follow_contents " INTPTR_FORMAT, (address)obj); 1.80 + } 1.81 + ) 1.82 + if (referent != NULL) { 1.83 + if (PSParallelCompact::mark_bitmap()->is_unmarked(referent) && 1.84 + PSParallelCompact::ref_processor()-> 1.85 + discover_reference(obj, reference_type())) { 1.86 + // reference already enqueued, referent will be traversed later 1.87 + instanceKlass::oop_follow_contents(cm, obj); 1.88 + debug_only( 1.89 + if(TraceReferenceGC && PrintGCDetails) { 1.90 + gclog_or_tty->print_cr(" Non NULL enqueued " INTPTR_FORMAT, (address)obj); 1.91 + } 1.92 + ) 1.93 + return; 1.94 + } else { 1.95 + // treat referent as normal oop 1.96 + debug_only( 1.97 + if(TraceReferenceGC && PrintGCDetails) { 1.98 + gclog_or_tty->print_cr(" Non NULL normal " INTPTR_FORMAT, (address)obj); 1.99 + } 1.100 + ) 1.101 + PSParallelCompact::mark_and_push(cm, referent_addr); 1.102 + } 1.103 + } 1.104 + // treat next as normal oop. next is a link in the pending list. 1.105 + oop* next_addr = java_lang_ref_Reference::next_addr(obj); 1.106 + debug_only( 1.107 + if(TraceReferenceGC && PrintGCDetails) { 1.108 + gclog_or_tty->print_cr(" Process next as normal " INTPTR_FORMAT, next_addr); 1.109 + } 1.110 + ) 1.111 + PSParallelCompact::mark_and_push(cm, next_addr); 1.112 + instanceKlass::oop_follow_contents(cm, obj); 1.113 +} 1.114 +#endif // SERIALGC 1.115 + 1.116 + 1.117 +int instanceRefKlass::oop_adjust_pointers(oop obj) { 1.118 + int size = size_helper(); 1.119 + instanceKlass::oop_adjust_pointers(obj); 1.120 + 1.121 + oop* referent_addr = java_lang_ref_Reference::referent_addr(obj); 1.122 + MarkSweep::adjust_pointer(referent_addr); 1.123 + oop* next_addr = java_lang_ref_Reference::next_addr(obj); 1.124 + MarkSweep::adjust_pointer(next_addr); 1.125 + oop* discovered_addr = java_lang_ref_Reference::discovered_addr(obj); 1.126 + MarkSweep::adjust_pointer(discovered_addr); 1.127 + 1.128 +#ifdef ASSERT 1.129 + if(TraceReferenceGC && PrintGCDetails) { 1.130 + gclog_or_tty->print_cr("instanceRefKlass::oop_adjust_pointers obj " 1.131 + INTPTR_FORMAT, (address)obj); 1.132 + gclog_or_tty->print_cr(" referent_addr/* " INTPTR_FORMAT " / " 1.133 + INTPTR_FORMAT, referent_addr, 1.134 + referent_addr ? (address)*referent_addr : NULL); 1.135 + gclog_or_tty->print_cr(" next_addr/* " INTPTR_FORMAT " / " 1.136 + INTPTR_FORMAT, next_addr, 1.137 + next_addr ? (address)*next_addr : NULL); 1.138 + gclog_or_tty->print_cr(" discovered_addr/* " INTPTR_FORMAT " / " 1.139 + INTPTR_FORMAT, discovered_addr, 1.140 + discovered_addr ? (address)*discovered_addr : NULL); 1.141 + } 1.142 +#endif 1.143 + 1.144 + return size; 1.145 +} 1.146 + 1.147 +#define InstanceRefKlass_OOP_OOP_ITERATE_DEFN(OopClosureType, nv_suffix) \ 1.148 + \ 1.149 +int instanceRefKlass:: \ 1.150 +oop_oop_iterate##nv_suffix(oop obj, OopClosureType* closure) { \ 1.151 + /* Get size before changing pointers */ \ 1.152 + SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::irk);\ 1.153 + \ 1.154 + int size = instanceKlass::oop_oop_iterate##nv_suffix(obj, closure); \ 1.155 + \ 1.156 + oop* referent_addr = java_lang_ref_Reference::referent_addr(obj); \ 1.157 + oop referent = *referent_addr; \ 1.158 + if (referent != NULL) { \ 1.159 + ReferenceProcessor* rp = closure->_ref_processor; \ 1.160 + if (!referent->is_gc_marked() && (rp != NULL) && \ 1.161 + rp->discover_reference(obj, reference_type())) { \ 1.162 + return size; \ 1.163 + } else { \ 1.164 + /* treat referent as normal oop */ \ 1.165 + SpecializationStats::record_do_oop_call##nv_suffix(SpecializationStats::irk);\ 1.166 + closure->do_oop##nv_suffix(referent_addr); \ 1.167 + } \ 1.168 + } \ 1.169 + \ 1.170 + /* treat next as normal oop */ \ 1.171 + oop* next_addr = java_lang_ref_Reference::next_addr(obj); \ 1.172 + SpecializationStats::record_do_oop_call##nv_suffix(SpecializationStats::irk); \ 1.173 + closure->do_oop##nv_suffix(next_addr); \ 1.174 + return size; \ 1.175 +} 1.176 + 1.177 +#define InstanceRefKlass_OOP_OOP_ITERATE_DEFN_m(OopClosureType, nv_suffix) \ 1.178 + \ 1.179 +int instanceRefKlass:: \ 1.180 +oop_oop_iterate##nv_suffix##_m(oop obj, \ 1.181 + OopClosureType* closure, \ 1.182 + MemRegion mr) { \ 1.183 + SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::irk);\ 1.184 + \ 1.185 + int size = instanceKlass::oop_oop_iterate##nv_suffix##_m(obj, closure, mr); \ 1.186 + \ 1.187 + oop* referent_addr = java_lang_ref_Reference::referent_addr(obj); \ 1.188 + oop referent = *referent_addr; \ 1.189 + if (referent != NULL && mr.contains(referent_addr)) { \ 1.190 + ReferenceProcessor* rp = closure->_ref_processor; \ 1.191 + if (!referent->is_gc_marked() && (rp != NULL) && \ 1.192 + rp->discover_reference(obj, reference_type())) { \ 1.193 + return size; \ 1.194 + } else { \ 1.195 + /* treat referent as normal oop */ \ 1.196 + SpecializationStats::record_do_oop_call##nv_suffix(SpecializationStats::irk);\ 1.197 + closure->do_oop##nv_suffix(referent_addr); \ 1.198 + } \ 1.199 + } \ 1.200 + \ 1.201 + /* treat next as normal oop */ \ 1.202 + oop* next_addr = java_lang_ref_Reference::next_addr(obj); \ 1.203 + if (mr.contains(next_addr)) { \ 1.204 + SpecializationStats::record_do_oop_call##nv_suffix(SpecializationStats::irk);\ 1.205 + closure->do_oop##nv_suffix(next_addr); \ 1.206 + } \ 1.207 + return size; \ 1.208 +} 1.209 + 1.210 +ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceRefKlass_OOP_OOP_ITERATE_DEFN) 1.211 +ALL_OOP_OOP_ITERATE_CLOSURES_3(InstanceRefKlass_OOP_OOP_ITERATE_DEFN) 1.212 +ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceRefKlass_OOP_OOP_ITERATE_DEFN_m) 1.213 +ALL_OOP_OOP_ITERATE_CLOSURES_3(InstanceRefKlass_OOP_OOP_ITERATE_DEFN_m) 1.214 + 1.215 + 1.216 +#ifndef SERIALGC 1.217 +void instanceRefKlass::oop_copy_contents(PSPromotionManager* pm, oop obj) { 1.218 + assert(!pm->depth_first(), "invariant"); 1.219 + oop* referent_addr = java_lang_ref_Reference::referent_addr(obj); 1.220 + if (PSScavenge::should_scavenge(*referent_addr)) { 1.221 + ReferenceProcessor* rp = PSScavenge::reference_processor(); 1.222 + if (rp->discover_reference(obj, reference_type())) { 1.223 + // reference already enqueued, referent and next will be traversed later 1.224 + instanceKlass::oop_copy_contents(pm, obj); 1.225 + return; 1.226 + } else { 1.227 + // treat referent as normal oop 1.228 + pm->claim_or_forward_breadth(referent_addr); 1.229 + } 1.230 + } 1.231 + // treat next as normal oop 1.232 + oop* next_addr = java_lang_ref_Reference::next_addr(obj); 1.233 + if (PSScavenge::should_scavenge(*next_addr)) { 1.234 + pm->claim_or_forward_breadth(next_addr); 1.235 + } 1.236 + instanceKlass::oop_copy_contents(pm, obj); 1.237 +} 1.238 + 1.239 +void instanceRefKlass::oop_push_contents(PSPromotionManager* pm, oop obj) { 1.240 + assert(pm->depth_first(), "invariant"); 1.241 + oop* referent_addr = java_lang_ref_Reference::referent_addr(obj); 1.242 + if (PSScavenge::should_scavenge(*referent_addr)) { 1.243 + ReferenceProcessor* rp = PSScavenge::reference_processor(); 1.244 + if (rp->discover_reference(obj, reference_type())) { 1.245 + // reference already enqueued, referent and next will be traversed later 1.246 + instanceKlass::oop_push_contents(pm, obj); 1.247 + return; 1.248 + } else { 1.249 + // treat referent as normal oop 1.250 + pm->claim_or_forward_depth(referent_addr); 1.251 + } 1.252 + } 1.253 + // treat next as normal oop 1.254 + oop* next_addr = java_lang_ref_Reference::next_addr(obj); 1.255 + if (PSScavenge::should_scavenge(*next_addr)) { 1.256 + pm->claim_or_forward_depth(next_addr); 1.257 + } 1.258 + instanceKlass::oop_push_contents(pm, obj); 1.259 +} 1.260 + 1.261 +int instanceRefKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) { 1.262 + instanceKlass::oop_update_pointers(cm, obj); 1.263 + 1.264 + oop* referent_addr = java_lang_ref_Reference::referent_addr(obj); 1.265 + PSParallelCompact::adjust_pointer(referent_addr); 1.266 + oop* next_addr = java_lang_ref_Reference::next_addr(obj); 1.267 + PSParallelCompact::adjust_pointer(next_addr); 1.268 + oop* discovered_addr = java_lang_ref_Reference::discovered_addr(obj); 1.269 + PSParallelCompact::adjust_pointer(discovered_addr); 1.270 + 1.271 +#ifdef ASSERT 1.272 + if(TraceReferenceGC && PrintGCDetails) { 1.273 + gclog_or_tty->print_cr("instanceRefKlass::oop_update_pointers obj " 1.274 + INTPTR_FORMAT, (oopDesc*) obj); 1.275 + gclog_or_tty->print_cr(" referent_addr/* " INTPTR_FORMAT " / " 1.276 + INTPTR_FORMAT, referent_addr, 1.277 + referent_addr ? (oopDesc*) *referent_addr : NULL); 1.278 + gclog_or_tty->print_cr(" next_addr/* " INTPTR_FORMAT " / " 1.279 + INTPTR_FORMAT, next_addr, 1.280 + next_addr ? (oopDesc*) *next_addr : NULL); 1.281 + gclog_or_tty->print_cr(" discovered_addr/* " INTPTR_FORMAT " / " 1.282 + INTPTR_FORMAT, discovered_addr, 1.283 + discovered_addr ? (oopDesc*) *discovered_addr : NULL); 1.284 + } 1.285 +#endif 1.286 + 1.287 + return size_helper(); 1.288 +} 1.289 + 1.290 +int 1.291 +instanceRefKlass::oop_update_pointers(ParCompactionManager* cm, oop obj, 1.292 + HeapWord* beg_addr, HeapWord* end_addr) { 1.293 + instanceKlass::oop_update_pointers(cm, obj, beg_addr, end_addr); 1.294 + 1.295 + oop* p; 1.296 + oop* referent_addr = p = java_lang_ref_Reference::referent_addr(obj); 1.297 + PSParallelCompact::adjust_pointer(p, beg_addr, end_addr); 1.298 + oop* next_addr = p = java_lang_ref_Reference::next_addr(obj); 1.299 + PSParallelCompact::adjust_pointer(p, beg_addr, end_addr); 1.300 + oop* discovered_addr = p = java_lang_ref_Reference::discovered_addr(obj); 1.301 + PSParallelCompact::adjust_pointer(p, beg_addr, end_addr); 1.302 + 1.303 +#ifdef ASSERT 1.304 + if(TraceReferenceGC && PrintGCDetails) { 1.305 + gclog_or_tty->print_cr("instanceRefKlass::oop_update_pointers obj " 1.306 + INTPTR_FORMAT, (oopDesc*) obj); 1.307 + gclog_or_tty->print_cr(" referent_addr/* " INTPTR_FORMAT " / " 1.308 + INTPTR_FORMAT, referent_addr, 1.309 + referent_addr ? (oopDesc*) *referent_addr : NULL); 1.310 + gclog_or_tty->print_cr(" next_addr/* " INTPTR_FORMAT " / " 1.311 + INTPTR_FORMAT, next_addr, 1.312 + next_addr ? (oopDesc*) *next_addr : NULL); 1.313 + gclog_or_tty->print_cr(" discovered_addr/* " INTPTR_FORMAT " / " 1.314 + INTPTR_FORMAT, discovered_addr, 1.315 + discovered_addr ? (oopDesc*) *discovered_addr : NULL); 1.316 + } 1.317 +#endif 1.318 + 1.319 + return size_helper(); 1.320 +} 1.321 +#endif // SERIALGC 1.322 + 1.323 +void instanceRefKlass::update_nonstatic_oop_maps(klassOop k) { 1.324 + // Clear the nonstatic oop-map entries corresponding to referent 1.325 + // and nextPending field. They are treated specially by the 1.326 + // garbage collector. 1.327 + // The discovered field is used only by the garbage collector 1.328 + // and is also treated specially. 1.329 + instanceKlass* ik = instanceKlass::cast(k); 1.330 + 1.331 + // Check that we have the right class 1.332 + debug_only(static bool first_time = true); 1.333 + assert(k == SystemDictionary::reference_klass() && first_time, 1.334 + "Invalid update of maps"); 1.335 + debug_only(first_time = false); 1.336 + assert(ik->nonstatic_oop_map_size() == 1, "just checking"); 1.337 + 1.338 + OopMapBlock* map = ik->start_of_nonstatic_oop_maps(); 1.339 + 1.340 + // Check that the current map is (2,4) - currently points at field with 1.341 + // offset 2 (words) and has 4 map entries. 1.342 + debug_only(int offset = java_lang_ref_Reference::referent_offset); 1.343 + debug_only(int length = ((java_lang_ref_Reference::discovered_offset - 1.344 + java_lang_ref_Reference::referent_offset)/wordSize) + 1); 1.345 + 1.346 + if (UseSharedSpaces) { 1.347 + assert(map->offset() == java_lang_ref_Reference::queue_offset && 1.348 + map->length() == 1, "just checking"); 1.349 + } else { 1.350 + assert(map->offset() == offset && map->length() == length, 1.351 + "just checking"); 1.352 + 1.353 + // Update map to (3,1) - point to offset of 3 (words) with 1 map entry. 1.354 + map->set_offset(java_lang_ref_Reference::queue_offset); 1.355 + map->set_length(1); 1.356 + } 1.357 +} 1.358 + 1.359 + 1.360 +// Verification 1.361 + 1.362 +void instanceRefKlass::oop_verify_on(oop obj, outputStream* st) { 1.363 + instanceKlass::oop_verify_on(obj, st); 1.364 + // Verify referent field 1.365 + oop referent = java_lang_ref_Reference::referent(obj); 1.366 + 1.367 + // We should make this general to all heaps 1.368 + GenCollectedHeap* gch = NULL; 1.369 + if (Universe::heap()->kind() == CollectedHeap::GenCollectedHeap) 1.370 + gch = GenCollectedHeap::heap(); 1.371 + 1.372 + if (referent != NULL) { 1.373 + guarantee(referent->is_oop(), "referent field heap failed"); 1.374 + if (gch != NULL && !gch->is_in_youngest(obj)) 1.375 + // We do a specific remembered set check here since the referent 1.376 + // field is not part of the oop mask and therefore skipped by the 1.377 + // regular verify code. 1.378 + obj->verify_old_oop(java_lang_ref_Reference::referent_addr(obj), true); 1.379 + } 1.380 + // Verify next field 1.381 + oop next = java_lang_ref_Reference::next(obj); 1.382 + if (next != NULL) { 1.383 + guarantee(next->is_oop(), "next field verify failed"); 1.384 + guarantee(next->is_instanceRef(), "next field verify failed"); 1.385 + if (gch != NULL && !gch->is_in_youngest(obj)) { 1.386 + // We do a specific remembered set check here since the next field is 1.387 + // not part of the oop mask and therefore skipped by the regular 1.388 + // verify code. 1.389 + obj->verify_old_oop(java_lang_ref_Reference::next_addr(obj), true); 1.390 + } 1.391 + } 1.392 +} 1.393 + 1.394 +void instanceRefKlass::acquire_pending_list_lock(BasicLock *pending_list_basic_lock) { 1.395 + // we may enter this with pending exception set 1.396 + PRESERVE_EXCEPTION_MARK; // exceptions are never thrown, needed for TRAPS argument 1.397 + Handle h_lock(THREAD, java_lang_ref_Reference::pending_list_lock()); 1.398 + ObjectSynchronizer::fast_enter(h_lock, pending_list_basic_lock, false, THREAD); 1.399 + assert(ObjectSynchronizer::current_thread_holds_lock( 1.400 + JavaThread::current(), h_lock), 1.401 + "Locking should have succeeded"); 1.402 + if (HAS_PENDING_EXCEPTION) CLEAR_PENDING_EXCEPTION; 1.403 +} 1.404 + 1.405 +void instanceRefKlass::release_and_notify_pending_list_lock( 1.406 + BasicLock *pending_list_basic_lock) { 1.407 + // we may enter this with pending exception set 1.408 + PRESERVE_EXCEPTION_MARK; // exceptions are never thrown, needed for TRAPS argument 1.409 + // 1.410 + Handle h_lock(THREAD, java_lang_ref_Reference::pending_list_lock()); 1.411 + assert(ObjectSynchronizer::current_thread_holds_lock( 1.412 + JavaThread::current(), h_lock), 1.413 + "Lock should be held"); 1.414 + // Notify waiters on pending lists lock if there is any reference. 1.415 + if (java_lang_ref_Reference::pending_list() != NULL) { 1.416 + ObjectSynchronizer::notifyall(h_lock, THREAD); 1.417 + } 1.418 + ObjectSynchronizer::fast_exit(h_lock(), pending_list_basic_lock, THREAD); 1.419 + if (HAS_PENDING_EXCEPTION) CLEAR_PENDING_EXCEPTION; 1.420 +}