Thu, 07 Apr 2011 09:53:20 -0700
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
Summary: A referent object that is only weakly reachable at the start of concurrent marking but is re-attached to the strongly reachable object graph during marking may not be marked as live. This can cause the reference object to be processed prematurely and leave dangling pointers to the referent object. Implement a read barrier for the java.lang.ref.Reference::referent field by intrinsifying the Reference.get() method, and intercepting accesses though JNI, reflection, and Unsafe, so that when a non-null referent object is read it is also logged in an SATB buffer.
Reviewed-by: kvn, iveresov, never, tonyp, dholmes
duke@435 | 1 | /* |
stefank@2534 | 2 | * Copyright (c) 1998, 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 "gc_implementation/shared/markSweep.inline.hpp" |
stefank@2314 | 28 | #include "gc_interface/collectedHeap.hpp" |
stefank@2314 | 29 | #include "interpreter/bytecodes.hpp" |
stefank@2314 | 30 | #include "memory/genOopClosures.inline.hpp" |
stefank@2314 | 31 | #include "memory/permGen.hpp" |
stefank@2314 | 32 | #include "oops/constantPoolOop.hpp" |
stefank@2314 | 33 | #include "oops/cpCacheKlass.hpp" |
stefank@2314 | 34 | #include "oops/oop.inline.hpp" |
stefank@2314 | 35 | #include "runtime/handles.inline.hpp" |
stefank@2314 | 36 | #ifndef SERIALGC |
stefank@2314 | 37 | #include "gc_implementation/parNew/parOopClosures.inline.hpp" |
stefank@2314 | 38 | #include "gc_implementation/parallelScavenge/psPromotionManager.inline.hpp" |
stefank@2314 | 39 | #include "gc_implementation/parallelScavenge/psScavenge.inline.hpp" |
stefank@2314 | 40 | #include "memory/cardTableRS.hpp" |
stefank@2314 | 41 | #include "oops/oop.pcgc.inline.hpp" |
stefank@2314 | 42 | #endif |
duke@435 | 43 | |
duke@435 | 44 | |
duke@435 | 45 | int constantPoolCacheKlass::oop_size(oop obj) const { |
duke@435 | 46 | assert(obj->is_constantPoolCache(), "must be constantPool"); |
duke@435 | 47 | return constantPoolCacheOop(obj)->object_size(); |
duke@435 | 48 | } |
duke@435 | 49 | |
duke@435 | 50 | |
jmasa@977 | 51 | constantPoolCacheOop constantPoolCacheKlass::allocate(int length, |
jmasa@977 | 52 | TRAPS) { |
duke@435 | 53 | // allocate memory |
duke@435 | 54 | int size = constantPoolCacheOopDesc::object_size(length); |
jmasa@977 | 55 | |
duke@435 | 56 | KlassHandle klass (THREAD, as_klassOop()); |
jmasa@977 | 57 | |
ysr@2533 | 58 | // Commented out below is the original code. The code from |
ysr@2533 | 59 | // permanent_obj_allocate() was in-lined so that we could |
ysr@2533 | 60 | // set the _length field, necessary to correctly compute its |
ysr@2533 | 61 | // size(), before setting its klass word further below. |
jmasa@977 | 62 | // constantPoolCacheOop cache = (constantPoolCacheOop) |
jmasa@977 | 63 | // CollectedHeap::permanent_obj_allocate(klass, size, CHECK_NULL); |
jmasa@977 | 64 | |
jmasa@977 | 65 | oop obj = CollectedHeap::permanent_obj_allocate_no_klass_install(klass, size, CHECK_NULL); |
jmasa@977 | 66 | NOT_PRODUCT(Universe::heap()->check_for_bad_heap_word_value((HeapWord*) obj, |
jmasa@977 | 67 | size)); |
ysr@2533 | 68 | constantPoolCacheOop cache = (constantPoolCacheOop) obj; |
ysr@2533 | 69 | assert(!UseConcMarkSweepGC || obj->klass_or_null() == NULL, |
ysr@2533 | 70 | "klass should be NULL here when using CMS"); |
ysr@2533 | 71 | cache->set_length(length); // should become visible before klass is set below. |
ysr@2533 | 72 | cache->set_constant_pool(NULL); |
jmasa@977 | 73 | |
ysr@2533 | 74 | OrderAccess::storestore(); |
ysr@2533 | 75 | obj->set_klass(klass()); |
ysr@2533 | 76 | assert(cache->size() == size, "Incorrect cache->size()"); |
duke@435 | 77 | return cache; |
duke@435 | 78 | } |
duke@435 | 79 | |
duke@435 | 80 | klassOop constantPoolCacheKlass::create_klass(TRAPS) { |
duke@435 | 81 | constantPoolCacheKlass o; |
coleenp@548 | 82 | KlassHandle h_this_klass(THREAD, Universe::klassKlassObj()); |
coleenp@548 | 83 | KlassHandle k = base_create_klass(h_this_klass, header_size(), o.vtbl_value(), CHECK_NULL); |
coleenp@548 | 84 | // Make sure size calculation is right |
coleenp@548 | 85 | assert(k()->size() == align_object_size(header_size()), "wrong size for object"); |
coleenp@548 | 86 | java_lang_Class::create_mirror(k, CHECK_NULL); // Allocate mirror |
duke@435 | 87 | return k(); |
duke@435 | 88 | } |
duke@435 | 89 | |
duke@435 | 90 | |
duke@435 | 91 | void constantPoolCacheKlass::oop_follow_contents(oop obj) { |
duke@435 | 92 | assert(obj->is_constantPoolCache(), "obj must be constant pool cache"); |
duke@435 | 93 | constantPoolCacheOop cache = (constantPoolCacheOop)obj; |
duke@435 | 94 | // Performance tweak: We skip iterating over the klass pointer since we |
duke@435 | 95 | // know that Universe::constantPoolCacheKlassObj never moves. |
duke@435 | 96 | // gc of constant pool cache instance variables |
duke@435 | 97 | MarkSweep::mark_and_push((oop*)cache->constant_pool_addr()); |
duke@435 | 98 | // gc of constant pool cache entries |
duke@435 | 99 | int i = cache->length(); |
duke@435 | 100 | while (i-- > 0) cache->entry_at(i)->follow_contents(); |
duke@435 | 101 | } |
duke@435 | 102 | |
duke@435 | 103 | #ifndef SERIALGC |
duke@435 | 104 | void constantPoolCacheKlass::oop_follow_contents(ParCompactionManager* cm, |
duke@435 | 105 | oop obj) { |
duke@435 | 106 | assert(obj->is_constantPoolCache(), "obj must be constant pool cache"); |
duke@435 | 107 | constantPoolCacheOop cache = (constantPoolCacheOop)obj; |
duke@435 | 108 | // Performance tweak: We skip iterating over the klass pointer since we |
duke@435 | 109 | // know that Universe::constantPoolCacheKlassObj never moves. |
duke@435 | 110 | // gc of constant pool cache instance variables |
duke@435 | 111 | PSParallelCompact::mark_and_push(cm, (oop*)cache->constant_pool_addr()); |
duke@435 | 112 | // gc of constant pool cache entries |
duke@435 | 113 | int i = cache->length(); |
duke@435 | 114 | while (i-- > 0) cache->entry_at(i)->follow_contents(cm); |
duke@435 | 115 | } |
duke@435 | 116 | #endif // SERIALGC |
duke@435 | 117 | |
duke@435 | 118 | |
duke@435 | 119 | int constantPoolCacheKlass::oop_oop_iterate(oop obj, OopClosure* blk) { |
duke@435 | 120 | assert(obj->is_constantPoolCache(), "obj must be constant pool cache"); |
duke@435 | 121 | constantPoolCacheOop cache = (constantPoolCacheOop)obj; |
duke@435 | 122 | // Get size before changing pointers. |
duke@435 | 123 | // Don't call size() or oop_size() since that is a virtual call. |
duke@435 | 124 | int size = cache->object_size(); |
duke@435 | 125 | // Performance tweak: We skip iterating over the klass pointer since we |
duke@435 | 126 | // know that Universe::constantPoolCacheKlassObj never moves. |
duke@435 | 127 | // iteration over constant pool cache instance variables |
duke@435 | 128 | blk->do_oop((oop*)cache->constant_pool_addr()); |
duke@435 | 129 | // iteration over constant pool cache entries |
duke@435 | 130 | for (int i = 0; i < cache->length(); i++) cache->entry_at(i)->oop_iterate(blk); |
duke@435 | 131 | return size; |
duke@435 | 132 | } |
duke@435 | 133 | |
duke@435 | 134 | |
duke@435 | 135 | int constantPoolCacheKlass::oop_oop_iterate_m(oop obj, OopClosure* blk, MemRegion mr) { |
duke@435 | 136 | assert(obj->is_constantPoolCache(), "obj must be constant pool cache"); |
duke@435 | 137 | constantPoolCacheOop cache = (constantPoolCacheOop)obj; |
duke@435 | 138 | // Get size before changing pointers. |
duke@435 | 139 | // Don't call size() or oop_size() since that is a virtual call. |
duke@435 | 140 | int size = cache->object_size(); |
duke@435 | 141 | // Performance tweak: We skip iterating over the klass pointer since we |
duke@435 | 142 | // know that Universe::constantPoolCacheKlassObj never moves. |
duke@435 | 143 | // iteration over constant pool cache instance variables |
duke@435 | 144 | oop* addr = (oop*)cache->constant_pool_addr(); |
duke@435 | 145 | if (mr.contains(addr)) blk->do_oop(addr); |
duke@435 | 146 | // iteration over constant pool cache entries |
duke@435 | 147 | for (int i = 0; i < cache->length(); i++) cache->entry_at(i)->oop_iterate_m(blk, mr); |
duke@435 | 148 | return size; |
duke@435 | 149 | } |
duke@435 | 150 | |
duke@435 | 151 | int constantPoolCacheKlass::oop_adjust_pointers(oop obj) { |
duke@435 | 152 | assert(obj->is_constantPoolCache(), "obj must be constant pool cache"); |
duke@435 | 153 | constantPoolCacheOop cache = (constantPoolCacheOop)obj; |
duke@435 | 154 | // Get size before changing pointers. |
duke@435 | 155 | // Don't call size() or oop_size() since that is a virtual call. |
duke@435 | 156 | int size = cache->object_size(); |
duke@435 | 157 | // Performance tweak: We skip iterating over the klass pointer since we |
duke@435 | 158 | // know that Universe::constantPoolCacheKlassObj never moves. |
duke@435 | 159 | // Iteration over constant pool cache instance variables |
duke@435 | 160 | MarkSweep::adjust_pointer((oop*)cache->constant_pool_addr()); |
duke@435 | 161 | // iteration over constant pool cache entries |
duke@435 | 162 | for (int i = 0; i < cache->length(); i++) |
duke@435 | 163 | cache->entry_at(i)->adjust_pointers(); |
duke@435 | 164 | return size; |
duke@435 | 165 | } |
duke@435 | 166 | |
duke@435 | 167 | #ifndef SERIALGC |
duke@435 | 168 | void constantPoolCacheKlass::oop_push_contents(PSPromotionManager* pm, |
duke@435 | 169 | oop obj) { |
duke@435 | 170 | assert(obj->is_constantPoolCache(), "should be constant pool"); |
never@2658 | 171 | if (ScavengeRootsInCode) { |
jrose@1161 | 172 | constantPoolCacheOop cache = (constantPoolCacheOop)obj; |
jrose@1161 | 173 | // during a scavenge, it is safe to inspect my pool, since it is perm |
jrose@1161 | 174 | constantPoolOop pool = cache->constant_pool(); |
jrose@1161 | 175 | assert(pool->is_constantPool(), "should be constant pool"); |
never@2658 | 176 | for (int i = 0; i < cache->length(); i++) { |
never@2658 | 177 | ConstantPoolCacheEntry* e = cache->entry_at(i); |
never@2658 | 178 | oop* p = (oop*)&e->_f1; |
never@2658 | 179 | if (PSScavenge::should_scavenge(p)) |
never@2658 | 180 | pm->claim_or_forward_depth(p); |
never@2658 | 181 | assert(!(e->is_vfinal() && PSScavenge::should_scavenge((oop*)&e->_f2)), |
never@2658 | 182 | "no live oops here"); |
jrose@1161 | 183 | } |
jrose@1161 | 184 | } |
duke@435 | 185 | } |
duke@435 | 186 | |
duke@435 | 187 | int |
duke@435 | 188 | constantPoolCacheKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) { |
duke@435 | 189 | assert(obj->is_constantPoolCache(), "obj must be constant pool cache"); |
duke@435 | 190 | constantPoolCacheOop cache = (constantPoolCacheOop)obj; |
duke@435 | 191 | |
duke@435 | 192 | // Iteration over constant pool cache instance variables |
duke@435 | 193 | PSParallelCompact::adjust_pointer((oop*)cache->constant_pool_addr()); |
duke@435 | 194 | |
duke@435 | 195 | // iteration over constant pool cache entries |
duke@435 | 196 | for (int i = 0; i < cache->length(); ++i) { |
duke@435 | 197 | cache->entry_at(i)->update_pointers(); |
duke@435 | 198 | } |
duke@435 | 199 | |
duke@435 | 200 | return cache->object_size(); |
duke@435 | 201 | } |
duke@435 | 202 | #endif // SERIALGC |
duke@435 | 203 | |
duke@435 | 204 | void constantPoolCacheKlass::oop_print_on(oop obj, outputStream* st) { |
duke@435 | 205 | assert(obj->is_constantPoolCache(), "obj must be constant pool cache"); |
duke@435 | 206 | constantPoolCacheOop cache = (constantPoolCacheOop)obj; |
duke@435 | 207 | // super print |
coleenp@548 | 208 | Klass::oop_print_on(obj, st); |
duke@435 | 209 | // print constant pool cache entries |
duke@435 | 210 | for (int i = 0; i < cache->length(); i++) cache->entry_at(i)->print(st, i); |
duke@435 | 211 | } |
duke@435 | 212 | |
jrose@1590 | 213 | void constantPoolCacheKlass::oop_print_value_on(oop obj, outputStream* st) { |
jrose@1590 | 214 | assert(obj->is_constantPoolCache(), "obj must be constant pool cache"); |
jrose@1590 | 215 | constantPoolCacheOop cache = (constantPoolCacheOop)obj; |
jrose@1590 | 216 | st->print("cache [%d]", cache->length()); |
jrose@1590 | 217 | cache->print_address_on(st); |
jrose@1590 | 218 | st->print(" for "); |
jrose@1590 | 219 | cache->constant_pool()->print_value_on(st); |
jrose@1590 | 220 | } |
jrose@1590 | 221 | |
duke@435 | 222 | void constantPoolCacheKlass::oop_verify_on(oop obj, outputStream* st) { |
duke@435 | 223 | guarantee(obj->is_constantPoolCache(), "obj must be constant pool cache"); |
duke@435 | 224 | constantPoolCacheOop cache = (constantPoolCacheOop)obj; |
duke@435 | 225 | // super verify |
coleenp@548 | 226 | Klass::oop_verify_on(obj, st); |
duke@435 | 227 | // print constant pool cache entries |
duke@435 | 228 | for (int i = 0; i < cache->length(); i++) cache->entry_at(i)->verify(st); |
duke@435 | 229 | } |
duke@435 | 230 | |
duke@435 | 231 | |
duke@435 | 232 | const char* constantPoolCacheKlass::internal_name() const { |
duke@435 | 233 | return "{constant pool cache}"; |
duke@435 | 234 | } |