mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
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:
parent
2b82651ec0
commit
088ded71f9
18 changed files with 662 additions and 248 deletions
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue