# HG changeset patch # User asaha # Date 1417489794 28800 # Node ID d6a05415f1f47faf4c58d14e316dfca6d83cd14d # Parent f3ffb37f88a636ac1457a277631680bbde4b1d63# Parent d5b74c583ec1530f407af92e74fafbd1d08993f2 Merge diff -r f3ffb37f88a6 -r d6a05415f1f4 src/share/vm/code/dependencies.cpp --- a/src/share/vm/code/dependencies.cpp Mon Dec 01 11:29:12 2014 -0800 +++ b/src/share/vm/code/dependencies.cpp Mon Dec 01 19:09:54 2014 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2014, 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 @@ -560,7 +560,7 @@ put_star = !Dependencies::is_concrete_klass((Klass*)arg.metadata_value()); } else if (arg.is_method()) { what = "method "; - put_star = !Dependencies::is_concrete_method((Method*)arg.metadata_value()); + put_star = !Dependencies::is_concrete_method((Method*)arg.metadata_value(), NULL); } else if (arg.is_klass()) { what = "class "; } else { @@ -845,8 +845,8 @@ // Static methods don't override non-static so punt return true; } - if ( !Dependencies::is_concrete_method(lm) - && !Dependencies::is_concrete_method(m) + if ( !Dependencies::is_concrete_method(lm, k) + && !Dependencies::is_concrete_method(m, ctxk) && lm->method_holder()->is_subtype_of(m->method_holder())) // Method m is overridden by lm, but both are non-concrete. return true; @@ -880,8 +880,17 @@ if (doing_subtype_search()) { return Dependencies::is_concrete_klass(k); } else { - Method* m = InstanceKlass::cast(k)->find_method(_name, _signature); - if (m == NULL || !Dependencies::is_concrete_method(m)) return false; + // Search class hierarchy first. + Method* m = InstanceKlass::cast(k)->find_instance_method(_name, _signature); + if (!Dependencies::is_concrete_method(m, k)) { + // Check interface defaults also, if any exist. + Array* default_methods = InstanceKlass::cast(k)->default_methods(); + if (default_methods == NULL) + return false; + m = InstanceKlass::cast(k)->find_method(default_methods, _name, _signature); + if (!Dependencies::is_concrete_method(m, NULL)) + return false; + } _found_methods[_num_participants] = m; // Note: If add_participant(k) is called, // the method m will already be memoized for it. @@ -1172,15 +1181,17 @@ return true; } -bool Dependencies::is_concrete_method(Method* m) { - // Statics are irrelevant to virtual call sites. - if (m->is_static()) return false; - - // We could also return false if m does not yet appear to be - // executed, if the VM version supports this distinction also. - // Default methods are considered "concrete" as well. - return !m->is_abstract() && - !m->is_overpass(); // error functions aren't concrete +bool Dependencies::is_concrete_method(Method* m, Klass * k) { + // NULL is not a concrete method, + // statics are irrelevant to virtual call sites, + // abstract methods are not concrete, + // overpass (error) methods are not concrete if k is abstract + // + // note "true" is conservative answer -- + // overpass clause is false if k == NULL, implies return true if + // answer depends on overpass clause. + return ! ( m == NULL || m -> is_static() || m -> is_abstract() || + m->is_overpass() && k != NULL && k -> is_abstract() ); } @@ -1205,16 +1216,6 @@ return true; } -bool Dependencies::is_concrete_method(ciMethod* m) { - // Statics are irrelevant to virtual call sites. - if (m->is_static()) return false; - - // We could also return false if m does not yet appear to be - // executed, if the VM version supports this distinction also. - return !m->is_abstract(); -} - - bool Dependencies::has_finalizable_subclass(ciInstanceKlass* k) { return k->has_finalizable_subclass(); } @@ -1428,7 +1429,7 @@ Klass* wit = wf.find_witness_definer(ctxk); if (wit != NULL) return NULL; // Too many witnesses. Method* fm = wf.found_method(0); // Will be NULL if num_parts == 0. - if (Dependencies::is_concrete_method(m)) { + if (Dependencies::is_concrete_method(m, ctxk)) { if (fm == NULL) { // It turns out that m was always the only implementation. fm = m; @@ -1458,61 +1459,6 @@ return wf.find_witness_definer(ctxk, changes); } -// Find the set of all non-abstract methods under ctxk that match m[0]. -// (The method m[0] must be defined or inherited in ctxk.) -// Include m itself in the set, unless it is abstract. -// Fill the given array m[0..(mlen-1)] with this set, and return the length. -// (The length may be zero if no concrete methods are found anywhere.) -// If there are too many concrete methods to fit in marray, return -1. -int Dependencies::find_exclusive_concrete_methods(Klass* ctxk, - int mlen, - Method* marray[]) { - Method* m0 = marray[0]; - ClassHierarchyWalker wf(m0); - assert(wf.check_method_context(ctxk, m0), "proper context"); - wf.record_witnesses(mlen); - bool participants_hide_witnesses = true; - Klass* wit = wf.find_witness_definer(ctxk); - if (wit != NULL) return -1; // Too many witnesses. - int num = wf.num_participants(); - assert(num <= mlen, "oob"); - // Keep track of whether m is also part of the result set. - int mfill = 0; - assert(marray[mfill] == m0, "sanity"); - if (Dependencies::is_concrete_method(m0)) - mfill++; // keep m0 as marray[0], the first result - for (int i = 0; i < num; i++) { - Method* fm = wf.found_method(i); - if (fm == m0) continue; // Already put this guy in the list. - if (mfill == mlen) { - return -1; // Oops. Too many methods after all! - } - marray[mfill++] = fm; - } -#ifndef PRODUCT - // Make sure the dependency mechanism will pass this discovery: - if (VerifyDependencies) { - // Turn off dependency tracing while actually testing deps. - FlagSetting fs(TraceDependencies, false); - switch (mfill) { - case 1: - guarantee(NULL == (void *)check_unique_concrete_method(ctxk, marray[0]), - "verify dep."); - break; - case 2: - guarantee(NULL == (void *) - check_exclusive_concrete_methods(ctxk, marray[0], marray[1]), - "verify dep."); - break; - default: - ShouldNotReachHere(); // mlen > 2 yet supported - } - } -#endif //PRODUCT - return mfill; -} - - Klass* Dependencies::check_has_no_finalizable_subclasses(Klass* ctxk, KlassDepChange* changes) { Klass* search_at = ctxk; if (changes != NULL) @@ -1520,7 +1466,6 @@ return find_finalizable_subclass(search_at); } - Klass* Dependencies::check_call_site_target_value(oop call_site, oop method_handle, CallSiteDepChange* changes) { assert(call_site ->is_a(SystemDictionary::CallSite_klass()), "sanity"); assert(method_handle->is_a(SystemDictionary::MethodHandle_klass()), "sanity"); diff -r f3ffb37f88a6 -r d6a05415f1f4 src/share/vm/code/dependencies.hpp --- a/src/share/vm/code/dependencies.hpp Mon Dec 01 11:29:12 2014 -0800 +++ b/src/share/vm/code/dependencies.hpp Mon Dec 01 19:09:54 2014 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2014, 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 @@ -287,7 +287,7 @@ // In that case, there would be a middle ground between concrete // and abstract (as defined by the Java language and VM). static bool is_concrete_klass(Klass* k); // k is instantiable - static bool is_concrete_method(Method* m); // m is invocable + static bool is_concrete_method(Method* m, Klass* k); // m is invocable static Klass* find_finalizable_subclass(Klass* k); // These versions of the concreteness queries work through the CI. @@ -301,7 +301,6 @@ // not go back into the VM to get their value; they must cache the // bit in the CI, either eagerly or lazily.) static bool is_concrete_klass(ciInstanceKlass* k); // k appears instantiable - static bool is_concrete_method(ciMethod* m); // m appears invocable static bool has_finalizable_subclass(ciInstanceKlass* k); // As a general rule, it is OK to compile under the assumption that @@ -348,7 +347,6 @@ static Klass* find_unique_concrete_subtype(Klass* ctxk); static Method* find_unique_concrete_method(Klass* ctxk, Method* m); static int find_exclusive_concrete_subtypes(Klass* ctxk, int klen, Klass* k[]); - static int find_exclusive_concrete_methods(Klass* ctxk, int mlen, Method* m[]); // Create the encoding which will be stored in an nmethod. void encode_content_bytes(); diff -r f3ffb37f88a6 -r d6a05415f1f4 src/share/vm/interpreter/linkResolver.cpp --- a/src/share/vm/interpreter/linkResolver.cpp Mon Dec 01 11:29:12 2014 -0800 +++ b/src/share/vm/interpreter/linkResolver.cpp Mon Dec 01 19:09:54 2014 -0800 @@ -320,7 +320,7 @@ // 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, false, false); if (index >= 0 ) { vtable_index = InstanceKlass::cast(klass())->default_vtable_indices()->at(index); } diff -r f3ffb37f88a6 -r d6a05415f1f4 src/share/vm/oops/instanceKlass.cpp --- a/src/share/vm/oops/instanceKlass.cpp Mon Dec 01 11:29:12 2014 -0800 +++ b/src/share/vm/oops/instanceKlass.cpp Mon Dec 01 19:09:54 2014 -0800 @@ -1453,32 +1453,41 @@ } Method* InstanceKlass::find_method_impl(Symbol* name, Symbol* signature, bool skipping_overpass) const { - return InstanceKlass::find_method_impl(methods(), name, signature, skipping_overpass); + return InstanceKlass::find_method_impl(methods(), name, signature, skipping_overpass, false); } // 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, false, true); return meth; } +// find_instance_method looks up the name/signature in the local methods array +// and skips over static methods +Method* InstanceKlass::find_instance_method(Symbol* name, Symbol* signature) { + return InstanceKlass::find_instance_method(methods(), name, signature); +} + // 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, false, false); } 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, bool skipping_overpass, bool skipping_static) { + int hit = find_method_index(methods, name, signature, skipping_overpass, skipping_static); return hit >= 0 ? methods->at(hit): NULL; } +bool InstanceKlass::method_matches(Method* m, Symbol* signature, bool skipping_overpass, bool skipping_static) { + return (m->signature() == signature) && + (!skipping_overpass || !m->is_overpass()) && + (!skipping_static || !m->is_static()); +} + // 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 @@ -1487,13 +1496,14 @@ // 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, bool skipping_overpass, bool skipping_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 (method_matches(m, signature, skipping_overpass, skipping_static)) return hit; // search downwards through overloaded methods int i; @@ -1501,18 +1511,18 @@ 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 (method_matches(m, signature, skipping_overpass, skipping_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 (method_matches(m, signature, skipping_overpass, skipping_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 } diff -r f3ffb37f88a6 -r d6a05415f1f4 src/share/vm/oops/instanceKlass.hpp --- a/src/share/vm/oops/instanceKlass.hpp Mon Dec 01 11:29:12 2014 -0800 +++ b/src/share/vm/oops/instanceKlass.hpp Mon Dec 01 19:09:54 2014 -0800 @@ -520,10 +520,16 @@ // find a local method (returns NULL if not found) Method* find_method(Symbol* name, Symbol* signature) const; static Method* find_method(Array* methods, Symbol* name, Symbol* signature); + + // find a local method, but skip static methods + Method* find_instance_method(Symbol* name, Symbol* signature); static Method* find_instance_method(Array* methods, Symbol* name, Symbol* signature); + // true if method matches signature and conforms to skipping_X conditions. + static bool method_matches(Method* m, Symbol* signature, bool skipping_overpass, bool skipping_static); + // 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, bool skipping_overpass, bool skipping_static); // lookup operation (returns NULL if not found) Method* uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode mode) const; @@ -1076,7 +1082,7 @@ // 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); + static Method* find_method_impl(Array* methods, Symbol* name, Symbol* signature, bool skipping_overpass, bool skipping_static); // Free CHeap allocated fields. void release_C_heap_structures();