8009130: Lambda: Fix access controls, loader constraints

New default methods list with inherited superinterface methods

Reviewed-by: minqi, sspitsyn, coleenp
This commit is contained in:
Karen Kinnear 2013-10-07 12:20:28 -04:00
parent 2b82651ec0
commit 088ded71f9
18 changed files with 662 additions and 248 deletions

View file

@ -238,6 +238,13 @@ void InstanceKlass::copy_method_ordering(intArray* m, TRAPS) {
}
}
// create a new array of vtable_indices for default methods
Array<int>* InstanceKlass::create_new_default_vtable_indices(int len, TRAPS) {
Array<int>* vtable_indices = MetadataFactory::new_array<int>(class_loader_data(), len, CHECK_NULL);
assert(default_vtable_indices() == NULL, "only create once");
set_default_vtable_indices(vtable_indices);
return vtable_indices;
}
InstanceKlass::InstanceKlass(int vtable_len,
int itable_len,
@ -263,6 +270,8 @@ InstanceKlass::InstanceKlass(int vtable_len,
set_array_klasses(NULL);
set_methods(NULL);
set_method_ordering(NULL);
set_default_methods(NULL);
set_default_vtable_indices(NULL);
set_local_interfaces(NULL);
set_transitive_interfaces(NULL);
init_implementor();
@ -376,6 +385,21 @@ void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) {
}
set_method_ordering(NULL);
// default methods can be empty
if (default_methods() != NULL &&
default_methods() != Universe::the_empty_method_array()) {
MetadataFactory::free_array<Method*>(loader_data, default_methods());
}
// Do NOT deallocate the default methods, they are owned by superinterfaces.
set_default_methods(NULL);
// default methods vtable indices can be empty
if (default_vtable_indices() != NULL) {
MetadataFactory::free_array<int>(loader_data, default_vtable_indices());
}
set_default_vtable_indices(NULL);
// This array is in Klass, but remove it with the InstanceKlass since
// this place would be the only caller and it can share memory with transitive
// interfaces.
@ -1354,32 +1378,44 @@ static int binary_search(Array<Method*>* methods, Symbol* name) {
return -1;
}
// find_method looks up the name/signature in the local methods array
Method* InstanceKlass::find_method(Symbol* name, Symbol* signature) const {
return InstanceKlass::find_method(methods(), name, signature);
}
// find_method looks up the name/signature in the local methods array
Method* InstanceKlass::find_method(
Array<Method*>* methods, Symbol* name, Symbol* signature) {
int hit = find_method_index(methods, name, signature);
return hit >= 0 ? methods->at(hit): NULL;
}
// Used directly for default_methods to find the index into the
// default_vtable_indices, and indirectly by find_method
// find_method_index looks in the local methods array to return the index
// of the matching name/signature
int InstanceKlass::find_method_index(
Array<Method*>* methods, Symbol* name, Symbol* signature) {
int hit = binary_search(methods, name);
if (hit != -1) {
Method* m = methods->at(hit);
// Do linear search to find matching signature. First, quick check
// for common case
if (m->signature() == signature) return m;
if (m->signature() == signature) return hit;
// search downwards through overloaded methods
int i;
for (i = hit - 1; i >= 0; --i) {
Method* m = methods->at(i);
assert(m->is_method(), "must be method");
if (m->name() != name) break;
if (m->signature() == signature) return m;
if (m->signature() == signature) return i;
}
// search upwards
for (i = hit + 1; i < methods->length(); ++i) {
Method* m = methods->at(i);
assert(m->is_method(), "must be method");
if (m->name() != name) break;
if (m->signature() == signature) return m;
if (m->signature() == signature) return i;
}
// not found
#ifdef ASSERT
@ -1387,9 +1423,8 @@ Method* InstanceKlass::find_method(
assert(index == -1, err_msg("binary search should have found entry %d", index));
#endif
}
return NULL;
return -1;
}
int InstanceKlass::find_method_by_name(Symbol* name, int* end) {
return find_method_by_name(methods(), name, end);
}
@ -1408,6 +1443,7 @@ int InstanceKlass::find_method_by_name(
return -1;
}
// lookup_method searches both the local methods array and all superclasses methods arrays
Method* InstanceKlass::uncached_lookup_method(Symbol* name, Symbol* signature) const {
Klass* klass = const_cast<InstanceKlass*>(this);
while (klass != NULL) {
@ -1418,6 +1454,21 @@ Method* InstanceKlass::uncached_lookup_method(Symbol* name, Symbol* signature) c
return NULL;
}
// lookup a method in the default methods list then in all transitive interfaces
// Do NOT return private or static methods
Method* InstanceKlass::lookup_method_in_ordered_interfaces(Symbol* name,
Symbol* signature) const {
Method* m;
if (default_methods() != NULL) {
m = find_method(default_methods(), name, signature);
}
// Look up interfaces
if (m == NULL) {
m = lookup_method_in_all_interfaces(name, signature);
}
return m;
}
// lookup a method in all the interfaces that this class implements
// Do NOT return private or static methods, new in JDK8 which are not externally visible
// They should only be found in the initial InterfaceMethodRef
@ -2548,6 +2599,42 @@ Method* InstanceKlass::method_at_itable(Klass* holder, int index, TRAPS) {
return m;
}
#if INCLUDE_JVMTI
// update default_methods for redefineclasses for methods that are
// not yet in the vtable due to concurrent subclass define and superinterface
// redefinition
// Note: those in the vtable, should have been updated via adjust_method_entries
void InstanceKlass::adjust_default_methods(Method** old_methods, Method** new_methods,
int methods_length, bool* trace_name_printed) {
// search the default_methods for uses of either obsolete or EMCP methods
if (default_methods() != NULL) {
for (int j = 0; j < methods_length; j++) {
Method* old_method = old_methods[j];
Method* new_method = new_methods[j];
for (int index = 0; index < default_methods()->length(); index ++) {
if (default_methods()->at(index) == old_method) {
default_methods()->at_put(index, new_method);
if (RC_TRACE_IN_RANGE(0x00100000, 0x00400000)) {
if (!(*trace_name_printed)) {
// RC_TRACE_MESG macro has an embedded ResourceMark
RC_TRACE_MESG(("adjust: klassname=%s default methods from name=%s",
external_name(),
old_method->method_holder()->external_name()));
*trace_name_printed = true;
}
RC_TRACE(0x00100000, ("default method update: %s(%s) ",
new_method->name()->as_C_string(),
new_method->signature()->as_C_string()));
}
}
}
}
}
}
#endif // INCLUDE_JVMTI
// On-stack replacement stuff
void InstanceKlass::add_osr_nmethod(nmethod* n) {
// only one compilation can be active
@ -2742,11 +2829,21 @@ void InstanceKlass::print_on(outputStream* st) const {
st->print(BULLET"methods: "); methods()->print_value_on(st); st->cr();
if (Verbose || WizardMode) {
Array<Method*>* method_array = methods();
for(int i = 0; i < method_array->length(); i++) {
for (int i = 0; i < method_array->length(); i++) {
st->print("%d : ", i); method_array->at(i)->print_value(); st->cr();
}
}
st->print(BULLET"method ordering: "); method_ordering()->print_value_on(st); st->cr();
st->print(BULLET"method ordering: "); method_ordering()->print_value_on(st); st->cr();
st->print(BULLET"default_methods: "); default_methods()->print_value_on(st); st->cr();
if (Verbose && default_methods() != NULL) {
Array<Method*>* method_array = default_methods();
for (int i = 0; i < method_array->length(); i++) {
st->print("%d : ", i); method_array->at(i)->print_value(); st->cr();
}
}
if (default_vtable_indices() != NULL) {
st->print(BULLET"default vtable indices: "); default_vtable_indices()->print_value_on(st); st->cr();
}
st->print(BULLET"local interfaces: "); local_interfaces()->print_value_on(st); st->cr();
st->print(BULLET"trans. interfaces: "); transitive_interfaces()->print_value_on(st); st->cr();
st->print(BULLET"constants: "); constants()->print_value_on(st); st->cr();
@ -3099,6 +3196,19 @@ void InstanceKlass::verify_on(outputStream* st, bool check_dictionary) {
}
}
// Verify default methods
if (default_methods() != NULL) {
Array<Method*>* methods = this->default_methods();
for (int j = 0; j < methods->length(); j++) {
guarantee(methods->at(j)->is_method(), "non-method in methods array");
}
for (int j = 0; j < methods->length() - 1; j++) {
Method* m1 = methods->at(j);
Method* m2 = methods->at(j + 1);
guarantee(m1->name()->fast_compare(m2->name()) <= 0, "methods not sorted correctly");
}
}
// Verify JNI static field identifiers
if (jni_ids() != NULL) {
jni_ids()->verify(this);