257 assert(method->method_holder()->is_interface() || method->method_holder()->verify_vtable_index(index), ""); |
257 assert(method->method_holder()->is_interface() || method->method_holder()->verify_vtable_index(index), ""); |
258 // index >= 0; FIXME: inline and customize set_direct_or_vtable_call |
258 // index >= 0; FIXME: inline and customize set_direct_or_vtable_call |
259 set_direct_or_vtable_call(invoke_code, method, index, false); |
259 set_direct_or_vtable_call(invoke_code, method, index, false); |
260 } |
260 } |
261 |
261 |
262 void ConstantPoolCacheEntry::set_itable_call(Bytecodes::Code invoke_code, methodHandle method, int index) { |
262 void ConstantPoolCacheEntry::set_itable_call(Bytecodes::Code invoke_code, |
|
263 KlassHandle referenced_klass, |
|
264 methodHandle method, int index) { |
263 assert(method->method_holder()->verify_itable_index(index), ""); |
265 assert(method->method_holder()->verify_itable_index(index), ""); |
264 assert(invoke_code == Bytecodes::_invokeinterface, ""); |
266 assert(invoke_code == Bytecodes::_invokeinterface, ""); |
265 InstanceKlass* interf = method->method_holder(); |
267 InstanceKlass* interf = method->method_holder(); |
266 assert(interf->is_interface(), "must be an interface"); |
268 assert(interf->is_interface(), "must be an interface"); |
267 assert(!method->is_final_method(), "interfaces do not have final methods; cannot link to one here"); |
269 assert(!method->is_final_method(), "interfaces do not have final methods; cannot link to one here"); |
268 set_f1(interf); |
270 set_f1(referenced_klass()); |
269 set_f2(index); |
271 set_f2((intx)method()); |
270 set_method_flags(as_TosState(method->result_type()), |
272 set_method_flags(as_TosState(method->result_type()), |
271 0, // no option bits |
273 0, // no option bits |
272 method()->size_of_parameters()); |
274 method()->size_of_parameters()); |
273 set_bytecode_1(Bytecodes::_invokeinterface); |
275 set_bytecode_1(Bytecodes::_invokeinterface); |
274 } |
276 } |
431 return resolved_references->obj_at(ref_index); |
433 return resolved_references->obj_at(ref_index); |
432 } |
434 } |
433 |
435 |
434 |
436 |
435 #if INCLUDE_JVMTI |
437 #if INCLUDE_JVMTI |
|
438 |
|
439 void log_adjust(const char* entry_type, Method* old_method, Method* new_method, bool* trace_name_printed) { |
|
440 if (RC_TRACE_IN_RANGE(0x00100000, 0x00400000)) { |
|
441 if (!(*trace_name_printed)) { |
|
442 // RC_TRACE_MESG macro has an embedded ResourceMark |
|
443 RC_TRACE_MESG(("adjust: name=%s", |
|
444 old_method->method_holder()->external_name())); |
|
445 *trace_name_printed = true; |
|
446 } |
|
447 // RC_TRACE macro has an embedded ResourceMark |
|
448 RC_TRACE(0x00400000, ("cpc %s entry update: %s(%s)", |
|
449 entry_type, |
|
450 new_method->name()->as_C_string(), |
|
451 new_method->signature()->as_C_string())); |
|
452 } |
|
453 } |
|
454 |
436 // RedefineClasses() API support: |
455 // RedefineClasses() API support: |
437 // If this ConstantPoolCacheEntry refers to old_method then update it |
456 // If this ConstantPoolCacheEntry refers to old_method then update it |
438 // to refer to new_method. |
457 // to refer to new_method. |
439 bool ConstantPoolCacheEntry::adjust_method_entry(Method* old_method, |
458 void ConstantPoolCacheEntry::adjust_method_entry(Method* old_method, |
440 Method* new_method, bool * trace_name_printed) { |
459 Method* new_method, bool * trace_name_printed) { |
441 |
460 |
442 if (is_vfinal()) { |
461 if (is_vfinal()) { |
443 // virtual and final so _f2 contains method ptr instead of vtable index |
462 // virtual and final so _f2 contains method ptr instead of vtable index |
444 if (f2_as_vfinal_method() == old_method) { |
463 if (f2_as_vfinal_method() == old_method) { |
445 // match old_method so need an update |
464 // match old_method so need an update |
446 // NOTE: can't use set_f2_as_vfinal_method as it asserts on different values |
465 // NOTE: can't use set_f2_as_vfinal_method as it asserts on different values |
447 _f2 = (intptr_t)new_method; |
466 _f2 = (intptr_t)new_method; |
448 if (RC_TRACE_IN_RANGE(0x00100000, 0x00400000)) { |
467 } |
449 if (!(*trace_name_printed)) { |
468 return; |
450 // RC_TRACE_MESG macro has an embedded ResourceMark |
469 } |
451 RC_TRACE_MESG(("adjust: name=%s", |
470 |
452 old_method->method_holder()->external_name())); |
471 assert (_f1 != NULL, "should not call with uninteresting entry"); |
453 *trace_name_printed = true; |
472 |
454 } |
473 if (!(_f1->is_method())) { |
455 // RC_TRACE macro has an embedded ResourceMark |
474 // _f1 is a Klass* for an interface, _f2 is the method |
456 RC_TRACE(0x00400000, ("cpc vf-entry update: %s(%s)", |
475 if (f2_as_interface_method() == old_method) { |
457 new_method->name()->as_C_string(), |
476 _f2 = (intptr_t)new_method; |
458 new_method->signature()->as_C_string())); |
477 log_adjust("interface", old_method, new_method, trace_name_printed); |
459 } |
478 } |
460 return true; |
479 } else if (_f1 == old_method) { |
461 } |
|
462 |
|
463 // f1() is not used with virtual entries so bail out |
|
464 return false; |
|
465 } |
|
466 |
|
467 if (_f1 == NULL) { |
|
468 // NULL f1() means this is a virtual entry so bail out |
|
469 // We are assuming that the vtable index does not need change. |
|
470 return false; |
|
471 } |
|
472 |
|
473 if (_f1 == old_method) { |
|
474 _f1 = new_method; |
480 _f1 = new_method; |
475 if (RC_TRACE_IN_RANGE(0x00100000, 0x00400000)) { |
481 log_adjust("special, static or dynamic", old_method, new_method, trace_name_printed); |
476 if (!(*trace_name_printed)) { |
482 } |
477 // RC_TRACE_MESG macro has an embedded ResourceMark |
|
478 RC_TRACE_MESG(("adjust: name=%s", |
|
479 old_method->method_holder()->external_name())); |
|
480 *trace_name_printed = true; |
|
481 } |
|
482 // RC_TRACE macro has an embedded ResourceMark |
|
483 RC_TRACE(0x00400000, ("cpc entry update: %s(%s)", |
|
484 new_method->name()->as_C_string(), |
|
485 new_method->signature()->as_C_string())); |
|
486 } |
|
487 return true; |
|
488 } |
|
489 |
|
490 return false; |
|
491 } |
483 } |
492 |
484 |
493 // a constant pool cache entry should never contain old or obsolete methods |
485 // a constant pool cache entry should never contain old or obsolete methods |
494 bool ConstantPoolCacheEntry::check_no_old_or_obsolete_entries() { |
486 bool ConstantPoolCacheEntry::check_no_old_or_obsolete_entries() { |
495 if (is_vfinal()) { |
487 Method* m = get_interesting_method_entry(NULL); |
496 // virtual and final so _f2 contains method ptr instead of vtable index |
488 // return false if m refers to a non-deleted old or obsolete method |
497 Metadata* f2 = (Metadata*)_f2; |
489 if (m != NULL) { |
498 // Return false if _f2 refers to an old or an obsolete method. |
490 assert(m->is_valid() && m->is_method(), "m is a valid method"); |
499 // _f2 == NULL || !_f2->is_method() are just as unexpected here. |
491 return !m->is_old() && !m->is_obsolete(); // old is always set for old and obsolete |
500 return (f2 != NULL NOT_PRODUCT(&& f2->is_valid()) && f2->is_method() && |
492 } else { |
501 !((Method*)f2)->is_old() && !((Method*)f2)->is_obsolete()); |
|
502 } else if (_f1 == NULL || |
|
503 (NOT_PRODUCT(_f1->is_valid() &&) !_f1->is_method())) { |
|
504 // _f1 == NULL || !_f1->is_method() are OK here |
|
505 return true; |
493 return true; |
506 } |
494 } |
507 // return false if _f1 refers to a non-deleted old or obsolete method |
|
508 return (NOT_PRODUCT(_f1->is_valid() &&) _f1->is_method() && |
|
509 (f1_as_method()->is_deleted() || |
|
510 (!f1_as_method()->is_old() && !f1_as_method()->is_obsolete()))); |
|
511 } |
495 } |
512 |
496 |
513 Method* ConstantPoolCacheEntry::get_interesting_method_entry(Klass* k) { |
497 Method* ConstantPoolCacheEntry::get_interesting_method_entry(Klass* k) { |
514 if (!is_method_entry()) { |
498 if (!is_method_entry()) { |
515 // not a method entry so not interesting by default |
499 // not a method entry so not interesting by default |