src/share/vm/oops/klassVtable.cpp
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File
8014013 Cdiff src/share/vm/oops/klassVtable.cpp
src/share/vm/oops/klassVtable.cpp
Print this page
*** 45,59 ****
return (InstanceKlass*)k;
}
// this function computes the vtable size (including the size needed for miranda
! // methods) and the number of miranda methods in this class
// Note on Miranda methods: Let's say there is a class C that implements
! // interface I. Let's say there is a method m in I that neither C nor any
! // of its super classes implement (i.e there is no method of any access, with
! // the same name and signature as m), then m is a Miranda method which is
// entered as a public abstract method in C's vtable. From then on it should
// treated as any other public method in C for method over-ride purposes.
void klassVtable::compute_vtable_size_and_num_mirandas(
int* vtable_length_ret, int* num_new_mirandas,
GrowableArray<Method*>* all_mirandas, Klass* super,
--- 45,60 ----
return (InstanceKlass*)k;
}
// this function computes the vtable size (including the size needed for miranda
! // methods) and the number of miranda methods in this class.
// Note on Miranda methods: Let's say there is a class C that implements
! // interface I, and none of C's superclasses implements I.
! // Let's say there is an abstract method m in I that neither C
! // nor any of its super classes implement (i.e there is no method of any access,
! // with the same name and signature as m), then m is a Miranda method which is
// entered as a public abstract method in C's vtable. From then on it should
// treated as any other public method in C for method over-ride purposes.
void klassVtable::compute_vtable_size_and_num_mirandas(
int* vtable_length_ret, int* num_new_mirandas,
GrowableArray<Method*>* all_mirandas, Klass* super,
*** 109,122 ****
*vtable_length_ret = vtable_length;
}
int klassVtable::index_of(Method* m, int len) const {
! assert(m->vtable_index() >= 0, "do not ask this of non-vtable methods");
return m->vtable_index();
}
int klassVtable::initialize_from_super(KlassHandle super) {
if (super.is_null()) {
return 0;
} else {
// copy methods from superKlass
--- 110,126 ----
*vtable_length_ret = vtable_length;
}
int klassVtable::index_of(Method* m, int len) const {
! assert(m->has_vtable_index(), "do not ask this of non-vtable methods");
return m->vtable_index();
}
+ // Copy super class's vtable to the first part (prefix) of this class's vtable,
+ // and return the number of entries copied. Expects that 'super' is the Java
+ // super class (arrays can have "array" super classes that must be skipped).
int klassVtable::initialize_from_super(KlassHandle super) {
if (super.is_null()) {
return 0;
} else {
// copy methods from superKlass
*** 137,154 ****
#endif
return superVtable->length();
}
}
! // Revised lookup semantics introduced 1.3 (Kestral beta)
void klassVtable::initialize_vtable(bool checkconstraints, TRAPS) {
// Note: Arrays can have intermediate array supers. Use java_super to skip them.
KlassHandle super (THREAD, klass()->java_super());
int nofNewEntries = 0;
-
if (PrintVtables && !klass()->oop_is_array()) {
ResourceMark rm(THREAD);
tty->print_cr("Initializing: %s", _klass->name()->as_C_string());
}
--- 141,158 ----
#endif
return superVtable->length();
}
}
! //
! // Revised lookup semantics introduced 1.3 (Kestrel beta)
void klassVtable::initialize_vtable(bool checkconstraints, TRAPS) {
// Note: Arrays can have intermediate array supers. Use java_super to skip them.
KlassHandle super (THREAD, klass()->java_super());
int nofNewEntries = 0;
if (PrintVtables && !klass()->oop_is_array()) {
ResourceMark rm(THREAD);
tty->print_cr("Initializing: %s", _klass->name()->as_C_string());
}
*** 172,183 ****
Array<Method*>* methods = ik()->methods();
int len = methods->length();
int initialized = super_vtable_len;
! // update_inherited_vtable can stop for gc - ensure using handles
for (int i = 0; i < len; i++) {
HandleMark hm(THREAD);
assert(methods->at(i)->is_method(), "must be a Method*");
methodHandle mh(THREAD, methods->at(i));
bool needs_new_entry = update_inherited_vtable(ik(), mh, super_vtable_len, checkconstraints, CHECK);
--- 176,189 ----
Array<Method*>* methods = ik()->methods();
int len = methods->length();
int initialized = super_vtable_len;
! // Check each of this class's methods against super;
! // if override, replace in copy of super vtable, otherwise append to end
for (int i = 0; i < len; i++) {
+ // update_inherited_vtable can stop for gc - ensure using handles
HandleMark hm(THREAD);
assert(methods->at(i)->is_method(), "must be a Method*");
methodHandle mh(THREAD, methods->at(i));
bool needs_new_entry = update_inherited_vtable(ik(), mh, super_vtable_len, checkconstraints, CHECK);
*** 187,201 ****
mh()->set_vtable_index(initialized); // set primary vtable index
initialized++;
}
}
! // add miranda methods; it will also update the value of initialized
! fill_in_mirandas(&initialized);
// In class hierarchies where the accessibility is not increasing (i.e., going from private ->
! // package_private -> publicprotected), the vtable might actually be smaller than our initial
// calculation.
assert(initialized <= _length, "vtable initialization failed");
for(;initialized < _length; initialized++) {
put_method_at(NULL, initialized);
}
--- 193,207 ----
mh()->set_vtable_index(initialized); // set primary vtable index
initialized++;
}
}
! // add miranda methods to end of vtable.
! initialized = fill_in_mirandas(initialized);
// In class hierarchies where the accessibility is not increasing (i.e., going from private ->
! // package_private -> public/protected), the vtable might actually be smaller than our initial
// calculation.
assert(initialized <= _length, "vtable initialization failed");
for(;initialized < _length; initialized++) {
put_method_at(NULL, initialized);
}
*** 246,285 ****
}
return superk;
}
- // Methods that are "effectively" final don't need vtable entries.
- bool method_is_effectively_final(
- AccessFlags klass_flags, methodHandle target) {
- return target->is_final() || klass_flags.is_final() && !target->is_overpass();
- }
-
// Update child's copy of super vtable for overrides
! // OR return true if a new vtable entry is required
// Only called for InstanceKlass's, i.e. not for arrays
// If that changed, could not use _klass as handle for klass
bool klassVtable::update_inherited_vtable(InstanceKlass* klass, methodHandle target_method, int super_vtable_len,
bool checkconstraints, TRAPS) {
ResourceMark rm;
bool allocate_new = true;
assert(klass->oop_is_instance(), "must be InstanceKlass");
// Initialize the method's vtable index to "nonvirtual".
// If we allocate a vtable entry, we will update it to a non-negative number.
target_method()->set_vtable_index(Method::nonvirtual_vtable_index);
// Static and <init> methods are never in
if (target_method()->is_static() || target_method()->name() == vmSymbols::object_initializer_name()) {
return false;
}
! if (method_is_effectively_final(klass->access_flags(), target_method)) {
// a final method never needs a new entry; final methods can be statically
// resolved and they have to be present in the vtable only if they override
// a super's method, in which case they re-use its entry
allocate_new = false;
}
// we need a new entry if there is no superclass
if (klass->super() == NULL) {
return allocate_new;
--- 252,292 ----
}
return superk;
}
// Update child's copy of super vtable for overrides
! // OR return true if a new vtable entry is required.
// Only called for InstanceKlass's, i.e. not for arrays
// If that changed, could not use _klass as handle for klass
bool klassVtable::update_inherited_vtable(InstanceKlass* klass, methodHandle target_method, int super_vtable_len,
bool checkconstraints, TRAPS) {
ResourceMark rm;
bool allocate_new = true;
assert(klass->oop_is_instance(), "must be InstanceKlass");
+ assert(klass == target_method()->method_holder(), "caller resp.");
// Initialize the method's vtable index to "nonvirtual".
// If we allocate a vtable entry, we will update it to a non-negative number.
target_method()->set_vtable_index(Method::nonvirtual_vtable_index);
// Static and <init> methods are never in
if (target_method()->is_static() || target_method()->name() == vmSymbols::object_initializer_name()) {
return false;
}
! if (target_method->is_final_method(klass->access_flags())) {
// a final method never needs a new entry; final methods can be statically
// resolved and they have to be present in the vtable only if they override
// a super's method, in which case they re-use its entry
allocate_new = false;
+ } else if (klass->is_interface()) {
+ allocate_new = false; // see note below in needs_new_vtable_entry
+ // An interface never allocates new vtable slots, only inherits old ones.
+ // This method will either be assigned its own itable index later,
+ // or be assigned an inherited vtable index in the loop below.
+ target_method()->set_vtable_index(Method::pending_itable_index);
}
// we need a new entry if there is no superclass
if (klass->super() == NULL) {
return allocate_new;
*** 409,420 ****
Klass* super,
Handle classloader,
Symbol* classname,
AccessFlags class_flags,
TRAPS) {
! if (method_is_effectively_final(class_flags, target_method) ||
// a final method never needs a new entry; final methods can be statically
// resolved and they have to be present in the vtable only if they override
// a super's method, in which case they re-use its entry
(target_method()->is_static()) ||
// static methods don't need to be in vtable
--- 416,433 ----
Klass* super,
Handle classloader,
Symbol* classname,
AccessFlags class_flags,
TRAPS) {
+ if (class_flags.is_interface()) {
+ // Interfaces do not use vtables, so there is no point to assigning
+ // a vtable index to any of their methods. If we refrain from doing this,
+ // we can use Method::_vtable_index to hold the itable index
+ return false;
+ }
! if (target_method->is_final_method(class_flags) ||
// a final method never needs a new entry; final methods can be statically
// resolved and they have to be present in the vtable only if they override
// a super's method, in which case they re-use its entry
(target_method()->is_static()) ||
// static methods don't need to be in vtable
*** 498,508 ****
}
}
return Method::invalid_vtable_index;
}
! // check if an entry is miranda
bool klassVtable::is_miranda_entry_at(int i) {
Method* m = method_at(i);
Klass* method_holder = m->method_holder();
InstanceKlass *mhk = InstanceKlass::cast(method_holder);
--- 511,522 ----
}
}
return Method::invalid_vtable_index;
}
! // check if an entry at an index is miranda
! // requires that method m at entry be declared ("held") by an interface.
bool klassVtable::is_miranda_entry_at(int i) {
Method* m = method_at(i);
Klass* method_holder = m->method_holder();
InstanceKlass *mhk = InstanceKlass::cast(method_holder);
*** 514,524 ****
return true;
}
return false;
}
! // check if a method is a miranda method, given a class's methods table and it's super
// the caller must make sure that the method belongs to an interface implemented by the class
bool klassVtable::is_miranda(Method* m, Array<Method*>* class_methods, Klass* super) {
if (m->is_static()) {
return false;
}
--- 528,540 ----
return true;
}
return false;
}
! // check if a method is a miranda method, given a class's methods table and its super
! // "miranda" means not static, not defined by this class, and not defined
! // in super unless it is private and therefore inaccessible to this class.
// the caller must make sure that the method belongs to an interface implemented by the class
bool klassVtable::is_miranda(Method* m, Array<Method*>* class_methods, Klass* super) {
if (m->is_static()) {
return false;
}
*** 539,548 ****
--- 555,572 ----
}
return false;
}
+ // Scans current_interface_methods for miranda methods that do not
+ // already appear in new_mirandas and are also not defined-and-non-private
+ // in super (superclass). These mirandas are added to all_mirandas if it is
+ // not null; in addition, those that are not duplicates of miranda methods
+ // inherited by super from its interfaces are added to new_mirandas.
+ // Thus, new_mirandas will be the set of mirandas that this class introduces,
+ // all_mirandas will be the set of all mirandas applicable to this class
+ // including all defined in superclasses.
void klassVtable::add_new_mirandas_to_lists(
GrowableArray<Method*>* new_mirandas, GrowableArray<Method*>* all_mirandas,
Array<Method*>* current_interface_methods, Array<Method*>* class_methods,
Klass* super) {
// iterate thru the current interface's method to see if it a miranda
*** 597,617 ****
sik->methods(), class_methods, super);
}
}
}
! // fill in mirandas
! void klassVtable::fill_in_mirandas(int* initialized) {
GrowableArray<Method*> mirandas(20);
get_mirandas(&mirandas, NULL, ik()->super(), ik()->methods(),
ik()->local_interfaces());
for (int i = 0; i < mirandas.length(); i++) {
! put_method_at(mirandas.at(i), *initialized);
! ++(*initialized);
}
}
void klassVtable::copy_vtable_to(vtableEntry* start) {
Copy::disjoint_words((HeapWord*)table(), (HeapWord*)start, _length * vtableEntry::size());
}
#if INCLUDE_JVMTI
--- 621,646 ----
sik->methods(), class_methods, super);
}
}
}
! // Discover miranda methods ("miranda" = "interface abstract, no binding"),
! // and append them into the vtable starting at index initialized,
! // return the new value of initialized.
! int klassVtable::fill_in_mirandas(int initialized) {
GrowableArray<Method*> mirandas(20);
get_mirandas(&mirandas, NULL, ik()->super(), ik()->methods(),
ik()->local_interfaces());
for (int i = 0; i < mirandas.length(); i++) {
! put_method_at(mirandas.at(i), initialized);
! ++initialized;
}
+ return initialized;
}
+ // Copy this class's vtable to the vtable beginning at start.
+ // Used to copy superclass vtable to prefix of subclass's vtable.
void klassVtable::copy_vtable_to(vtableEntry* start) {
Copy::disjoint_words((HeapWord*)table(), (HeapWord*)start, _length * vtableEntry::size());
}
#if INCLUDE_JVMTI
*** 721,730 ****
--- 750,765 ----
static int initialize_count = 0;
// Initialization
void klassItable::initialize_itable(bool checkconstraints, TRAPS) {
+ if (_klass->is_interface()) {
+ // This needs to go after vtable indexes are assigned but
+ // before implementors need to know the number of itable indexes.
+ assign_itable_indexes_for_interface(_klass());
+ }
+
// Cannot be setup doing bootstrapping, interfaces don't have
// itables, and klass with only ones entry have empty itables
if (Universe::is_bootstrapping() ||
_klass->is_interface() ||
_klass->itable_length() == itableOffsetEntry::size()) return;
*** 752,813 ****
itableOffsetEntry* ioe = offset_entry(size_offset_table() - 1);
guarantee(ioe->interface_klass() == NULL && ioe->offset() == 0, "terminator entry missing");
}
void klassItable::initialize_itable_for_interface(int method_table_offset, KlassHandle interf_h, bool checkconstraints, TRAPS) {
Array<Method*>* methods = InstanceKlass::cast(interf_h())->methods();
int nof_methods = methods->length();
HandleMark hm;
- KlassHandle klass = _klass;
assert(nof_methods > 0, "at least one method must exist for interface to be in vtable");
Handle interface_loader (THREAD, InstanceKlass::cast(interf_h())->class_loader());
- int ime_num = 0;
! // Skip first Method* if it is a class initializer
! int i = methods->at(0)->is_static_initializer() ? 1 : 0;
!
! // m, method_name, method_signature, klass reset each loop so they
! // don't need preserving across check_signature_loaders call
! // methods needs a handle in case of gc from check_signature_loaders
! for(; i < nof_methods; i++) {
Method* m = methods->at(i);
! Symbol* method_name = m->name();
! Symbol* method_signature = m->signature();
!
! // This is same code as in Linkresolver::lookup_instance_method_in_klasses
! Method* target = klass->uncached_lookup_method(method_name, method_signature);
! while (target != NULL && target->is_static()) {
! // continue with recursive lookup through the superclass
! Klass* super = target->method_holder()->super();
! target = (super == NULL) ? (Method*)NULL : super->uncached_lookup_method(method_name, method_signature);
}
if (target == NULL || !target->is_public() || target->is_abstract()) {
// Entry do not resolve. Leave it empty
} else {
// Entry did resolve, check loader constraints before initializing
// if checkconstraints requested
- methodHandle target_h (THREAD, target); // preserve across gc
if (checkconstraints) {
Handle method_holder_loader (THREAD, target->method_holder()->class_loader());
if (method_holder_loader() != interface_loader()) {
ResourceMark rm(THREAD);
Symbol* failed_type_symbol =
! SystemDictionary::check_signature_loaders(method_signature,
method_holder_loader,
interface_loader,
true, CHECK);
if (failed_type_symbol != NULL) {
const char* msg = "loader constraint violation in interface "
"itable initialization: when resolving method \"%s\" the class"
" loader (instance of %s) of the current class, %s, "
"and the class loader (instance of %s) for interface "
"%s have different Class objects for the type %s "
"used in the signature";
! char* sig = target_h()->name_and_sig_as_C_string();
const char* loader1 = SystemDictionary::loader_name(method_holder_loader());
! char* current = klass->name()->as_C_string();
const char* loader2 = SystemDictionary::loader_name(interface_loader());
char* iface = InstanceKlass::cast(interf_h())->name()->as_C_string();
char* failed_type_name = failed_type_symbol->as_C_string();
size_t buflen = strlen(msg) + strlen(sig) + strlen(loader1) +
strlen(current) + strlen(loader2) + strlen(iface) +
--- 787,892 ----
itableOffsetEntry* ioe = offset_entry(size_offset_table() - 1);
guarantee(ioe->interface_klass() == NULL && ioe->offset() == 0, "terminator entry missing");
}
+ inline bool interface_method_needs_itable_index(Method* m) {
+ if (m->is_static()) return false; // e.g., Stream.empty
+ if (m->is_initializer()) return false; // <init> or <clinit>
+ // If an interface redeclares a method from java.lang.Object,
+ // it should already have a vtable index, don't touch it.
+ // e.g., CharSequence.toString (from initialize_vtable)
+ // if (m->has_vtable_index()) return false; // NO!
+ return true;
+ }
+
+ int klassItable::assign_itable_indexes_for_interface(Klass* klass) {
+ // an interface does not have an itable, but its methods need to be numbered
+ if (TraceItables) tty->print_cr("%3d: Initializing itable for interface %s", ++initialize_count,
+ klass->name()->as_C_string());
+ Array<Method*>* methods = InstanceKlass::cast(klass)->methods();
+ int nof_methods = methods->length();
+ int ime_num = 0;
+ for (int i = 0; i < nof_methods; i++) {
+ Method* m = methods->at(i);
+ if (interface_method_needs_itable_index(m)) {
+ assert(!m->is_final_method(), "no final interface methods");
+ // If m is already assigned a vtable index, do not disturb it.
+ if (!m->has_vtable_index()) {
+ assert(m->vtable_index() == Method::pending_itable_index, "set by initialize_vtable");
+ m->set_itable_index(ime_num);
+ // Progress to next itable entry
+ ime_num++;
+ }
+ }
+ }
+ assert(ime_num == method_count_for_interface(klass), "proper sizing");
+ return ime_num;
+ }
+
+ int klassItable::method_count_for_interface(Klass* interf) {
+ assert(interf->oop_is_instance(), "must be");
+ assert(interf->is_interface(), "must be");
+ Array<Method*>* methods = InstanceKlass::cast(interf)->methods();
+ int nof_methods = methods->length();
+ while (nof_methods > 0) {
+ Method* m = methods->at(nof_methods-1);
+ if (m->has_itable_index()) {
+ int length = m->itable_index() + 1;
+ #ifdef ASSERT
+ while (nof_methods = 0) {
+ m = methods->at(--nof_methods);
+ assert(!m->has_itable_index() || m->itable_index() < length, "");
+ }
+ #endif //ASSERT
+ return length; // return the rightmost itable index, plus one
+ }
+ nof_methods -= 1;
+ }
+ // no methods have itable indexes
+ return 0;
+ }
+
+
void klassItable::initialize_itable_for_interface(int method_table_offset, KlassHandle interf_h, bool checkconstraints, TRAPS) {
Array<Method*>* methods = InstanceKlass::cast(interf_h())->methods();
int nof_methods = methods->length();
HandleMark hm;
assert(nof_methods > 0, "at least one method must exist for interface to be in vtable");
Handle interface_loader (THREAD, InstanceKlass::cast(interf_h())->class_loader());
! int ime_count = method_count_for_interface(interf_h());
! for (int i = 0; i < nof_methods; i++) {
Method* m = methods->at(i);
! methodHandle target;
! if (m->has_itable_index()) {
! LinkResolver::lookup_instance_method_in_klasses(target, _klass, m->name(), m->signature(), CHECK);
}
if (target == NULL || !target->is_public() || target->is_abstract()) {
// Entry do not resolve. Leave it empty
} else {
// Entry did resolve, check loader constraints before initializing
// if checkconstraints requested
if (checkconstraints) {
Handle method_holder_loader (THREAD, target->method_holder()->class_loader());
if (method_holder_loader() != interface_loader()) {
ResourceMark rm(THREAD);
Symbol* failed_type_symbol =
! SystemDictionary::check_signature_loaders(m->signature(),
method_holder_loader,
interface_loader,
true, CHECK);
if (failed_type_symbol != NULL) {
const char* msg = "loader constraint violation in interface "
"itable initialization: when resolving method \"%s\" the class"
" loader (instance of %s) of the current class, %s, "
"and the class loader (instance of %s) for interface "
"%s have different Class objects for the type %s "
"used in the signature";
! char* sig = target()->name_and_sig_as_C_string();
const char* loader1 = SystemDictionary::loader_name(method_holder_loader());
! char* current = _klass->name()->as_C_string();
const char* loader2 = SystemDictionary::loader_name(interface_loader());
char* iface = InstanceKlass::cast(interf_h())->name()->as_C_string();
char* failed_type_name = failed_type_symbol->as_C_string();
size_t buflen = strlen(msg) + strlen(sig) + strlen(loader1) +
strlen(current) + strlen(loader2) + strlen(iface) +
*** 819,832 ****
}
}
}
// ime may have moved during GC so recalculate address
! itableOffsetEntry::method_entry(_klass(), method_table_offset)[ime_num].initialize(target_h());
}
- // Progress to next entry
- ime_num++;
}
}
// Update entry for specific Method*
void klassItable::initialize_with_method(Method* m) {
--- 898,911 ----
}
}
}
// ime may have moved during GC so recalculate address
! int ime_num = m->itable_index();
! assert(ime_num < ime_count, "oob");
! itableOffsetEntry::method_entry(_klass(), method_table_offset)[ime_num].initialize(target());
}
}
}
// Update entry for specific Method*
void klassItable::initialize_with_method(Method* m) {
*** 911,934 ****
class InterfaceVisiterClosure : public StackObj {
public:
virtual void doit(Klass* intf, int method_count) = 0;
};
! // Visit all interfaces with at-least one method (excluding <clinit>)
void visit_all_interfaces(Array<Klass*>* transitive_intf, InterfaceVisiterClosure *blk) {
// Handle array argument
for(int i = 0; i < transitive_intf->length(); i++) {
Klass* intf = transitive_intf->at(i);
assert(intf->is_interface(), "sanity check");
! // Find no. of methods excluding a <clinit>
! int method_count = InstanceKlass::cast(intf)->methods()->length();
! if (method_count > 0) {
! Method* m = InstanceKlass::cast(intf)->methods()->at(0);
! assert(m != NULL && m->is_method(), "sanity check");
! if (m->name() == vmSymbols::object_initializer_name()) {
! method_count--;
}
}
// Only count interfaces with at least one method
if (method_count > 0) {
--- 990,1015 ----
class InterfaceVisiterClosure : public StackObj {
public:
virtual void doit(Klass* intf, int method_count) = 0;
};
! // Visit all interfaces with at least one itable method
void visit_all_interfaces(Array<Klass*>* transitive_intf, InterfaceVisiterClosure *blk) {
// Handle array argument
for(int i = 0; i < transitive_intf->length(); i++) {
Klass* intf = transitive_intf->at(i);
assert(intf->is_interface(), "sanity check");
! // Find no. of itable methods
! int method_count = 0;
! // method_count = klassItable::method_count_for_interface(intf);
! Array<Method*>* methods = InstanceKlass::cast(intf)->methods();
! if (methods->length() > 0) {
! for (int i = methods->length(); --i >= 0; ) {
! if (interface_method_needs_itable_index(methods->at(i))) {
! method_count++;
! }
}
}
// Only count interfaces with at least one method
if (method_count > 0) {
*** 1022,1065 ****
assert( (oop*)(ime) == v, "wrong offset calculation (2)");
#endif
}
! // m must be a method in an interface
! int klassItable::compute_itable_index(Method* m) {
! InstanceKlass* intf = m->method_holder();
! assert(intf->is_interface(), "sanity check");
! Array<Method*>* methods = intf->methods();
! int index = 0;
! while(methods->at(index) != m) {
! index++;
! assert(index < methods->length(), "should find index for resolve_invoke");
! }
! // Adjust for <clinit>, which is left out of table if first method
! if (methods->length() > 0 && methods->at(0)->is_static_initializer()) {
! index--;
! }
! return index;
! }
!
!
! // inverse to compute_itable_index
Method* klassItable::method_for_itable_index(Klass* intf, int itable_index) {
assert(InstanceKlass::cast(intf)->is_interface(), "sanity check");
Array<Method*>* methods = InstanceKlass::cast(intf)->methods();
! int index = itable_index;
! // Adjust for <clinit>, which is left out of table if first method
! if (methods->length() > 0 && methods->at(0)->is_static_initializer()) {
! index++;
! }
!
! if (itable_index < 0 || index >= methods->length())
return NULL; // help caller defend against bad indexes
Method* m = methods->at(index);
! assert(compute_itable_index(m) == itable_index, "correct inverse");
return m;
}
void klassVtable::verify(outputStream* st, bool forced) {
--- 1103,1132 ----
assert( (oop*)(ime) == v, "wrong offset calculation (2)");
#endif
}
! // inverse to itable_index
Method* klassItable::method_for_itable_index(Klass* intf, int itable_index) {
assert(InstanceKlass::cast(intf)->is_interface(), "sanity check");
+ assert(intf->verify_itable_index(itable_index), "");
Array<Method*>* methods = InstanceKlass::cast(intf)->methods();
! if (itable_index < 0 || itable_index >= method_count_for_interface(intf))
return NULL; // help caller defend against bad indexes
+ int index = itable_index;
Method* m = methods->at(index);
! int index2 = -1;
! while (!m->has_itable_index() ||
! (index2 = m->itable_index()) != itable_index) {
! assert(index2 < itable_index, "monotonic");
! if (++index == methods->length())
! return NULL;
! m = methods->at(index);
! }
! assert(m->itable_index() == itable_index, "correct inverse");
return m;
}
void klassVtable::verify(outputStream* st, bool forced) {
src/share/vm/oops/klassVtable.cpp
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File