src/share/vm/oops/klassVtable.cpp
Print this page
@@ -58,11 +58,11 @@
// 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, const Klass* super,
- Array<Method*>* methods, AccessFlags class_flags,
+ Array<Method*>* methods, AccessFlags class_flags, u2 major_version,
Handle classloader, Symbol* classname, Array<Klass*>* local_interfaces,
TRAPS) {
NoSafepointVerifier nsv;
// set up default result values
@@ -75,11 +75,11 @@
int len = methods->length();
for (int i = 0; i < len; i++) {
assert(methods->at(i)->is_method(), "must be a Method*");
methodHandle mh(THREAD, methods->at(i));
- if (needs_new_vtable_entry(mh, super, classloader, classname, class_flags, THREAD)) {
+ if (needs_new_vtable_entry(mh, super, classloader, classname, class_flags, major_version, THREAD)) {
vtable_length += vtableEntry::size(); // we need a new entry
}
}
GrowableArray<Method*> new_mirandas(20);
@@ -254,14 +254,19 @@
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.
+ // calculation, for classfile versions for which we do not do transitive override
+ // calculations.
+ if (ik()->major_version() >= VTABLE_TRANSITIVE_OVERRIDE_VERSION) {
+ assert(initialized == _length, "vtable initialization failed");
+ } else {
assert(initialized <= _length, "vtable initialization failed");
for(;initialized < _length; initialized++) {
- put_method_at(NULL, initialized);
+ table()[initialized].clear();
+ }
}
NOT_PRODUCT(verify(tty, true));
}
}
@@ -296,13 +301,13 @@
if (supersuperklass->is_override(super_method, target_loader, target_classname, THREAD)) {
if (log_develop_is_enabled(Trace, vtables)) {
ResourceMark rm(THREAD);
outputStream* logst = Log(vtables)::trace_stream();
char* sig = target_method()->name_and_sig_as_C_string();
- logst->print("transitive overriding superclass %s with %s::%s index %d, original flags: ",
+ logst->print("transitive overriding superclass %s with %s index %d, original flags: ",
supersuperklass->internal_name(),
- _klass->internal_name(), sig, vtable_index);
+ sig, vtable_index);
super_method->print_linkage_flags(logst);
logst->print("overriders flags: ");
target_method->print_linkage_flags(logst);
logst->cr();
}
@@ -328,15 +333,15 @@
if (log_develop_is_enabled(Trace, vtables)) {
ResourceMark rm(thread);
outputStream* logst = Log(vtables)::trace_stream();
char* sig = target_method()->name_and_sig_as_C_string();
if (overrides) {
- logst->print("overriding with %s::%s index %d, original flags: ",
- target_klass->internal_name(), sig, i);
+ logst->print("overriding with %s index %d, original flags: ",
+ sig, i);
} else {
- logst->print("NOT overriding with %s::%s index %d, original flags: ",
- target_klass->internal_name(), sig, i);
+ logst->print("NOT overriding with %s index %d, original flags: ",
+ sig, i);
}
super_method->print_linkage_flags(logst);
logst->print("overriders flags: ");
target_method->print_linkage_flags(logst);
logst->cr();
@@ -564,10 +569,11 @@
bool klassVtable::needs_new_vtable_entry(methodHandle target_method,
const Klass* super,
Handle classloader,
Symbol* classname,
AccessFlags class_flags,
+ u2 major_version,
TRAPS) {
if (class_flags.is_interface()) {
// Interfaces do not use vtables, except for java.lang.Object methods,
// so there is no point to assigning
// a vtable index to any of their local methods. If we refrain from doing this,
@@ -644,12 +650,16 @@
return false;
// else keep looking for transitive overrides
}
}
- // Start with lookup result and continue to search up
+ // Start with lookup result and continue to search up, for versions supporting transitive override
+ if (major_version >= VTABLE_TRANSITIVE_OVERRIDE_VERSION) {
k = superk->super(); // haven't found an override match yet; continue to look
+ } else {
+ break;
+ }
}
// if the target method is public or protected it may have a matching
// miranda method in the super, whose entry it should re-use.
// Actually, to handle cases that javac would not generate, we need
@@ -1498,19 +1508,25 @@
}
#endif
void vtableEntry::verify(klassVtable* vt, outputStream* st) {
NOT_PRODUCT(FlagSetting fs(IgnoreLockingAssertions, true));
+ KlassHandle vtklass_h = vt->klass();
+ Klass* vtklass = vtklass_h();
+ if (InstanceKlass::cast(vtklass)->major_version() >= klassVtable::VTABLE_TRANSITIVE_OVERRIDE_VERSION) {
assert(method() != NULL, "must have set method");
+ }
+ if (method() != NULL) {
method()->verify();
// we sub_type, because it could be a miranda method
- if (!vt->klass()->is_subtype_of(method()->method_holder())) {
+ if (!vtklass_h->is_subtype_of(method()->method_holder())) {
#ifndef PRODUCT
print();
#endif
fatal("vtableEntry " PTR_FORMAT ": method is from subclass", p2i(this));
}
+ }
}
#ifndef PRODUCT
void vtableEntry::print() {