8256365: Clean up vtable initialization code
Reviewed-by: eosterlund, dholmes
This commit is contained in:
parent
4e5116c46e
commit
fa8dce4f77
@ -2972,27 +2972,6 @@ bool InstanceKlass::is_same_class_package(oop other_class_loader,
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true iff super_method can be overridden by a method in targetclassname
|
||||
// See JLS 3rd edition 8.4.6.1
|
||||
// Assumes name-signature match
|
||||
// "this" is InstanceKlass of super_method which must exist
|
||||
// note that the InstanceKlass of the method in the targetclassname has not always been created yet
|
||||
bool InstanceKlass::is_override(const methodHandle& super_method, Handle targetclassloader, Symbol* targetclassname, TRAPS) {
|
||||
// Private methods can not be overridden
|
||||
if (super_method->is_private()) {
|
||||
return false;
|
||||
}
|
||||
// If super method is accessible, then override
|
||||
if ((super_method->is_protected()) ||
|
||||
(super_method->is_public())) {
|
||||
return true;
|
||||
}
|
||||
// Package-private methods are not inherited outside of package
|
||||
assert(super_method->is_package_private(), "must be package private");
|
||||
return(is_same_class_package(targetclassloader(), targetclassname));
|
||||
}
|
||||
|
||||
|
||||
static bool is_prohibited_package_slow(Symbol* class_name) {
|
||||
// Caller has ResourceMark
|
||||
int length;
|
||||
|
@ -512,9 +512,6 @@ public:
|
||||
enclosing_method_attribute_size = 2
|
||||
};
|
||||
|
||||
// method override check
|
||||
bool is_override(const methodHandle& super_method, Handle targetclassloader, Symbol* targetclassname, TRAPS);
|
||||
|
||||
// package
|
||||
PackageEntry* package() const { return _package_entry; }
|
||||
ModuleEntry* module() const;
|
||||
|
@ -80,11 +80,10 @@ void klassVtable::compute_vtable_size_and_num_mirandas(
|
||||
// go thru each method in the methods table to see if it needs a new entry
|
||||
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));
|
||||
Method* method = methods->at(i);
|
||||
|
||||
if (needs_new_vtable_entry(mh, super, classloader, classname, class_flags, major_version, THREAD)) {
|
||||
assert(!methods->at(i)->is_private(), "private methods should not need a vtable entry");
|
||||
if (needs_new_vtable_entry(method, super, classloader, classname, class_flags, major_version)) {
|
||||
assert(!method->is_private(), "private methods should not need a vtable entry");
|
||||
vtable_length += vtableEntry::size(); // we need a new entry
|
||||
}
|
||||
}
|
||||
@ -199,15 +198,13 @@ void klassVtable::initialize_vtable(bool checkconstraints, TRAPS) {
|
||||
// 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, -1, checkconstraints, CHECK);
|
||||
bool needs_new_entry = update_inherited_vtable(mh, super_vtable_len, -1, checkconstraints, CHECK);
|
||||
|
||||
if (needs_new_entry) {
|
||||
put_method_at(mh(), initialized);
|
||||
mh()->set_vtable_index(initialized); // set primary vtable index
|
||||
mh->set_vtable_index(initialized); // set primary vtable index
|
||||
initialized++;
|
||||
}
|
||||
}
|
||||
@ -225,11 +222,9 @@ void klassVtable::initialize_vtable(bool checkconstraints, TRAPS) {
|
||||
assert(def_vtable_indices->length() == len, "reinit vtable len?");
|
||||
}
|
||||
for (int i = 0; i < len; i++) {
|
||||
HandleMark hm(THREAD);
|
||||
assert(default_methods->at(i)->is_method(), "must be a Method*");
|
||||
methodHandle mh(THREAD, default_methods->at(i));
|
||||
assert(!mh->is_private(), "private interface method in the default method list");
|
||||
bool needs_new_entry = update_inherited_vtable(ik(), mh, super_vtable_len, i, checkconstraints, CHECK);
|
||||
bool needs_new_entry = update_inherited_vtable(mh, super_vtable_len, i, checkconstraints, CHECK);
|
||||
|
||||
// needs new entry
|
||||
if (needs_new_entry) {
|
||||
@ -272,6 +267,25 @@ void klassVtable::initialize_vtable(bool checkconstraints, TRAPS) {
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true iff super_method can be overridden by a method in targetclassname
|
||||
// See JLS 3rd edition 8.4.6.1
|
||||
// Assumes name-signature match
|
||||
// Note that the InstanceKlass of the method in the targetclassname has not always been created yet
|
||||
static bool can_be_overridden(Method* super_method, Handle targetclassloader, Symbol* targetclassname) {
|
||||
// Private methods can not be overridden
|
||||
assert(!super_method->is_private(), "shouldn't call with a private method");
|
||||
|
||||
// If super method is accessible, then override
|
||||
if ((super_method->is_protected()) ||
|
||||
(super_method->is_public())) {
|
||||
return true;
|
||||
}
|
||||
// Package-private methods are not inherited outside of package
|
||||
assert(super_method->is_package_private(), "must be package private");
|
||||
return(super_method->method_holder()->is_same_class_package(targetclassloader(), targetclassname));
|
||||
}
|
||||
|
||||
|
||||
// Called for cases where a method does not override its superclass' vtable entry
|
||||
// For bytecodes not produced by javac together it is possible that a method does not override
|
||||
// the superclass's method, but might indirectly override a super-super class's vtable entry
|
||||
@ -287,30 +301,31 @@ void klassVtable::initialize_vtable(bool checkconstraints, TRAPS) {
|
||||
// Therefore: all package private methods need their own vtable entries for
|
||||
// them to be the root of an inheritance overriding decision
|
||||
// Package private methods may also override other vtable entries
|
||||
InstanceKlass* klassVtable::find_transitive_override(InstanceKlass* initialsuper, const methodHandle& target_method,
|
||||
int vtable_index, Handle target_loader, Symbol* target_classname, Thread * THREAD) {
|
||||
InstanceKlass* klassVtable::find_transitive_override(InstanceKlass* initialsuper,
|
||||
const methodHandle& target_method,
|
||||
int vtable_index,
|
||||
Handle target_loader,
|
||||
Symbol* target_classname) {
|
||||
|
||||
InstanceKlass* superk = initialsuper;
|
||||
while (superk != NULL && superk->super() != NULL) {
|
||||
klassVtable ssVtable = (superk->super())->vtable();
|
||||
if (vtable_index < ssVtable.length()) {
|
||||
Method* super_method = ssVtable.method_at(vtable_index);
|
||||
// get the class holding the matching method
|
||||
// make sure you use that class for is_override
|
||||
InstanceKlass* supermethodholder = super_method->method_holder();
|
||||
#ifndef PRODUCT
|
||||
Symbol* name= target_method()->name();
|
||||
Symbol* signature = target_method()->signature();
|
||||
assert(super_method->name() == name && super_method->signature() == signature, "vtable entry name/sig mismatch");
|
||||
#endif
|
||||
|
||||
if (supermethodholder->is_override(methodHandle(THREAD, super_method), target_loader, target_classname, THREAD)) {
|
||||
if (can_be_overridden(super_method, target_loader, target_classname)) {
|
||||
if (log_develop_is_enabled(Trace, vtables)) {
|
||||
ResourceMark rm(THREAD);
|
||||
ResourceMark rm;
|
||||
LogTarget(Trace, vtables) lt;
|
||||
LogStream ls(lt);
|
||||
char* sig = target_method()->name_and_sig_as_C_string();
|
||||
ls.print("transitive overriding superclass %s with %s index %d, original flags: ",
|
||||
supermethodholder->internal_name(),
|
||||
super_method->method_holder()->internal_name(),
|
||||
sig, vtable_index);
|
||||
super_method->print_linkage_flags(&ls);
|
||||
ls.print("overriders flags: ");
|
||||
@ -360,12 +375,13 @@ static void log_vtables(int i, bool overrides, const methodHandle& target_method
|
||||
// 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, const methodHandle& target_method,
|
||||
bool klassVtable::update_inherited_vtable(const methodHandle& target_method,
|
||||
int super_vtable_len, int default_index,
|
||||
bool checkconstraints, TRAPS) {
|
||||
ResourceMark rm(THREAD);
|
||||
bool allocate_new = true;
|
||||
assert(klass->is_instance_klass(), "must be InstanceKlass");
|
||||
|
||||
InstanceKlass* klass = ik();
|
||||
|
||||
Array<int>* def_vtable_indices = NULL;
|
||||
bool is_default = false;
|
||||
@ -378,19 +394,19 @@ bool klassVtable::update_inherited_vtable(InstanceKlass* klass, const methodHand
|
||||
if (default_index >= 0 ) {
|
||||
is_default = true;
|
||||
def_vtable_indices = klass->default_vtable_indices();
|
||||
assert(!target_method()->is_private(), "private interface method flagged as default");
|
||||
assert(!target_method->is_private(), "private interface method flagged as default");
|
||||
assert(def_vtable_indices != NULL, "def vtable alloc?");
|
||||
assert(default_index <= def_vtable_indices->length(), "def vtable len?");
|
||||
} else {
|
||||
assert(klass == target_method()->method_holder(), "caller resp.");
|
||||
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);
|
||||
target_method->set_vtable_index(Method::nonvirtual_vtable_index);
|
||||
}
|
||||
|
||||
// Private, static and <init> methods are never in
|
||||
if (target_method()->is_private() || target_method()->is_static() ||
|
||||
(target_method()->name()->fast_compare(vmSymbols::object_initializer_name()) == 0)) {
|
||||
if (target_method->is_private() || target_method->is_static() ||
|
||||
(target_method->name()->fast_compare(vmSymbols::object_initializer_name()) == 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -410,8 +426,8 @@ bool klassVtable::update_inherited_vtable(InstanceKlass* klass, const methodHand
|
||||
// valid itable index, if so, don't change it.
|
||||
// Overpass methods in an interface will be assigned an itable index later
|
||||
// by an inheriting class.
|
||||
if ((!is_default || !target_method()->has_itable_index())) {
|
||||
target_method()->set_vtable_index(Method::pending_itable_index);
|
||||
if ((!is_default || !target_method->has_itable_index())) {
|
||||
target_method->set_vtable_index(Method::pending_itable_index);
|
||||
}
|
||||
}
|
||||
|
||||
@ -426,14 +442,16 @@ bool klassVtable::update_inherited_vtable(InstanceKlass* klass, const methodHand
|
||||
// which can block for gc, once we are in this loop, use handles
|
||||
// For classfiles built with >= jdk7, we now look for transitive overrides
|
||||
|
||||
Symbol* name = target_method()->name();
|
||||
Symbol* signature = target_method()->signature();
|
||||
Symbol* name = target_method->name();
|
||||
Symbol* signature = target_method->signature();
|
||||
|
||||
Klass* target_klass = target_method()->method_holder();
|
||||
Klass* target_klass = target_method->method_holder();
|
||||
assert(target_klass != NULL, "impossible");
|
||||
if (target_klass == NULL) {
|
||||
target_klass = _klass;
|
||||
}
|
||||
|
||||
HandleMark hm(THREAD);
|
||||
Handle target_loader(THREAD, target_klass->class_loader());
|
||||
|
||||
Symbol* target_classname = target_klass->name();
|
||||
@ -452,7 +470,7 @@ bool klassVtable::update_inherited_vtable(InstanceKlass* klass, const methodHand
|
||||
// This is safe because the method at this slot should never get invoked.
|
||||
// (TBD: put in a method to throw NoSuchMethodError if this slot is ever used.)
|
||||
if (super_method->name() == name && super_method->signature() == signature &&
|
||||
(!_klass->is_interface() ||
|
||||
(!klass->is_interface() ||
|
||||
!SystemDictionary::is_nonpublic_Object_method(super_method))) {
|
||||
|
||||
// get super_klass for method_holder for the found method
|
||||
@ -463,23 +481,22 @@ bool klassVtable::update_inherited_vtable(InstanceKlass* klass, const methodHand
|
||||
|
||||
// private methods are also never overridden
|
||||
if (!super_method->is_private() &&
|
||||
(is_default
|
||||
|| ((super_klass->is_override(methodHandle(THREAD, super_method), target_loader, target_classname, THREAD))
|
||||
|| ((klass->major_version() >= VTABLE_TRANSITIVE_OVERRIDE_VERSION)
|
||||
&& ((super_klass = find_transitive_override(super_klass,
|
||||
target_method, i, target_loader,
|
||||
target_classname, THREAD))
|
||||
!= (InstanceKlass*)NULL)))))
|
||||
{
|
||||
(is_default ||
|
||||
can_be_overridden(super_method, target_loader, target_classname) ||
|
||||
(klass->major_version() >= VTABLE_TRANSITIVE_OVERRIDE_VERSION &&
|
||||
(super_klass = find_transitive_override(super_klass,
|
||||
target_method, i, target_loader,
|
||||
target_classname)) != NULL))) {
|
||||
|
||||
// Package private methods always need a new entry to root their own
|
||||
// overriding. They may also override other methods.
|
||||
if (!target_method()->is_package_private()) {
|
||||
if (!target_method->is_package_private()) {
|
||||
allocate_new = false;
|
||||
}
|
||||
|
||||
// Do not check loader constraints for overpass methods because overpass
|
||||
// methods are created by the jvm to throw exceptions.
|
||||
if (checkconstraints && !target_method()->is_overpass()) {
|
||||
if (checkconstraints && !target_method->is_overpass()) {
|
||||
// Override vtable entry if passes loader constraint check
|
||||
// if loader constraint checking requested
|
||||
// No need to visit his super, since he and his super
|
||||
@ -498,7 +515,7 @@ bool klassVtable::update_inherited_vtable(InstanceKlass* klass, const methodHand
|
||||
stringStream ss;
|
||||
ss.print("loader constraint violation for class %s: when selecting "
|
||||
"overriding method '", klass->external_name());
|
||||
target_method()->print_external_name(&ss),
|
||||
target_method->print_external_name(&ss),
|
||||
ss.print("' the class loader %s of the "
|
||||
"selected method's type %s, and the class loader %s for its super "
|
||||
"type %s have different Class objects for the type %s used in the signature (%s; %s)",
|
||||
@ -517,7 +534,7 @@ bool klassVtable::update_inherited_vtable(InstanceKlass* klass, const methodHand
|
||||
put_method_at(target_method(), i);
|
||||
overrides = true;
|
||||
if (!is_default) {
|
||||
target_method()->set_vtable_index(i);
|
||||
target_method->set_vtable_index(i);
|
||||
} else {
|
||||
if (def_vtable_indices != NULL) {
|
||||
if (is_preinitialized_vtable()) {
|
||||
@ -544,6 +561,7 @@ bool klassVtable::update_inherited_vtable(InstanceKlass* klass, const methodHand
|
||||
|
||||
void klassVtable::put_method_at(Method* m, int index) {
|
||||
assert(!m->is_private(), "private methods should not be in vtable");
|
||||
JVMTI_ONLY(assert(!m->is_old() || ik()->is_being_redefined(), "old methods should not be in vtable"));
|
||||
if (is_preinitialized_vtable()) {
|
||||
// At runtime initialize_vtable is rerun as part of link_class_impl()
|
||||
// for shared class loaded by the non-boot loader to obtain the loader
|
||||
@ -576,13 +594,12 @@ void klassVtable::put_method_at(Method* m, int index) {
|
||||
// superclass has been loaded.
|
||||
// However, the vtable entries are filled in at link time, and therefore
|
||||
// the superclass' vtable may not yet have been filled in.
|
||||
bool klassVtable::needs_new_vtable_entry(const methodHandle& target_method,
|
||||
bool klassVtable::needs_new_vtable_entry(Method* target_method,
|
||||
const Klass* super,
|
||||
Handle classloader,
|
||||
Symbol* classname,
|
||||
AccessFlags class_flags,
|
||||
u2 major_version,
|
||||
TRAPS) {
|
||||
u2 major_version) {
|
||||
if (class_flags.is_interface()) {
|
||||
// Interfaces do not use vtables, except for java.lang.Object methods,
|
||||
// so there is no point to assigning
|
||||
@ -595,11 +612,11 @@ bool klassVtable::needs_new_vtable_entry(const methodHandle& 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_private()) ||
|
||||
(target_method->is_private()) ||
|
||||
// private methods don't need to be in vtable
|
||||
(target_method()->is_static()) ||
|
||||
(target_method->is_static()) ||
|
||||
// static methods don't need to be in vtable
|
||||
(target_method()->name()->fast_compare(vmSymbols::object_initializer_name()) == 0)
|
||||
(target_method->name()->fast_compare(vmSymbols::object_initializer_name()) == 0)
|
||||
// <init> is never called dynamically-bound
|
||||
) {
|
||||
return false;
|
||||
@ -607,10 +624,10 @@ bool klassVtable::needs_new_vtable_entry(const methodHandle& target_method,
|
||||
|
||||
// Concrete interface methods do not need new entries, they override
|
||||
// abstract method entries using default inheritance rules
|
||||
if (target_method()->method_holder() != NULL &&
|
||||
target_method()->method_holder()->is_interface() &&
|
||||
!target_method()->is_abstract()) {
|
||||
assert(target_method()->is_default_method(),
|
||||
if (target_method->method_holder() != NULL &&
|
||||
target_method->method_holder()->is_interface() &&
|
||||
!target_method->is_abstract()) {
|
||||
assert(target_method->is_default_method(),
|
||||
"unexpected interface method type");
|
||||
return false;
|
||||
}
|
||||
@ -622,15 +639,14 @@ bool klassVtable::needs_new_vtable_entry(const methodHandle& target_method,
|
||||
|
||||
// Package private methods always need a new entry to root their own
|
||||
// overriding. This allows transitive overriding to work.
|
||||
if (target_method()->is_package_private()) {
|
||||
if (target_method->is_package_private()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// search through the super class hierarchy to see if we need
|
||||
// a new entry
|
||||
ResourceMark rm(THREAD);
|
||||
Symbol* name = target_method()->name();
|
||||
Symbol* signature = target_method()->signature();
|
||||
Symbol* name = target_method->name();
|
||||
Symbol* signature = target_method->signature();
|
||||
const Klass* k = super;
|
||||
Method* super_method = NULL;
|
||||
InstanceKlass *holder = NULL;
|
||||
@ -643,7 +659,6 @@ bool klassVtable::needs_new_vtable_entry(const methodHandle& target_method,
|
||||
break; // we still have to search for a matching miranda method
|
||||
}
|
||||
// get the class holding the matching method
|
||||
// make sure you use that class for is_override
|
||||
InstanceKlass* superk = super_method->method_holder();
|
||||
// we want only instance method matches
|
||||
// ignore private methods found via lookup_method since they do not participate in overriding,
|
||||
@ -651,11 +666,11 @@ bool klassVtable::needs_new_vtable_entry(const methodHandle& target_method,
|
||||
// ignore private, c.m pub does override a.m pub
|
||||
// For classes that were not javac'd together, we also do transitive overriding around
|
||||
// methods that have less accessibility
|
||||
if ((!super_method->is_static()) &&
|
||||
(!super_method->is_private())) {
|
||||
if (superk->is_override(methodHandle(THREAD, super_method), classloader, classname, THREAD)) {
|
||||
if (!super_method->is_static() &&
|
||||
!super_method->is_private()) {
|
||||
if (can_be_overridden(super_method, classloader, classname)) {
|
||||
return false;
|
||||
// else keep looking for transitive overrides
|
||||
// else keep looking for transitive overrides
|
||||
}
|
||||
// If we get here then one of the super classes has a package private method
|
||||
// that will not get overridden because it is in a different package. But,
|
||||
@ -718,13 +733,12 @@ int klassVtable::index_of_miranda(Symbol* name, Symbol* signature) {
|
||||
// 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);
|
||||
InstanceKlass* holder = m->method_holder();
|
||||
|
||||
// miranda methods are public abstract instance interface methods in a class's vtable
|
||||
if (mhk->is_interface()) {
|
||||
if (holder->is_interface()) {
|
||||
assert(m->is_public(), "should be public");
|
||||
assert(ik()->implements_interface(method_holder) , "this class should implement the interface");
|
||||
assert(ik()->implements_interface(holder) , "this class should implement the interface");
|
||||
if (is_miranda(m, ik()->methods(), ik()->default_methods(), ik()->super(), klass()->is_interface())) {
|
||||
return true;
|
||||
}
|
||||
@ -888,7 +902,7 @@ void klassVtable::get_mirandas(GrowableArray<Method*>* new_mirandas,
|
||||
// iterate thru the local interfaces looking for a miranda
|
||||
int num_local_ifs = local_interfaces->length();
|
||||
for (int i = 0; i < num_local_ifs; i++) {
|
||||
InstanceKlass *ik = InstanceKlass::cast(local_interfaces->at(i));
|
||||
InstanceKlass *ik = local_interfaces->at(i);
|
||||
add_new_mirandas_to_lists(new_mirandas, all_mirandas,
|
||||
ik->methods(), class_methods,
|
||||
default_methods, super, is_interface);
|
||||
@ -1107,9 +1121,9 @@ void klassItable::initialize_itable(bool checkconstraints, TRAPS) {
|
||||
for(i = 0; i < num_interfaces; i++) {
|
||||
itableOffsetEntry* ioe = offset_entry(i);
|
||||
HandleMark hm(THREAD);
|
||||
Klass* interf = ioe->interface_klass();
|
||||
InstanceKlass* interf = ioe->interface_klass();
|
||||
assert(interf != NULL && ioe->offset() != 0, "bad offset entry in itable");
|
||||
initialize_itable_for_interface(ioe->offset(), InstanceKlass::cast(interf), checkconstraints, CHECK);
|
||||
initialize_itable_for_interface(ioe->offset(), interf, checkconstraints, CHECK);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -109,17 +109,20 @@ class klassVtable {
|
||||
void copy_vtable_to(vtableEntry* start);
|
||||
int initialize_from_super(Klass* super);
|
||||
void put_method_at(Method* m, int index);
|
||||
static bool needs_new_vtable_entry(const methodHandle& m,
|
||||
static bool needs_new_vtable_entry(Method* m,
|
||||
const Klass* super,
|
||||
Handle classloader,
|
||||
Symbol* classname,
|
||||
AccessFlags access_flags,
|
||||
u2 major_version,
|
||||
TRAPS);
|
||||
u2 major_version);
|
||||
|
||||
bool update_inherited_vtable(InstanceKlass* klass, const methodHandle& target_method, int super_vtable_len, int default_index, bool checkconstraints, TRAPS);
|
||||
InstanceKlass* find_transitive_override(InstanceKlass* initialsuper, const methodHandle& target_method, int vtable_index,
|
||||
Handle target_loader, Symbol* target_classname, Thread* THREAD);
|
||||
bool update_inherited_vtable(const methodHandle& target_method,
|
||||
int super_vtable_len,
|
||||
int default_index,
|
||||
bool checkconstraints, TRAPS);
|
||||
InstanceKlass* find_transitive_override(InstanceKlass* initialsuper,
|
||||
const methodHandle& target_method, int vtable_index,
|
||||
Handle target_loader, Symbol* target_classname);
|
||||
|
||||
// support for miranda methods
|
||||
bool is_miranda_entry_at(int i);
|
||||
|
Loading…
Reference in New Issue
Block a user