Mercurial > hg > openjdk > jdk7u > hotspot
changeset 5826:7d1eb0dcab5a
8064524: Compiler code generation improvements
Summary: Contains refactoring from 8009130, 8033150, 7200776 & 8028438 without default method work
Reviewed-by: jrose, acorn, vlivanov
author | drchase |
---|---|
date | Tue, 17 Apr 2018 22:51:28 +0100 |
parents | 8b0587cd6277 |
children | 0dc659da232e |
files | src/share/vm/code/dependencies.cpp src/share/vm/code/dependencies.hpp src/share/vm/interpreter/linkResolver.cpp src/share/vm/oops/instanceKlass.cpp src/share/vm/oops/instanceKlass.hpp |
diffstat | 5 files changed, 119 insertions(+), 113 deletions(-) [+] |
line wrap: on
line diff
--- a/src/share/vm/code/dependencies.cpp Sat Apr 14 07:26:03 2018 +0100 +++ b/src/share/vm/code/dependencies.cpp Tue Apr 17 22:51:28 2018 +0100 @@ -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 @@ -810,8 +810,11 @@ if (doing_subtype_search()) { return Dependencies::is_concrete_klass(k); } else { - methodOop m = instanceKlass::cast(k)->find_method(_name, _signature); - if (m == NULL || !Dependencies::is_concrete_method(m)) return false; + // Search class hierarchy first. + methodOop m = instanceKlass::cast(k)->find_instance_method(_name, _signature); + if (!Dependencies::is_concrete_method(m)) { + return false; + } _found_methods[_num_participants] = m; // Note: If add_participant(k) is called, // the method m will already be memoized for it. @@ -1104,15 +1107,12 @@ } bool Dependencies::is_concrete_method(methodOop 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(); + // NULL is not a concrete method, + // statics are irrelevant to virtual call sites, + // abstract methods are not concrete, + return ! ( m == NULL || m -> is_static() || m -> is_abstract()); } - Klass* Dependencies::find_finalizable_subclass(Klass* k) { if (k->is_interface()) return NULL; if (k->has_finalizer()) return k; @@ -1134,16 +1134,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(); } @@ -1387,61 +1377,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(klassOop ctxk, - int mlen, - methodOop marray[]) { - methodOop m0 = marray[0]; - ClassHierarchyWalker wf(m0); - assert(wf.check_method_context(ctxk, m0), "proper context"); - wf.record_witnesses(mlen); - bool participants_hide_witnesses = true; - klassOop 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++) { - methodOop 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; -} - - klassOop Dependencies::check_has_no_finalizable_subclasses(klassOop ctxk, KlassDepChange* changes) { Klass* search_at = ctxk->klass_part(); if (changes != NULL) @@ -1453,7 +1388,6 @@ return result->as_klassOop(); } - klassOop 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");
--- a/src/share/vm/code/dependencies.hpp Sat Apr 14 07:26:03 2018 +0100 +++ b/src/share/vm/code/dependencies.hpp Tue Apr 17 22:51:28 2018 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, 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 @@ -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 klassOop find_unique_concrete_subtype(klassOop ctxk); static methodOop find_unique_concrete_method(klassOop ctxk, methodOop m); static int find_exclusive_concrete_subtypes(klassOop ctxk, int klen, klassOop k[]); - static int find_exclusive_concrete_methods(klassOop ctxk, int mlen, methodOop m[]); // Create the encoding which will be stored in an nmethod. void encode_content_bytes();
--- a/src/share/vm/interpreter/linkResolver.cpp Sat Apr 14 07:26:03 2018 +0100 +++ b/src/share/vm/interpreter/linkResolver.cpp Tue Apr 17 22:51:28 2018 +0100 @@ -188,6 +188,7 @@ // // According to JVM spec. $5.4.3c & $5.4.3d +// Look up method in klasses, including static methods void LinkResolver::lookup_method_in_klasses(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) { methodOop result_oop = klass->uncached_lookup_method(name, signature); @@ -213,8 +214,8 @@ methodOop result_oop = klass->uncached_lookup_method(name, signature); result = methodHandle(THREAD, result_oop); while (!result.is_null() && result->is_static()) { - klass = KlassHandle(THREAD, Klass::cast(result->method_holder())->super()); - result = methodHandle(THREAD, klass->uncached_lookup_method(name, signature)); + KlassHandle super_klass = KlassHandle(THREAD, Klass::cast(result->method_holder())->super()); + result = methodHandle(THREAD, super_klass->uncached_lookup_method(name, signature)); } }
--- a/src/share/vm/oops/instanceKlass.cpp Sat Apr 14 07:26:03 2018 +0100 +++ b/src/share/vm/oops/instanceKlass.cpp Tue Apr 17 22:51:28 2018 +0100 @@ -1046,11 +1046,7 @@ } #endif -methodOop instanceKlass::find_method(Symbol* name, Symbol* signature) const { - return instanceKlass::find_method(methods(), name, signature); -} - -methodOop instanceKlass::find_method(objArrayOop methods, Symbol* name, Symbol* signature) { +static int binary_search(objArrayOop methods, Symbol* name) { int len = methods->length(); // methods are sorted, so do binary search int l = 0; @@ -1061,43 +1057,100 @@ assert(m->is_method(), "must be method"); int res = m->name()->fast_compare(name); if (res == 0) { - // found matching name; do linear search to find matching signature - // first, quick check for common case - if (m->signature() == signature) return m; - // search downwards through overloaded methods - int i; - for (i = mid - 1; i >= l; i--) { - methodOop m = (methodOop)methods->obj_at(i); - assert(m->is_method(), "must be method"); - if (m->name() != name) break; - if (m->signature() == signature) return m; - } - // search upwards - for (i = mid + 1; i <= h; i++) { - methodOop m = (methodOop)methods->obj_at(i); - assert(m->is_method(), "must be method"); - if (m->name() != name) break; - if (m->signature() == signature) return m; - } - // not found -#ifdef ASSERT - int index = linear_search(methods, name, signature); - assert(index == -1, err_msg("binary search should have found entry %d", index)); -#endif - return NULL; + return mid; } else if (res < 0) { l = mid + 1; } else { h = mid - 1; } } + return -1; +} + +// find_method looks up the name/signature in the local methods array +methodOop instanceKlass::find_method(Symbol* name, Symbol* signature) const { + return instanceKlass::find_method(methods(), name, signature); +} + +// find_instance_method looks up the name/signature in the local methods array +// and skips over static methods +methodOop instanceKlass::find_instance_method(Symbol* name, Symbol* signature) { + return instanceKlass::find_instance_method(methods(), name, signature); +} + +// find_instance_method looks up the name/signature in the local methods array +// and skips over static methods +methodOop instanceKlass::find_instance_method(objArrayOop methods, Symbol* name, Symbol* signature) { + methodOop meth = instanceKlass::find_method_impl(methods, name, signature, true); + return meth; +} + +// find_method looks up the name/signature in the local methods array +methodOop instanceKlass::find_method(objArrayOop methods, Symbol* name, Symbol* signature) { + return instanceKlass::find_method_impl(methods, name, signature, false); +} + +methodOop instanceKlass::find_method_impl(objArrayOop methods, Symbol* name, Symbol* signature, bool skipping_static) { + int hit = find_method_index(methods, name, signature, skipping_static); + return hit >= 0 ? (methodOop) methods->obj_at(hit): NULL; +} + +bool instanceKlass::method_matches(methodOop m, Symbol* signature, bool skipping_static) { + return (m->signature() == signature) && (!skipping_static || !m->is_static()); +} + +// Used 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(objArrayOop methods, Symbol* name, Symbol* signature, bool skipping_static) { + int hit = binary_search(methods, name); + if (hit != -1) { + methodOop m = (methodOop) methods->obj_at(hit); + + // Do linear search to find matching signature. First, quick check + // for common case + if (method_matches(m, signature, skipping_static)) return hit; + // search downwards through overloaded methods + int i; + for (i = hit - 1; i >= 0; --i) { + methodOop m = (methodOop) methods->obj_at(i); + assert(m->is_method(), "must be method"); + if (m->name() != name) break; + if (method_matches(m, signature, skipping_static)) return i; + } + // search upwards + for (i = hit + 1; i < methods->length(); ++i) { + methodOop m = (methodOop) methods->obj_at(i); + assert(m->is_method(), "must be method"); + if (m->name() != name) break; + if (method_matches(m, signature, skipping_static)) return i; + } + // not found #ifdef ASSERT - int index = linear_search(methods, name, signature); - assert(index == -1, err_msg("binary search should have found entry %d", index)); + int index = skipping_static ? -1 : linear_search(methods, name, signature); + 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); } +int instanceKlass::find_method_by_name(objArrayOop methods, Symbol* name, int* end_ptr) { + assert(end_ptr != NULL, "just checking"); + int start = binary_search(methods, name); + int end = start + 1; + if (start != -1) { + while (start - 1 >= 0 && ((methodOop)(methods->obj_at(start - 1)))->name() == name) --start; + while (end < methods->length() && ((methodOop)(methods->obj_at(end)))->name() == name) ++end; + *end_ptr = end; + return start; + } + return -1; +} + +// lookup_method searches both the local methods array and all superclasses methods arrays methodOop instanceKlass::uncached_lookup_method(Symbol* name, Symbol* signature) const { klassOop klass = as_klassOop(); while (klass != NULL) {
--- a/src/share/vm/oops/instanceKlass.hpp Sat Apr 14 07:26:03 2018 +0100 +++ b/src/share/vm/oops/instanceKlass.hpp Tue Apr 17 22:51:28 2018 +0100 @@ -494,6 +494,16 @@ methodOop find_method(Symbol* name, Symbol* signature) const; static methodOop find_method(objArrayOop methods, Symbol* name, Symbol* signature); + // find a local method, but skip static methods + methodOop find_instance_method(Symbol* name, Symbol* signature); + static methodOop find_instance_method(objArrayOop methods, Symbol* name, Symbol* signature); + + // true if method matches signature and conforms to skipping_X conditions. + static bool method_matches(methodOop m, Symbol* signature, bool skipping_static); + + // find a local method index in default_methods (returns -1 if not found) + static int find_method_index(objArrayOop methods, Symbol* name, Symbol* signature, bool skipping_static); + // lookup operation (returns NULL if not found) methodOop uncached_lookup_method(Symbol* name, Symbol* signature) const; @@ -501,6 +511,13 @@ // (returns NULL if not found) methodOop lookup_method_in_all_interfaces(Symbol* name, Symbol* signature) const; + // Find method indices by name. If a method with the specified name is + // found the index to the first method is returned, and 'end' is filled in + // with the index of first non-name-matching method. If no method is found + // -1 is returned. + int find_method_by_name(Symbol* name, int* end); + static int find_method_by_name(objArrayOop methods, Symbol* name, int* end); + // constant pool constantPoolOop constants() const { return _constants; } void set_constants(constantPoolOop c) { oop_store_without_check((oop*) &_constants, (oop) c); } @@ -968,6 +985,9 @@ // Returns the array class with this class as element type klassOop array_klass_impl(bool or_null, TRAPS); + // find a local method (returns NULL if not found) + static methodOop find_method_impl(objArrayOop methods, Symbol* name, Symbol* signature, bool skipping_static); + public: // sharing support virtual void remove_unshareable_info();