src/share/vm/oops/constMethodKlass.cpp

Thu, 07 Apr 2011 09:53:20 -0700

author
johnc
date
Thu, 07 Apr 2011 09:53:20 -0700
changeset 2781
e1162778c1c8
parent 2534
e5383553fd4e
child 3099
c124e2e7463e
permissions
-rw-r--r--

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) 2003, 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 "gc_implementation/shared/markSweep.inline.hpp"
stefank@2314 27 #include "interpreter/interpreter.hpp"
stefank@2314 28 #include "memory/gcLocker.hpp"
stefank@2314 29 #include "memory/resourceArea.hpp"
stefank@2314 30 #include "oops/constMethodKlass.hpp"
stefank@2314 31 #include "oops/constMethodOop.hpp"
stefank@2314 32 #include "oops/oop.inline.hpp"
stefank@2314 33 #include "oops/oop.inline2.hpp"
stefank@2314 34 #include "runtime/handles.inline.hpp"
duke@435 35
duke@435 36
duke@435 37 klassOop constMethodKlass::create_klass(TRAPS) {
duke@435 38 constMethodKlass o;
duke@435 39 KlassHandle h_this_klass(THREAD, Universe::klassKlassObj());
duke@435 40 KlassHandle k = base_create_klass(h_this_klass, header_size(),
duke@435 41 o.vtbl_value(), CHECK_NULL);
duke@435 42 // Make sure size calculation is right
duke@435 43 assert(k()->size() == align_object_size(header_size()),
duke@435 44 "wrong size for object");
duke@435 45 //java_lang_Class::create_mirror(k, CHECK_NULL); // Allocate mirror
duke@435 46 return k();
duke@435 47 }
duke@435 48
duke@435 49
duke@435 50 int constMethodKlass::oop_size(oop obj) const {
duke@435 51 assert(obj->is_constMethod(), "must be constMethod oop");
duke@435 52 return constMethodOop(obj)->object_size();
duke@435 53 }
duke@435 54
duke@435 55 bool constMethodKlass::oop_is_parsable(oop obj) const {
duke@435 56 assert(obj->is_constMethod(), "must be constMethod oop");
duke@435 57 return constMethodOop(obj)->object_is_parsable();
duke@435 58 }
duke@435 59
jmasa@953 60 bool constMethodKlass::oop_is_conc_safe(oop obj) const {
jmasa@953 61 assert(obj->is_constMethod(), "must be constMethod oop");
jmasa@953 62 return constMethodOop(obj)->is_conc_safe();
jmasa@953 63 }
jmasa@953 64
duke@435 65 constMethodOop constMethodKlass::allocate(int byte_code_size,
duke@435 66 int compressed_line_number_size,
duke@435 67 int localvariable_table_length,
duke@435 68 int checked_exceptions_length,
jmasa@953 69 bool is_conc_safe,
duke@435 70 TRAPS) {
duke@435 71
duke@435 72 int size = constMethodOopDesc::object_size(byte_code_size,
duke@435 73 compressed_line_number_size,
duke@435 74 localvariable_table_length,
duke@435 75 checked_exceptions_length);
duke@435 76 KlassHandle h_k(THREAD, as_klassOop());
duke@435 77 constMethodOop cm = (constMethodOop)
duke@435 78 CollectedHeap::permanent_obj_allocate(h_k, size, CHECK_NULL);
duke@435 79 assert(!cm->is_parsable(), "Not yet safely parsable");
duke@435 80 No_Safepoint_Verifier no_safepoint;
duke@435 81 cm->set_interpreter_kind(Interpreter::invalid);
duke@435 82 cm->init_fingerprint();
duke@435 83 cm->set_method(NULL);
duke@435 84 cm->set_stackmap_data(NULL);
duke@435 85 cm->set_exception_table(NULL);
duke@435 86 cm->set_code_size(byte_code_size);
duke@435 87 cm->set_constMethod_size(size);
duke@435 88 cm->set_inlined_tables_length(checked_exceptions_length,
duke@435 89 compressed_line_number_size,
duke@435 90 localvariable_table_length);
duke@435 91 assert(cm->size() == size, "wrong size for object");
jmasa@953 92 cm->set_is_conc_safe(is_conc_safe);
duke@435 93 cm->set_partially_loaded();
duke@435 94 assert(cm->is_parsable(), "Is safely parsable by gc");
duke@435 95 return cm;
duke@435 96 }
duke@435 97
duke@435 98 void constMethodKlass::oop_follow_contents(oop obj) {
duke@435 99 assert (obj->is_constMethod(), "object must be constMethod");
duke@435 100 constMethodOop cm = constMethodOop(obj);
duke@435 101 MarkSweep::mark_and_push(cm->adr_method());
duke@435 102 MarkSweep::mark_and_push(cm->adr_stackmap_data());
duke@435 103 MarkSweep::mark_and_push(cm->adr_exception_table());
duke@435 104 // Performance tweak: We skip iterating over the klass pointer since we
duke@435 105 // know that Universe::constMethodKlassObj never moves.
duke@435 106 }
duke@435 107
duke@435 108 #ifndef SERIALGC
duke@435 109 void constMethodKlass::oop_follow_contents(ParCompactionManager* cm,
duke@435 110 oop obj) {
duke@435 111 assert (obj->is_constMethod(), "object must be constMethod");
duke@435 112 constMethodOop cm_oop = constMethodOop(obj);
duke@435 113 PSParallelCompact::mark_and_push(cm, cm_oop->adr_method());
duke@435 114 PSParallelCompact::mark_and_push(cm, cm_oop->adr_stackmap_data());
duke@435 115 PSParallelCompact::mark_and_push(cm, cm_oop->adr_exception_table());
duke@435 116 // Performance tweak: We skip iterating over the klass pointer since we
duke@435 117 // know that Universe::constMethodKlassObj never moves.
duke@435 118 }
duke@435 119 #endif // SERIALGC
duke@435 120
duke@435 121 int constMethodKlass::oop_oop_iterate(oop obj, OopClosure* blk) {
duke@435 122 assert (obj->is_constMethod(), "object must be constMethod");
duke@435 123 constMethodOop cm = constMethodOop(obj);
duke@435 124 blk->do_oop(cm->adr_method());
duke@435 125 blk->do_oop(cm->adr_stackmap_data());
duke@435 126 blk->do_oop(cm->adr_exception_table());
duke@435 127 // Get size before changing pointers.
duke@435 128 // Don't call size() or oop_size() since that is a virtual call.
duke@435 129 int size = cm->object_size();
duke@435 130 return size;
duke@435 131 }
duke@435 132
duke@435 133
duke@435 134 int constMethodKlass::oop_oop_iterate_m(oop obj, OopClosure* blk, MemRegion mr) {
duke@435 135 assert (obj->is_constMethod(), "object must be constMethod");
duke@435 136 constMethodOop cm = constMethodOop(obj);
duke@435 137 oop* adr;
duke@435 138 adr = cm->adr_method();
duke@435 139 if (mr.contains(adr)) blk->do_oop(adr);
duke@435 140 adr = cm->adr_stackmap_data();
duke@435 141 if (mr.contains(adr)) blk->do_oop(adr);
duke@435 142 adr = cm->adr_exception_table();
duke@435 143 if (mr.contains(adr)) blk->do_oop(adr);
duke@435 144 // Get size before changing pointers.
duke@435 145 // Don't call size() or oop_size() since that is a virtual call.
duke@435 146 int size = cm->object_size();
duke@435 147 // Performance tweak: We skip iterating over the klass pointer since we
duke@435 148 // know that Universe::constMethodKlassObj never moves.
duke@435 149 return size;
duke@435 150 }
duke@435 151
duke@435 152
duke@435 153 int constMethodKlass::oop_adjust_pointers(oop obj) {
duke@435 154 assert(obj->is_constMethod(), "should be constMethod");
duke@435 155 constMethodOop cm = constMethodOop(obj);
duke@435 156 MarkSweep::adjust_pointer(cm->adr_method());
duke@435 157 MarkSweep::adjust_pointer(cm->adr_stackmap_data());
duke@435 158 MarkSweep::adjust_pointer(cm->adr_exception_table());
duke@435 159 // Get size before changing pointers.
duke@435 160 // Don't call size() or oop_size() since that is a virtual call.
duke@435 161 int size = cm->object_size();
duke@435 162 // Performance tweak: We skip iterating over the klass pointer since we
duke@435 163 // know that Universe::constMethodKlassObj never moves.
duke@435 164 return size;
duke@435 165 }
duke@435 166
duke@435 167 #ifndef SERIALGC
duke@435 168 void constMethodKlass::oop_push_contents(PSPromotionManager* pm, oop obj) {
duke@435 169 assert(obj->is_constMethod(), "should be constMethod");
duke@435 170 }
duke@435 171
duke@435 172 int constMethodKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) {
duke@435 173 assert(obj->is_constMethod(), "should be constMethod");
duke@435 174 constMethodOop cm_oop = constMethodOop(obj);
duke@435 175 #if 0
duke@435 176 PSParallelCompact::adjust_pointer(cm_oop->adr_method());
duke@435 177 PSParallelCompact::adjust_pointer(cm_oop->adr_exception_table());
duke@435 178 PSParallelCompact::adjust_pointer(cm_oop->adr_stackmap_data());
duke@435 179 #endif
duke@435 180 oop* const beg_oop = cm_oop->oop_block_beg();
duke@435 181 oop* const end_oop = cm_oop->oop_block_end();
duke@435 182 for (oop* cur_oop = beg_oop; cur_oop < end_oop; ++cur_oop) {
duke@435 183 PSParallelCompact::adjust_pointer(cur_oop);
duke@435 184 }
duke@435 185 return cm_oop->object_size();
duke@435 186 }
duke@435 187 #endif // SERIALGC
duke@435 188
duke@435 189 // Printing
duke@435 190
duke@435 191 void constMethodKlass::oop_print_on(oop obj, outputStream* st) {
duke@435 192 ResourceMark rm;
duke@435 193 assert(obj->is_constMethod(), "must be constMethod");
duke@435 194 Klass::oop_print_on(obj, st);
duke@435 195 constMethodOop m = constMethodOop(obj);
duke@435 196 st->print(" - method: " INTPTR_FORMAT " ", (address)m->method());
duke@435 197 m->method()->print_value_on(st); st->cr();
duke@435 198 st->print(" - exceptions: " INTPTR_FORMAT "\n", (address)m->exception_table());
duke@435 199 if (m->has_stackmap_table()) {
duke@435 200 st->print(" - stackmap data: ");
duke@435 201 m->stackmap_data()->print_value_on(st);
duke@435 202 st->cr();
duke@435 203 }
duke@435 204 }
duke@435 205
duke@435 206 // Short version of printing constMethodOop - just print the name of the
duke@435 207 // method it belongs to.
duke@435 208 void constMethodKlass::oop_print_value_on(oop obj, outputStream* st) {
duke@435 209 assert(obj->is_constMethod(), "must be constMethod");
duke@435 210 constMethodOop m = constMethodOop(obj);
duke@435 211 st->print(" const part of method " );
duke@435 212 m->method()->print_value_on(st);
duke@435 213 }
duke@435 214
duke@435 215 const char* constMethodKlass::internal_name() const {
duke@435 216 return "{constMethod}";
duke@435 217 }
duke@435 218
duke@435 219
duke@435 220 // Verification
duke@435 221
duke@435 222 void constMethodKlass::oop_verify_on(oop obj, outputStream* st) {
duke@435 223 Klass::oop_verify_on(obj, st);
duke@435 224 guarantee(obj->is_constMethod(), "object must be constMethod");
duke@435 225 constMethodOop m = constMethodOop(obj);
duke@435 226 guarantee(m->is_perm(), "should be in permspace");
duke@435 227
duke@435 228 // Verification can occur during oop construction before the method or
duke@435 229 // other fields have been initialized.
duke@435 230 if (!obj->partially_loaded()) {
duke@435 231 guarantee(m->method()->is_perm(), "should be in permspace");
duke@435 232 guarantee(m->method()->is_method(), "should be method");
duke@435 233 typeArrayOop stackmap_data = m->stackmap_data();
duke@435 234 guarantee(stackmap_data == NULL ||
duke@435 235 stackmap_data->is_perm(), "should be in permspace");
duke@435 236 guarantee(m->exception_table()->is_perm(), "should be in permspace");
duke@435 237 guarantee(m->exception_table()->is_typeArray(), "should be type array");
duke@435 238
duke@435 239 address m_end = (address)((oop*) m + m->size());
duke@435 240 address compressed_table_start = m->code_end();
duke@435 241 guarantee(compressed_table_start <= m_end, "invalid method layout");
duke@435 242 address compressed_table_end = compressed_table_start;
duke@435 243 // Verify line number table
duke@435 244 if (m->has_linenumber_table()) {
duke@435 245 CompressedLineNumberReadStream stream(m->compressed_linenumber_table());
duke@435 246 while (stream.read_pair()) {
duke@435 247 guarantee(stream.bci() >= 0 && stream.bci() <= m->code_size(), "invalid bci in line number table");
duke@435 248 }
duke@435 249 compressed_table_end += stream.position();
duke@435 250 }
duke@435 251 guarantee(compressed_table_end <= m_end, "invalid method layout");
duke@435 252 // Verify checked exceptions and local variable tables
duke@435 253 if (m->has_checked_exceptions()) {
duke@435 254 u2* addr = m->checked_exceptions_length_addr();
duke@435 255 guarantee(*addr > 0 && (address) addr >= compressed_table_end && (address) addr < m_end, "invalid method layout");
duke@435 256 }
duke@435 257 if (m->has_localvariable_table()) {
duke@435 258 u2* addr = m->localvariable_table_length_addr();
duke@435 259 guarantee(*addr > 0 && (address) addr >= compressed_table_end && (address) addr < m_end, "invalid method layout");
duke@435 260 }
duke@435 261 // Check compressed_table_end relative to uncompressed_table_start
duke@435 262 u2* uncompressed_table_start;
duke@435 263 if (m->has_localvariable_table()) {
duke@435 264 uncompressed_table_start = (u2*) m->localvariable_table_start();
duke@435 265 } else {
duke@435 266 if (m->has_checked_exceptions()) {
duke@435 267 uncompressed_table_start = (u2*) m->checked_exceptions_start();
duke@435 268 } else {
duke@435 269 uncompressed_table_start = (u2*) m_end;
duke@435 270 }
duke@435 271 }
duke@435 272 int gap = (intptr_t) uncompressed_table_start - (intptr_t) compressed_table_end;
duke@435 273 int max_gap = align_object_size(1)*BytesPerWord;
duke@435 274 guarantee(gap >= 0 && gap < max_gap, "invalid method layout");
duke@435 275 }
duke@435 276 }
duke@435 277
duke@435 278 bool constMethodKlass::oop_partially_loaded(oop obj) const {
duke@435 279 assert(obj->is_constMethod(), "object must be klass");
duke@435 280 constMethodOop m = constMethodOop(obj);
duke@435 281 // check whether exception_table points to self (flag for partially loaded)
duke@435 282 return m->exception_table() == (typeArrayOop)obj;
duke@435 283 }
duke@435 284
duke@435 285
duke@435 286 // The exception_table is the last field set when loading an object.
duke@435 287 void constMethodKlass::oop_set_partially_loaded(oop obj) {
duke@435 288 assert(obj->is_constMethod(), "object must be klass");
duke@435 289 constMethodOop m = constMethodOop(obj);
duke@435 290 // Temporarily set exception_table to point to self
duke@435 291 m->set_exception_table((typeArrayOop)obj);
duke@435 292 }

mercurial