src/share/vm/oops/cpCacheOop.cpp

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

author
johnc
date
Thu, 07 Apr 2011 09:53:20 -0700
changeset 2781
e1162778c1c8
parent 2658
c7f3d0b4570f
child 2742
ed69575596ac
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) 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 "gc_implementation/shared/markSweep.inline.hpp"
stefank@2314 27 #include "interpreter/interpreter.hpp"
stefank@2314 28 #include "interpreter/rewriter.hpp"
stefank@2314 29 #include "memory/universe.inline.hpp"
stefank@2314 30 #include "oops/cpCacheOop.hpp"
stefank@2314 31 #include "oops/objArrayOop.hpp"
stefank@2314 32 #include "oops/oop.inline.hpp"
stefank@2314 33 #include "prims/jvmtiRedefineClassesTrace.hpp"
stefank@2314 34 #include "runtime/handles.inline.hpp"
duke@435 35
duke@435 36
duke@435 37 // Implememtation of ConstantPoolCacheEntry
duke@435 38
jrose@1494 39 void ConstantPoolCacheEntry::initialize_entry(int index) {
jrose@1161 40 assert(0 < index && index < 0x10000, "sanity check");
duke@435 41 _indices = index;
jrose@1161 42 assert(constant_pool_index() == index, "");
duke@435 43 }
duke@435 44
jrose@1494 45 void ConstantPoolCacheEntry::initialize_secondary_entry(int main_index) {
jrose@1494 46 assert(0 <= main_index && main_index < 0x10000, "sanity check");
jrose@1494 47 _indices = (main_index << 16);
jrose@1494 48 assert(main_entry_index() == main_index, "");
jrose@1494 49 }
duke@435 50
duke@435 51 int ConstantPoolCacheEntry::as_flags(TosState state, bool is_final,
duke@435 52 bool is_vfinal, bool is_volatile,
duke@435 53 bool is_method_interface, bool is_method) {
duke@435 54 int f = state;
duke@435 55
duke@435 56 assert( state < number_of_states, "Invalid state in as_flags");
duke@435 57
duke@435 58 f <<= 1;
duke@435 59 if (is_final) f |= 1;
duke@435 60 f <<= 1;
duke@435 61 if (is_vfinal) f |= 1;
duke@435 62 f <<= 1;
duke@435 63 if (is_volatile) f |= 1;
duke@435 64 f <<= 1;
duke@435 65 if (is_method_interface) f |= 1;
duke@435 66 f <<= 1;
duke@435 67 if (is_method) f |= 1;
duke@435 68 f <<= ConstantPoolCacheEntry::hotSwapBit;
duke@435 69 // Preserve existing flag bit values
duke@435 70 #ifdef ASSERT
duke@435 71 int old_state = ((_flags >> tosBits) & 0x0F);
duke@435 72 assert(old_state == 0 || old_state == state,
duke@435 73 "inconsistent cpCache flags state");
duke@435 74 #endif
duke@435 75 return (_flags | f) ;
duke@435 76 }
duke@435 77
duke@435 78 void ConstantPoolCacheEntry::set_bytecode_1(Bytecodes::Code code) {
duke@435 79 #ifdef ASSERT
duke@435 80 // Read once.
duke@435 81 volatile Bytecodes::Code c = bytecode_1();
duke@435 82 assert(c == 0 || c == code || code == 0, "update must be consistent");
duke@435 83 #endif
duke@435 84 // Need to flush pending stores here before bytecode is written.
duke@435 85 OrderAccess::release_store_ptr(&_indices, _indices | ((u_char)code << 16));
duke@435 86 }
duke@435 87
duke@435 88 void ConstantPoolCacheEntry::set_bytecode_2(Bytecodes::Code code) {
duke@435 89 #ifdef ASSERT
duke@435 90 // Read once.
duke@435 91 volatile Bytecodes::Code c = bytecode_2();
duke@435 92 assert(c == 0 || c == code || code == 0, "update must be consistent");
duke@435 93 #endif
duke@435 94 // Need to flush pending stores here before bytecode is written.
duke@435 95 OrderAccess::release_store_ptr(&_indices, _indices | ((u_char)code << 24));
duke@435 96 }
duke@435 97
twisti@2258 98 // Atomically sets f1 if it is still NULL, otherwise it keeps the
twisti@2258 99 // current value.
twisti@2258 100 void ConstantPoolCacheEntry::set_f1_if_null_atomic(oop f1) {
twisti@2553 101 // Use barriers as in oop_store
twisti@2553 102 oop* f1_addr = (oop*) &_f1;
twisti@2553 103 update_barrier_set_pre(f1_addr, f1);
twisti@2553 104 void* result = Atomic::cmpxchg_ptr(f1, f1_addr, NULL);
twisti@2553 105 bool success = (result == NULL);
twisti@2553 106 if (success) {
twisti@2553 107 update_barrier_set(f1_addr, f1);
twisti@2258 108 }
twisti@2553 109 }
twisti@2258 110
duke@435 111 #ifdef ASSERT
duke@435 112 // It is possible to have two different dummy methodOops created
duke@435 113 // when the resolve code for invoke interface executes concurrently
duke@435 114 // Hence the assertion below is weakened a bit for the invokeinterface
duke@435 115 // case.
duke@435 116 bool ConstantPoolCacheEntry::same_methodOop(oop cur_f1, oop f1) {
duke@435 117 return (cur_f1 == f1 || ((methodOop)cur_f1)->name() ==
duke@435 118 ((methodOop)f1)->name() || ((methodOop)cur_f1)->signature() ==
duke@435 119 ((methodOop)f1)->signature());
duke@435 120 }
duke@435 121 #endif
duke@435 122
duke@435 123 // Note that concurrent update of both bytecodes can leave one of them
duke@435 124 // reset to zero. This is harmless; the interpreter will simply re-resolve
duke@435 125 // the damaged entry. More seriously, the memory synchronization is needed
duke@435 126 // to flush other fields (f1, f2) completely to memory before the bytecodes
duke@435 127 // are updated, lest other processors see a non-zero bytecode but zero f1/f2.
duke@435 128 void ConstantPoolCacheEntry::set_field(Bytecodes::Code get_code,
duke@435 129 Bytecodes::Code put_code,
duke@435 130 KlassHandle field_holder,
duke@435 131 int orig_field_index,
duke@435 132 int field_offset,
duke@435 133 TosState field_type,
duke@435 134 bool is_final,
duke@435 135 bool is_volatile) {
never@2658 136 set_f1(field_holder()->java_mirror());
duke@435 137 set_f2(field_offset);
duke@435 138 // The field index is used by jvm/ti and is the index into fields() array
duke@435 139 // in holder instanceKlass. This is scaled by instanceKlass::next_offset.
duke@435 140 assert((orig_field_index % instanceKlass::next_offset) == 0, "wierd index");
duke@435 141 const int field_index = orig_field_index / instanceKlass::next_offset;
duke@435 142 assert(field_index <= field_index_mask,
duke@435 143 "field index does not fit in low flag bits");
duke@435 144 set_flags(as_flags(field_type, is_final, false, is_volatile, false, false) |
duke@435 145 (field_index & field_index_mask));
duke@435 146 set_bytecode_1(get_code);
duke@435 147 set_bytecode_2(put_code);
duke@435 148 NOT_PRODUCT(verify(tty));
duke@435 149 }
duke@435 150
duke@435 151 int ConstantPoolCacheEntry::field_index() const {
duke@435 152 return (_flags & field_index_mask) * instanceKlass::next_offset;
duke@435 153 }
duke@435 154
duke@435 155 void ConstantPoolCacheEntry::set_method(Bytecodes::Code invoke_code,
duke@435 156 methodHandle method,
duke@435 157 int vtable_index) {
jrose@2015 158 assert(!is_secondary_entry(), "");
duke@435 159 assert(method->interpreter_entry() != NULL, "should have been set at this point");
duke@435 160 assert(!method->is_obsolete(), "attempt to write obsolete method to cpCache");
duke@435 161 bool change_to_virtual = (invoke_code == Bytecodes::_invokeinterface);
duke@435 162
duke@435 163 int byte_no = -1;
duke@435 164 bool needs_vfinal_flag = false;
duke@435 165 switch (invoke_code) {
duke@435 166 case Bytecodes::_invokevirtual:
duke@435 167 case Bytecodes::_invokeinterface: {
duke@435 168 if (method->can_be_statically_bound()) {
duke@435 169 set_f2((intptr_t)method());
duke@435 170 needs_vfinal_flag = true;
duke@435 171 } else {
duke@435 172 assert(vtable_index >= 0, "valid index");
duke@435 173 set_f2(vtable_index);
duke@435 174 }
duke@435 175 byte_no = 2;
duke@435 176 break;
duke@435 177 }
jrose@2015 178
jrose@2015 179 case Bytecodes::_invokedynamic: // similar to _invokevirtual
jrose@2015 180 if (TraceInvokeDynamic) {
jrose@2015 181 tty->print_cr("InvokeDynamic set_method%s method="PTR_FORMAT" index=%d",
jrose@2015 182 (is_secondary_entry() ? " secondary" : ""),
jrose@2015 183 (intptr_t)method(), vtable_index);
jrose@2015 184 method->print();
jrose@2015 185 this->print(tty, 0);
jrose@2015 186 }
jrose@2015 187 assert(method->can_be_statically_bound(), "must be a MH invoker method");
jrose@2015 188 assert(AllowTransitionalJSR292 || _f2 >= constantPoolOopDesc::CPCACHE_INDEX_TAG, "BSM index initialized");
twisti@2258 189 // SystemDictionary::find_method_handle_invoke only caches
twisti@2258 190 // methods which signature classes are on the boot classpath,
twisti@2258 191 // otherwise the newly created method is returned. To avoid
twisti@2258 192 // races in that case we store the first one coming in into the
twisti@2258 193 // cp-cache atomically if it's still unset.
twisti@2258 194 set_f1_if_null_atomic(method());
jrose@2015 195 needs_vfinal_flag = false; // _f2 is not an oop
jrose@2015 196 assert(!is_vfinal(), "f2 not an oop");
jrose@2017 197 byte_no = 1; // coordinate this with bytecode_number & is_resolved
jrose@2015 198 break;
jrose@2015 199
duke@435 200 case Bytecodes::_invokespecial:
duke@435 201 // Preserve the value of the vfinal flag on invokevirtual bytecode
duke@435 202 // which may be shared with this constant pool cache entry.
duke@435 203 needs_vfinal_flag = is_resolved(Bytecodes::_invokevirtual) && is_vfinal();
duke@435 204 // fall through
duke@435 205 case Bytecodes::_invokestatic:
duke@435 206 set_f1(method());
duke@435 207 byte_no = 1;
duke@435 208 break;
duke@435 209 default:
duke@435 210 ShouldNotReachHere();
duke@435 211 break;
duke@435 212 }
duke@435 213
duke@435 214 set_flags(as_flags(as_TosState(method->result_type()),
duke@435 215 method->is_final_method(),
duke@435 216 needs_vfinal_flag,
duke@435 217 false,
duke@435 218 change_to_virtual,
duke@435 219 true)|
duke@435 220 method()->size_of_parameters());
duke@435 221
duke@435 222 // Note: byte_no also appears in TemplateTable::resolve.
duke@435 223 if (byte_no == 1) {
duke@435 224 set_bytecode_1(invoke_code);
duke@435 225 } else if (byte_no == 2) {
duke@435 226 if (change_to_virtual) {
duke@435 227 // NOTE: THIS IS A HACK - BE VERY CAREFUL!!!
duke@435 228 //
duke@435 229 // Workaround for the case where we encounter an invokeinterface, but we
duke@435 230 // should really have an _invokevirtual since the resolved method is a
duke@435 231 // virtual method in java.lang.Object. This is a corner case in the spec
duke@435 232 // but is presumably legal. javac does not generate this code.
duke@435 233 //
duke@435 234 // We set bytecode_1() to _invokeinterface, because that is the
duke@435 235 // bytecode # used by the interpreter to see if it is resolved.
duke@435 236 // We set bytecode_2() to _invokevirtual.
duke@435 237 // See also interpreterRuntime.cpp. (8/25/2000)
duke@435 238 // Only set resolved for the invokeinterface case if method is public.
duke@435 239 // Otherwise, the method needs to be reresolved with caller for each
duke@435 240 // interface call.
duke@435 241 if (method->is_public()) set_bytecode_1(invoke_code);
duke@435 242 set_bytecode_2(Bytecodes::_invokevirtual);
duke@435 243 } else {
duke@435 244 set_bytecode_2(invoke_code);
duke@435 245 }
duke@435 246 } else {
duke@435 247 ShouldNotReachHere();
duke@435 248 }
duke@435 249 NOT_PRODUCT(verify(tty));
duke@435 250 }
duke@435 251
duke@435 252
duke@435 253 void ConstantPoolCacheEntry::set_interface_call(methodHandle method, int index) {
jrose@2015 254 assert(!is_secondary_entry(), "");
duke@435 255 klassOop interf = method->method_holder();
duke@435 256 assert(instanceKlass::cast(interf)->is_interface(), "must be an interface");
duke@435 257 set_f1(interf);
duke@435 258 set_f2(index);
duke@435 259 set_flags(as_flags(as_TosState(method->result_type()), method->is_final_method(), false, false, false, true) | method()->size_of_parameters());
duke@435 260 set_bytecode_1(Bytecodes::_invokeinterface);
duke@435 261 }
duke@435 262
duke@435 263
jrose@2015 264 void ConstantPoolCacheEntry::initialize_bootstrap_method_index_in_cache(int bsm_cache_index) {
jrose@2015 265 assert(!is_secondary_entry(), "only for JVM_CONSTANT_InvokeDynamic main entry");
jrose@2015 266 assert(_f2 == 0, "initialize once");
jrose@2015 267 assert(bsm_cache_index == (int)(u2)bsm_cache_index, "oob");
jrose@2015 268 set_f2(bsm_cache_index + constantPoolOopDesc::CPCACHE_INDEX_TAG);
jrose@2015 269 }
jrose@2015 270
jrose@2015 271 int ConstantPoolCacheEntry::bootstrap_method_index_in_cache() {
jrose@2015 272 assert(!is_secondary_entry(), "only for JVM_CONSTANT_InvokeDynamic main entry");
jrose@2015 273 intptr_t bsm_cache_index = (intptr_t) _f2 - constantPoolOopDesc::CPCACHE_INDEX_TAG;
jrose@2015 274 assert(bsm_cache_index == (intptr_t)(u2)bsm_cache_index, "oob");
jrose@2015 275 return (int) bsm_cache_index;
jrose@2015 276 }
jrose@2015 277
jrose@1862 278 void ConstantPoolCacheEntry::set_dynamic_call(Handle call_site,
jrose@1862 279 methodHandle signature_invoker) {
jrose@2015 280 assert(is_secondary_entry(), "");
jrose@1862 281 int param_size = signature_invoker->size_of_parameters();
jrose@1494 282 assert(param_size >= 1, "method argument size must include MH.this");
jrose@1161 283 param_size -= 1; // do not count MH.this; it is not stacked for invokedynamic
jrose@1161 284 if (Atomic::cmpxchg_ptr(call_site(), &_f1, NULL) == NULL) {
jrose@1161 285 // racing threads might be trying to install their own favorites
jrose@1161 286 set_f1(call_site());
jrose@1161 287 }
jrose@1862 288 bool is_final = true;
jrose@1862 289 assert(signature_invoker->is_final_method(), "is_final");
jrose@1862 290 set_flags(as_flags(as_TosState(signature_invoker->result_type()), is_final, false, false, false, true) | param_size);
jrose@1161 291 // do not do set_bytecode on a secondary CP cache entry
jrose@1161 292 //set_bytecode_1(Bytecodes::_invokedynamic);
jrose@1161 293 }
jrose@1161 294
jrose@1161 295
duke@435 296 class LocalOopClosure: public OopClosure {
duke@435 297 private:
duke@435 298 void (*_f)(oop*);
duke@435 299
duke@435 300 public:
duke@435 301 LocalOopClosure(void f(oop*)) { _f = f; }
duke@435 302 virtual void do_oop(oop* o) { _f(o); }
coleenp@548 303 virtual void do_oop(narrowOop *o) { ShouldNotReachHere(); }
duke@435 304 };
duke@435 305
duke@435 306
duke@435 307 void ConstantPoolCacheEntry::oops_do(void f(oop*)) {
duke@435 308 LocalOopClosure blk(f);
duke@435 309 oop_iterate(&blk);
duke@435 310 }
duke@435 311
duke@435 312
duke@435 313 void ConstantPoolCacheEntry::oop_iterate(OopClosure* blk) {
duke@435 314 assert(in_words(size()) == 4, "check code below - may need adjustment");
duke@435 315 // field[1] is always oop or NULL
duke@435 316 blk->do_oop((oop*)&_f1);
duke@435 317 if (is_vfinal()) {
duke@435 318 blk->do_oop((oop*)&_f2);
duke@435 319 }
duke@435 320 }
duke@435 321
duke@435 322
duke@435 323 void ConstantPoolCacheEntry::oop_iterate_m(OopClosure* blk, MemRegion mr) {
duke@435 324 assert(in_words(size()) == 4, "check code below - may need adjustment");
duke@435 325 // field[1] is always oop or NULL
duke@435 326 if (mr.contains((oop *)&_f1)) blk->do_oop((oop*)&_f1);
duke@435 327 if (is_vfinal()) {
duke@435 328 if (mr.contains((oop *)&_f2)) blk->do_oop((oop*)&_f2);
duke@435 329 }
duke@435 330 }
duke@435 331
duke@435 332
duke@435 333 void ConstantPoolCacheEntry::follow_contents() {
duke@435 334 assert(in_words(size()) == 4, "check code below - may need adjustment");
duke@435 335 // field[1] is always oop or NULL
duke@435 336 MarkSweep::mark_and_push((oop*)&_f1);
duke@435 337 if (is_vfinal()) {
duke@435 338 MarkSweep::mark_and_push((oop*)&_f2);
duke@435 339 }
duke@435 340 }
duke@435 341
duke@435 342 #ifndef SERIALGC
duke@435 343 void ConstantPoolCacheEntry::follow_contents(ParCompactionManager* cm) {
duke@435 344 assert(in_words(size()) == 4, "check code below - may need adjustment");
duke@435 345 // field[1] is always oop or NULL
duke@435 346 PSParallelCompact::mark_and_push(cm, (oop*)&_f1);
duke@435 347 if (is_vfinal()) {
duke@435 348 PSParallelCompact::mark_and_push(cm, (oop*)&_f2);
duke@435 349 }
duke@435 350 }
duke@435 351 #endif // SERIALGC
duke@435 352
duke@435 353 void ConstantPoolCacheEntry::adjust_pointers() {
duke@435 354 assert(in_words(size()) == 4, "check code below - may need adjustment");
duke@435 355 // field[1] is always oop or NULL
duke@435 356 MarkSweep::adjust_pointer((oop*)&_f1);
duke@435 357 if (is_vfinal()) {
duke@435 358 MarkSweep::adjust_pointer((oop*)&_f2);
duke@435 359 }
duke@435 360 }
duke@435 361
duke@435 362 #ifndef SERIALGC
duke@435 363 void ConstantPoolCacheEntry::update_pointers() {
duke@435 364 assert(in_words(size()) == 4, "check code below - may need adjustment");
duke@435 365 // field[1] is always oop or NULL
duke@435 366 PSParallelCompact::adjust_pointer((oop*)&_f1);
duke@435 367 if (is_vfinal()) {
duke@435 368 PSParallelCompact::adjust_pointer((oop*)&_f2);
duke@435 369 }
duke@435 370 }
duke@435 371 #endif // SERIALGC
duke@435 372
duke@435 373 // RedefineClasses() API support:
duke@435 374 // If this constantPoolCacheEntry refers to old_method then update it
duke@435 375 // to refer to new_method.
duke@435 376 bool ConstantPoolCacheEntry::adjust_method_entry(methodOop old_method,
duke@435 377 methodOop new_method, bool * trace_name_printed) {
duke@435 378
duke@435 379 if (is_vfinal()) {
duke@435 380 // virtual and final so f2() contains method ptr instead of vtable index
duke@435 381 if (f2() == (intptr_t)old_method) {
duke@435 382 // match old_method so need an update
duke@435 383 _f2 = (intptr_t)new_method;
duke@435 384 if (RC_TRACE_IN_RANGE(0x00100000, 0x00400000)) {
duke@435 385 if (!(*trace_name_printed)) {
duke@435 386 // RC_TRACE_MESG macro has an embedded ResourceMark
duke@435 387 RC_TRACE_MESG(("adjust: name=%s",
duke@435 388 Klass::cast(old_method->method_holder())->external_name()));
duke@435 389 *trace_name_printed = true;
duke@435 390 }
duke@435 391 // RC_TRACE macro has an embedded ResourceMark
duke@435 392 RC_TRACE(0x00400000, ("cpc vf-entry update: %s(%s)",
duke@435 393 new_method->name()->as_C_string(),
duke@435 394 new_method->signature()->as_C_string()));
duke@435 395 }
duke@435 396
duke@435 397 return true;
duke@435 398 }
duke@435 399
duke@435 400 // f1() is not used with virtual entries so bail out
duke@435 401 return false;
duke@435 402 }
duke@435 403
duke@435 404 if ((oop)_f1 == NULL) {
duke@435 405 // NULL f1() means this is a virtual entry so bail out
duke@435 406 // We are assuming that the vtable index does not need change.
duke@435 407 return false;
duke@435 408 }
duke@435 409
duke@435 410 if ((oop)_f1 == old_method) {
duke@435 411 _f1 = new_method;
duke@435 412 if (RC_TRACE_IN_RANGE(0x00100000, 0x00400000)) {
duke@435 413 if (!(*trace_name_printed)) {
duke@435 414 // RC_TRACE_MESG macro has an embedded ResourceMark
duke@435 415 RC_TRACE_MESG(("adjust: name=%s",
duke@435 416 Klass::cast(old_method->method_holder())->external_name()));
duke@435 417 *trace_name_printed = true;
duke@435 418 }
duke@435 419 // RC_TRACE macro has an embedded ResourceMark
duke@435 420 RC_TRACE(0x00400000, ("cpc entry update: %s(%s)",
duke@435 421 new_method->name()->as_C_string(),
duke@435 422 new_method->signature()->as_C_string()));
duke@435 423 }
duke@435 424
duke@435 425 return true;
duke@435 426 }
duke@435 427
duke@435 428 return false;
duke@435 429 }
duke@435 430
duke@435 431 bool ConstantPoolCacheEntry::is_interesting_method_entry(klassOop k) {
duke@435 432 if (!is_method_entry()) {
duke@435 433 // not a method entry so not interesting by default
duke@435 434 return false;
duke@435 435 }
duke@435 436
duke@435 437 methodOop m = NULL;
duke@435 438 if (is_vfinal()) {
duke@435 439 // virtual and final so _f2 contains method ptr instead of vtable index
duke@435 440 m = (methodOop)_f2;
duke@435 441 } else if ((oop)_f1 == NULL) {
duke@435 442 // NULL _f1 means this is a virtual entry so also not interesting
duke@435 443 return false;
duke@435 444 } else {
duke@435 445 if (!((oop)_f1)->is_method()) {
duke@435 446 // _f1 can also contain a klassOop for an interface
duke@435 447 return false;
duke@435 448 }
duke@435 449 m = (methodOop)_f1;
duke@435 450 }
duke@435 451
duke@435 452 assert(m != NULL && m->is_method(), "sanity check");
duke@435 453 if (m == NULL || !m->is_method() || m->method_holder() != k) {
duke@435 454 // robustness for above sanity checks or method is not in
duke@435 455 // the interesting class
duke@435 456 return false;
duke@435 457 }
duke@435 458
duke@435 459 // the method is in the interesting class so the entry is interesting
duke@435 460 return true;
duke@435 461 }
duke@435 462
duke@435 463 void ConstantPoolCacheEntry::print(outputStream* st, int index) const {
duke@435 464 // print separator
duke@435 465 if (index == 0) tty->print_cr(" -------------");
duke@435 466 // print entry
jrose@2015 467 tty->print("%3d ("PTR_FORMAT") ", index, (intptr_t)this);
jrose@1161 468 if (is_secondary_entry())
jrose@1161 469 tty->print_cr("[%5d|secondary]", main_entry_index());
jrose@1161 470 else
jrose@1161 471 tty->print_cr("[%02x|%02x|%5d]", bytecode_2(), bytecode_1(), constant_pool_index());
jrose@2015 472 tty->print_cr(" [ "PTR_FORMAT"]", (intptr_t)(oop)_f1);
jrose@2015 473 tty->print_cr(" [ "PTR_FORMAT"]", (intptr_t)_f2);
jrose@2015 474 tty->print_cr(" [ "PTR_FORMAT"]", (intptr_t)_flags);
duke@435 475 tty->print_cr(" -------------");
duke@435 476 }
duke@435 477
duke@435 478 void ConstantPoolCacheEntry::verify(outputStream* st) const {
duke@435 479 // not implemented yet
duke@435 480 }
duke@435 481
duke@435 482 // Implementation of ConstantPoolCache
duke@435 483
duke@435 484 void constantPoolCacheOopDesc::initialize(intArray& inverse_index_map) {
duke@435 485 assert(inverse_index_map.length() == length(), "inverse index map must have same length as cache");
jrose@1494 486 for (int i = 0; i < length(); i++) {
jrose@1494 487 ConstantPoolCacheEntry* e = entry_at(i);
jrose@1494 488 int original_index = inverse_index_map[i];
jrose@1494 489 if ((original_index & Rewriter::_secondary_entry_tag) != 0) {
jrose@1494 490 int main_index = (original_index - Rewriter::_secondary_entry_tag);
jrose@1494 491 assert(!entry_at(main_index)->is_secondary_entry(), "valid main index");
jrose@1494 492 e->initialize_secondary_entry(main_index);
jrose@1494 493 } else {
jrose@1494 494 e->initialize_entry(original_index);
jrose@1494 495 }
jrose@1494 496 assert(entry_at(i) == e, "sanity");
jrose@1494 497 }
duke@435 498 }
duke@435 499
duke@435 500 // RedefineClasses() API support:
duke@435 501 // If any entry of this constantPoolCache points to any of
duke@435 502 // old_methods, replace it with the corresponding new_method.
duke@435 503 void constantPoolCacheOopDesc::adjust_method_entries(methodOop* old_methods, methodOop* new_methods,
duke@435 504 int methods_length, bool * trace_name_printed) {
duke@435 505
duke@435 506 if (methods_length == 0) {
duke@435 507 // nothing to do if there are no methods
duke@435 508 return;
duke@435 509 }
duke@435 510
duke@435 511 // get shorthand for the interesting class
duke@435 512 klassOop old_holder = old_methods[0]->method_holder();
duke@435 513
duke@435 514 for (int i = 0; i < length(); i++) {
duke@435 515 if (!entry_at(i)->is_interesting_method_entry(old_holder)) {
duke@435 516 // skip uninteresting methods
duke@435 517 continue;
duke@435 518 }
duke@435 519
duke@435 520 // The constantPoolCache contains entries for several different
duke@435 521 // things, but we only care about methods. In fact, we only care
duke@435 522 // about methods in the same class as the one that contains the
duke@435 523 // old_methods. At this point, we have an interesting entry.
duke@435 524
duke@435 525 for (int j = 0; j < methods_length; j++) {
duke@435 526 methodOop old_method = old_methods[j];
duke@435 527 methodOop new_method = new_methods[j];
duke@435 528
duke@435 529 if (entry_at(i)->adjust_method_entry(old_method, new_method,
duke@435 530 trace_name_printed)) {
duke@435 531 // current old_method matched this entry and we updated it so
duke@435 532 // break out and get to the next interesting entry if there one
duke@435 533 break;
duke@435 534 }
duke@435 535 }
duke@435 536 }
duke@435 537 }

mercurial