# HG changeset patch # User lfoltan # Date 1422024873 18000 # Node ID f7339cba0a6ad6301e6b9d880fa621e68f02ab86 # Parent 544fb99e00801a903f1aec9fab82021ba5d97984 8067480: Crash in klassItable::initialize_itable_for_interface when running vm.runtime.defmeth.StaticMethodsTest. Summary: A static method should be skipped in entirety by find_instance_method(), searching should continue to find an overpass method of the same name and signature if present. Reviewed-by: acorn, hseigel diff -r 544fb99e0080 -r f7339cba0a6a hotspot/src/share/vm/classfile/verifier.cpp --- a/hotspot/src/share/vm/classfile/verifier.cpp Tue Jan 20 13:56:57 2015 +0100 +++ b/hotspot/src/share/vm/classfile/verifier.cpp Fri Jan 23 09:54:33 2015 -0500 @@ -1950,7 +1950,7 @@ InstanceKlass* target_instance = InstanceKlass::cast(target_class); fieldDescriptor fd; if (is_method) { - Method* m = target_instance->uncached_lookup_method(field_name, field_sig, Klass::normal); + Method* m = target_instance->uncached_lookup_method(field_name, field_sig, Klass::find_overpass); if (m != NULL && m->is_protected()) { if (!this_class->is_same_class_package(m->method_holder())) { return true; @@ -2487,7 +2487,7 @@ Method* m = InstanceKlass::cast(ref_klass)->uncached_lookup_method( vmSymbols::object_initializer_name(), cp->signature_ref_at(bcs->get_index_u2()), - Klass::normal); + Klass::find_overpass); // Do nothing if method is not found. Let resolution detect the error. if (m != NULL) { instanceKlassHandle mh(THREAD, m->method_holder()); diff -r 544fb99e0080 -r f7339cba0a6a hotspot/src/share/vm/interpreter/linkResolver.cpp --- a/hotspot/src/share/vm/interpreter/linkResolver.cpp Tue Jan 20 13:56:57 2015 +0100 +++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp Fri Jan 23 09:54:33 2015 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -289,11 +289,11 @@ // returns first instance method // Looks up method in classes, then looks up local default methods void LinkResolver::lookup_instance_method_in_klasses(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) { - Method* result_oop = klass->uncached_lookup_method(name, signature, Klass::normal); + Method* result_oop = klass->uncached_lookup_method(name, signature, Klass::find_overpass); result = methodHandle(THREAD, result_oop); while (!result.is_null() && result->is_static() && result->method_holder()->super() != NULL) { KlassHandle super_klass = KlassHandle(THREAD, result->method_holder()->super()); - result = methodHandle(THREAD, super_klass->uncached_lookup_method(name, signature, Klass::normal)); + result = methodHandle(THREAD, super_klass->uncached_lookup_method(name, signature, Klass::find_overpass)); } if (klass->oop_is_array()) { @@ -320,7 +320,8 @@ // First check in default method array if (!resolved_method->is_abstract() && (InstanceKlass::cast(klass())->default_methods() != NULL)) { - int index = InstanceKlass::find_method_index(InstanceKlass::cast(klass())->default_methods(), name, signature, false); + int index = InstanceKlass::find_method_index(InstanceKlass::cast(klass())->default_methods(), + name, signature, Klass::find_overpass, Klass::find_static); if (index >= 0 ) { vtable_index = InstanceKlass::cast(klass())->default_vtable_indices()->at(index); } diff -r 544fb99e0080 -r f7339cba0a6a hotspot/src/share/vm/oops/arrayKlass.cpp --- a/hotspot/src/share/vm/oops/arrayKlass.cpp Tue Jan 20 13:56:57 2015 +0100 +++ b/hotspot/src/share/vm/oops/arrayKlass.cpp Fri Jan 23 09:54:33 2015 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -71,10 +71,13 @@ return super()->find_field(name, sig, fd); } -Method* ArrayKlass::uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode mode) const { +Method* ArrayKlass::uncached_lookup_method(Symbol* name, Symbol* signature, OverpassLookupMode overpass_mode) const { // There are no methods in an array klass but the super class (Object) has some assert(super(), "super klass must be present"); - return super()->uncached_lookup_method(name, signature, mode); + // Always ignore overpass methods in superclasses, although technically the + // super klass of an array, (j.l.Object) should not have + // any overpass methods present. + return super()->uncached_lookup_method(name, signature, Klass::skip_overpass); } ArrayKlass::ArrayKlass(Symbol* name) { diff -r 544fb99e0080 -r f7339cba0a6a hotspot/src/share/vm/oops/arrayKlass.hpp --- a/hotspot/src/share/vm/oops/arrayKlass.hpp Tue Jan 20 13:56:57 2015 +0100 +++ b/hotspot/src/share/vm/oops/arrayKlass.hpp Fri Jan 23 09:54:33 2015 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -82,7 +82,7 @@ Klass* find_field(Symbol* name, Symbol* sig, fieldDescriptor* fd) const; // Lookup operations - Method* uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode mode) const; + Method* uncached_lookup_method(Symbol* name, Symbol* signature, OverpassLookupMode overpass_mode) const; // Casting from Klass* static ArrayKlass* cast(Klass* k) { diff -r 544fb99e0080 -r f7339cba0a6a hotspot/src/share/vm/oops/instanceKlass.cpp --- a/hotspot/src/share/vm/oops/instanceKlass.cpp Tue Jan 20 13:56:57 2015 +0100 +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp Fri Jan 23 09:54:33 2015 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1416,33 +1416,33 @@ // find_method looks up the name/signature in the local methods array Method* InstanceKlass::find_method(Symbol* name, Symbol* signature) const { - return find_method_impl(name, signature, false); + return find_method_impl(name, signature, find_overpass, find_static); } -Method* InstanceKlass::find_method_impl(Symbol* name, Symbol* signature, bool skipping_overpass) const { - return InstanceKlass::find_method_impl(methods(), name, signature, skipping_overpass); +Method* InstanceKlass::find_method_impl(Symbol* name, Symbol* signature, + OverpassLookupMode overpass_mode, StaticLookupMode static_mode) const { + return InstanceKlass::find_method_impl(methods(), name, signature, overpass_mode, static_mode); } // find_instance_method looks up the name/signature in the local methods array // and skips over static methods Method* InstanceKlass::find_instance_method( Array* methods, Symbol* name, Symbol* signature) { - Method* meth = InstanceKlass::find_method(methods, name, signature); - if (meth != NULL && meth->is_static()) { - meth = NULL; - } + Method* meth = InstanceKlass::find_method_impl(methods, name, signature, + find_overpass, skip_static); + assert(((meth == NULL) || !meth->is_static()), "find_instance_method should have skipped statics"); return meth; } // find_method looks up the name/signature in the local methods array Method* InstanceKlass::find_method( Array* methods, Symbol* name, Symbol* signature) { - return InstanceKlass::find_method_impl(methods, name, signature, false); + return InstanceKlass::find_method_impl(methods, name, signature, find_overpass, find_static); } Method* InstanceKlass::find_method_impl( - Array* methods, Symbol* name, Symbol* signature, bool skipping_overpass) { - int hit = find_method_index(methods, name, signature, skipping_overpass); + Array* methods, Symbol* name, Symbol* signature, OverpassLookupMode overpass_mode, StaticLookupMode static_mode) { + int hit = find_method_index(methods, name, signature, overpass_mode, static_mode); return hit >= 0 ? methods->at(hit): NULL; } @@ -1454,13 +1454,19 @@ // is important during method resolution to prefer a static method, for example, // over an overpass method. int InstanceKlass::find_method_index( - Array* methods, Symbol* name, Symbol* signature, bool skipping_overpass) { + Array* methods, Symbol* name, Symbol* signature, OverpassLookupMode overpass_mode, StaticLookupMode static_mode) { + bool skipping_overpass = (overpass_mode == skip_overpass); + bool skipping_static = (static_mode == skip_static); 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, ignoring overpasses if requested. - if ((m->signature() == signature) && (!skipping_overpass || !m->is_overpass())) return hit; + if ((m->signature() == signature) && + (!skipping_overpass || !m->is_overpass()) && + (!skipping_static || !m->is_static())) { + return hit; + } // search downwards through overloaded methods int i; @@ -1468,18 +1474,26 @@ Method* m = methods->at(i); assert(m->is_method(), "must be method"); if (m->name() != name) break; - if ((m->signature() == signature) && (!skipping_overpass || !m->is_overpass())) return i; + if ((m->signature() == signature) && + (!skipping_overpass || !m->is_overpass()) && + (!skipping_static || !m->is_static())) { + 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) && (!skipping_overpass || !m->is_overpass())) return i; + if ((m->signature() == signature) && + (!skipping_overpass || !m->is_overpass()) && + (!skipping_static || !m->is_static())) { + return i; + } } // not found #ifdef ASSERT - int index = skipping_overpass ? -1 : linear_search(methods, name, signature); + int index = (skipping_overpass || skipping_static) ? -1 : linear_search(methods, name, signature); assert(index == -1, err_msg("binary search should have found entry %d", index)); #endif } @@ -1505,16 +1519,16 @@ // uncached_lookup_method searches both the local class methods array and all // superclasses methods arrays, skipping any overpass methods in superclasses. -Method* InstanceKlass::uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode mode) const { - MethodLookupMode lookup_mode = mode; +Method* InstanceKlass::uncached_lookup_method(Symbol* name, Symbol* signature, OverpassLookupMode overpass_mode) const { + OverpassLookupMode overpass_local_mode = overpass_mode; Klass* klass = const_cast(this); while (klass != NULL) { - Method* method = InstanceKlass::cast(klass)->find_method_impl(name, signature, (lookup_mode == skip_overpass)); + Method* method = InstanceKlass::cast(klass)->find_method_impl(name, signature, overpass_local_mode, find_static); if (method != NULL) { return method; } klass = InstanceKlass::cast(klass)->super(); - lookup_mode = skip_overpass; // Always ignore overpass methods in superclasses + overpass_local_mode = skip_overpass; // Always ignore overpass methods in superclasses } return NULL; } @@ -1544,7 +1558,7 @@ } // Look up interfaces if (m == NULL) { - m = lookup_method_in_all_interfaces(name, signature, normal); + m = lookup_method_in_all_interfaces(name, signature, find_defaults); } return m; } @@ -1554,7 +1568,7 @@ // They should only be found in the initial InterfaceMethodRef Method* InstanceKlass::lookup_method_in_all_interfaces(Symbol* name, Symbol* signature, - MethodLookupMode mode) const { + DefaultsLookupMode defaults_mode) const { Array* all_ifs = transitive_interfaces(); int num_ifs = all_ifs->length(); InstanceKlass *ik = NULL; @@ -1562,7 +1576,7 @@ ik = InstanceKlass::cast(all_ifs->at(i)); Method* m = ik->lookup_method(name, signature); if (m != NULL && m->is_public() && !m->is_static() && - ((mode != skip_defaults) || !m->is_default_method())) { + ((defaults_mode != skip_defaults) || !m->is_default_method())) { return m; } } diff -r 544fb99e0080 -r f7339cba0a6a hotspot/src/share/vm/oops/instanceKlass.hpp --- a/hotspot/src/share/vm/oops/instanceKlass.hpp Tue Jan 20 13:56:57 2015 +0100 +++ b/hotspot/src/share/vm/oops/instanceKlass.hpp Fri Jan 23 09:54:33 2015 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -493,14 +493,15 @@ static Method* find_instance_method(Array* methods, Symbol* name, Symbol* signature); // find a local method index in default_methods (returns -1 if not found) - static int find_method_index(Array* methods, Symbol* name, Symbol* signature, bool skipping_overpass); + static int find_method_index(Array* methods, Symbol* name, Symbol* signature, + OverpassLookupMode overpass_mode, StaticLookupMode static_mode); // lookup operation (returns NULL if not found) - Method* uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode mode) const; + Method* uncached_lookup_method(Symbol* name, Symbol* signature, OverpassLookupMode overpass_mode) const; // lookup a method in all the interfaces that this class implements // (returns NULL if not found) - Method* lookup_method_in_all_interfaces(Symbol* name, Symbol* signature, MethodLookupMode mode) const; + Method* lookup_method_in_all_interfaces(Symbol* name, Symbol* signature, DefaultsLookupMode defaults_mode) const; // lookup a method in local defaults then in all interfaces // (returns NULL if not found) @@ -1052,8 +1053,10 @@ Klass* array_klass_impl(bool or_null, TRAPS); // find a local method (returns NULL if not found) - Method* find_method_impl(Symbol* name, Symbol* signature, bool skipping_overpass) const; - static Method* find_method_impl(Array* methods, Symbol* name, Symbol* signature, bool skipping_overpass); + Method* find_method_impl(Symbol* name, Symbol* signature, + OverpassLookupMode overpass_mode, StaticLookupMode static_mode) const; + static Method* find_method_impl(Array* methods, Symbol* name, Symbol* signature, + OverpassLookupMode overpass_mode, StaticLookupMode static_mode); // Free CHeap allocated fields. void release_C_heap_structures(); diff -r 544fb99e0080 -r f7339cba0a6a hotspot/src/share/vm/oops/klass.cpp --- a/hotspot/src/share/vm/oops/klass.cpp Tue Jan 20 13:56:57 2015 +0100 +++ b/hotspot/src/share/vm/oops/klass.cpp Fri Jan 23 09:54:33 2015 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -140,7 +140,7 @@ return NULL; } -Method* Klass::uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode mode) const { +Method* Klass::uncached_lookup_method(Symbol* name, Symbol* signature, OverpassLookupMode overpass_mode) const { #ifdef ASSERT tty->print_cr("Error: uncached_lookup_method called on a klass oop." " Likely error: reflection method does not correctly" diff -r 544fb99e0080 -r f7339cba0a6a hotspot/src/share/vm/oops/klass.hpp --- a/hotspot/src/share/vm/oops/klass.hpp Tue Jan 20 13:56:57 2015 +0100 +++ b/hotspot/src/share/vm/oops/klass.hpp Fri Jan 23 09:54:33 2015 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -164,7 +164,9 @@ void* operator new(size_t size, ClassLoaderData* loader_data, size_t word_size, TRAPS) throw(); public: - enum MethodLookupMode { normal, skip_overpass, skip_defaults }; + enum DefaultsLookupMode { find_defaults, skip_defaults }; + enum OverpassLookupMode { find_overpass, skip_overpass }; + enum StaticLookupMode { find_static, skip_static }; bool is_klass() const volatile { return true; } @@ -413,10 +415,10 @@ // lookup operation for MethodLookupCache friend class MethodLookupCache; virtual Klass* find_field(Symbol* name, Symbol* signature, fieldDescriptor* fd) const; - virtual Method* uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode mode) const; + virtual Method* uncached_lookup_method(Symbol* name, Symbol* signature, OverpassLookupMode overpass_mode) const; public: Method* lookup_method(Symbol* name, Symbol* signature) const { - return uncached_lookup_method(name, signature, normal); + return uncached_lookup_method(name, signature, find_overpass); } // array class with specific rank diff -r 544fb99e0080 -r f7339cba0a6a hotspot/src/share/vm/oops/klassVtable.cpp --- a/hotspot/src/share/vm/oops/klassVtable.cpp Tue Jan 20 13:56:57 2015 +0100 +++ b/hotspot/src/share/vm/oops/klassVtable.cpp Fri Jan 23 09:54:33 2015 -0500 @@ -649,7 +649,7 @@ // this check for all access permissions. InstanceKlass *sk = InstanceKlass::cast(super); if (sk->has_miranda_methods()) { - if (sk->lookup_method_in_all_interfaces(name, signature, Klass::normal) != NULL) { + if (sk->lookup_method_in_all_interfaces(name, signature, Klass::find_defaults) != NULL) { return false; // found a matching miranda; we do not need a new entry } } @@ -725,7 +725,7 @@ && mo->method_holder() != NULL && mo->method_holder()->super() != NULL) { - mo = mo->method_holder()->super()->uncached_lookup_method(name, signature, Klass::normal); + mo = mo->method_holder()->super()->uncached_lookup_method(name, signature, Klass::find_overpass); } if (mo == NULL || mo->access_flags().is_private() ) { // super class hierarchy does not implement it or protection is different @@ -770,7 +770,7 @@ if (is_miranda(im, class_methods, default_methods, super)) { // is it a miranda at all? InstanceKlass *sk = InstanceKlass::cast(super); // check if it is a duplicate of a super's miranda - if (sk->lookup_method_in_all_interfaces(im->name(), im->signature(), Klass::normal) == NULL) { + if (sk->lookup_method_in_all_interfaces(im->name(), im->signature(), Klass::find_defaults) == NULL) { new_mirandas->append(im); } if (all_mirandas != NULL) { diff -r 544fb99e0080 -r f7339cba0a6a hotspot/src/share/vm/prims/jvm.cpp --- a/hotspot/src/share/vm/prims/jvm.cpp Tue Jan 20 13:56:57 2015 +0100 +++ b/hotspot/src/share/vm/prims/jvm.cpp Fri Jan 23 09:54:33 2015 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1167,7 +1167,7 @@ Method* m_oop = object->klass()->uncached_lookup_method( vmSymbols::run_method_name(), vmSymbols::void_object_signature(), - Klass::normal); + Klass::find_overpass); methodHandle m (THREAD, m_oop); if (m.is_null() || !m->is_method() || !m()->is_public() || m()->is_static()) { THROW_MSG_0(vmSymbols::java_lang_InternalError(), "No run method"); diff -r 544fb99e0080 -r f7339cba0a6a hotspot/src/share/vm/prims/nativeLookup.cpp --- a/hotspot/src/share/vm/prims/nativeLookup.cpp Tue Jan 20 13:56:57 2015 +0100 +++ b/hotspot/src/share/vm/prims/nativeLookup.cpp Fri Jan 23 09:54:33 2015 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -393,7 +393,7 @@ // Find method and invoke standard lookup methodHandle method (THREAD, - klass->uncached_lookup_method(m_name, s_name, Klass::normal)); + klass->uncached_lookup_method(m_name, s_name, Klass::find_overpass)); address result = lookup(method, in_base_library, CATCH); assert(in_base_library, "must be in basic library"); guarantee(result != NULL, "must be non NULL");