提交 f2be3afa 编写于 作者: D drchase

8064524: Compiler code generation improvements

Reviewed-by: jrose, acorn, vlivanov
上级 9ec4da69
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -560,7 +560,7 @@ void Dependencies::print_dependency(DepType dept, GrowableArray<DepArgument>* ar ...@@ -560,7 +560,7 @@ void Dependencies::print_dependency(DepType dept, GrowableArray<DepArgument>* ar
put_star = !Dependencies::is_concrete_klass((Klass*)arg.metadata_value()); put_star = !Dependencies::is_concrete_klass((Klass*)arg.metadata_value());
} else if (arg.is_method()) { } else if (arg.is_method()) {
what = "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()) { } else if (arg.is_klass()) {
what = "class "; what = "class ";
} else { } else {
...@@ -845,8 +845,8 @@ class ClassHierarchyWalker { ...@@ -845,8 +845,8 @@ class ClassHierarchyWalker {
// Static methods don't override non-static so punt // Static methods don't override non-static so punt
return true; return true;
} }
if ( !Dependencies::is_concrete_method(lm) if ( !Dependencies::is_concrete_method(lm, k)
&& !Dependencies::is_concrete_method(m) && !Dependencies::is_concrete_method(m, ctxk)
&& lm->method_holder()->is_subtype_of(m->method_holder())) && lm->method_holder()->is_subtype_of(m->method_holder()))
// Method m is overridden by lm, but both are non-concrete. // Method m is overridden by lm, but both are non-concrete.
return true; return true;
...@@ -880,8 +880,17 @@ class ClassHierarchyWalker { ...@@ -880,8 +880,17 @@ class ClassHierarchyWalker {
if (doing_subtype_search()) { if (doing_subtype_search()) {
return Dependencies::is_concrete_klass(k); return Dependencies::is_concrete_klass(k);
} else { } else {
Method* m = InstanceKlass::cast(k)->find_method(_name, _signature); // Search class hierarchy first.
if (m == NULL || !Dependencies::is_concrete_method(m)) return false; 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<Method*>* 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; _found_methods[_num_participants] = m;
// Note: If add_participant(k) is called, // Note: If add_participant(k) is called,
// the method m will already be memoized for it. // the method m will already be memoized for it.
...@@ -1172,15 +1181,17 @@ bool Dependencies::is_concrete_klass(Klass* k) { ...@@ -1172,15 +1181,17 @@ bool Dependencies::is_concrete_klass(Klass* k) {
return true; return true;
} }
bool Dependencies::is_concrete_method(Method* m) { bool Dependencies::is_concrete_method(Method* m, Klass * k) {
// Statics are irrelevant to virtual call sites. // NULL is not a concrete method,
if (m->is_static()) return false; // statics are irrelevant to virtual call sites,
// abstract methods are not concrete,
// We could also return false if m does not yet appear to be // overpass (error) methods are not concrete if k is abstract
// executed, if the VM version supports this distinction also. //
// Default methods are considered "concrete" as well. // note "true" is conservative answer --
return !m->is_abstract() && // overpass clause is false if k == NULL, implies return true if
!m->is_overpass(); // error functions aren't concrete // 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 @@ bool Dependencies::is_concrete_klass(ciInstanceKlass* k) { ...@@ -1205,16 +1216,6 @@ bool Dependencies::is_concrete_klass(ciInstanceKlass* k) {
return true; 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) { bool Dependencies::has_finalizable_subclass(ciInstanceKlass* k) {
return k->has_finalizable_subclass(); return k->has_finalizable_subclass();
} }
...@@ -1428,7 +1429,7 @@ Method* Dependencies::find_unique_concrete_method(Klass* ctxk, Method* m) { ...@@ -1428,7 +1429,7 @@ Method* Dependencies::find_unique_concrete_method(Klass* ctxk, Method* m) {
Klass* wit = wf.find_witness_definer(ctxk); Klass* wit = wf.find_witness_definer(ctxk);
if (wit != NULL) return NULL; // Too many witnesses. if (wit != NULL) return NULL; // Too many witnesses.
Method* fm = wf.found_method(0); // Will be NULL if num_parts == 0. 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) { if (fm == NULL) {
// It turns out that m was always the only implementation. // It turns out that m was always the only implementation.
fm = m; fm = m;
...@@ -1458,61 +1459,6 @@ Klass* Dependencies::check_exclusive_concrete_methods(Klass* ctxk, ...@@ -1458,61 +1459,6 @@ Klass* Dependencies::check_exclusive_concrete_methods(Klass* ctxk,
return wf.find_witness_definer(ctxk, changes); 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* Dependencies::check_has_no_finalizable_subclasses(Klass* ctxk, KlassDepChange* changes) {
Klass* search_at = ctxk; Klass* search_at = ctxk;
if (changes != NULL) if (changes != NULL)
...@@ -1520,7 +1466,6 @@ Klass* Dependencies::check_has_no_finalizable_subclasses(Klass* ctxk, KlassDepCh ...@@ -1520,7 +1466,6 @@ Klass* Dependencies::check_has_no_finalizable_subclasses(Klass* ctxk, KlassDepCh
return find_finalizable_subclass(search_at); return find_finalizable_subclass(search_at);
} }
Klass* Dependencies::check_call_site_target_value(oop call_site, oop method_handle, CallSiteDepChange* changes) { 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(call_site ->is_a(SystemDictionary::CallSite_klass()), "sanity");
assert(method_handle->is_a(SystemDictionary::MethodHandle_klass()), "sanity"); assert(method_handle->is_a(SystemDictionary::MethodHandle_klass()), "sanity");
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -287,7 +287,7 @@ class Dependencies: public ResourceObj { ...@@ -287,7 +287,7 @@ class Dependencies: public ResourceObj {
// In that case, there would be a middle ground between concrete // In that case, there would be a middle ground between concrete
// and abstract (as defined by the Java language and VM). // and abstract (as defined by the Java language and VM).
static bool is_concrete_klass(Klass* k); // k is instantiable 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); static Klass* find_finalizable_subclass(Klass* k);
// These versions of the concreteness queries work through the CI. // These versions of the concreteness queries work through the CI.
...@@ -301,7 +301,6 @@ class Dependencies: public ResourceObj { ...@@ -301,7 +301,6 @@ class Dependencies: public ResourceObj {
// not go back into the VM to get their value; they must cache the // not go back into the VM to get their value; they must cache the
// bit in the CI, either eagerly or lazily.) // bit in the CI, either eagerly or lazily.)
static bool is_concrete_klass(ciInstanceKlass* k); // k appears instantiable 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); static bool has_finalizable_subclass(ciInstanceKlass* k);
// As a general rule, it is OK to compile under the assumption that // As a general rule, it is OK to compile under the assumption that
...@@ -348,7 +347,6 @@ class Dependencies: public ResourceObj { ...@@ -348,7 +347,6 @@ class Dependencies: public ResourceObj {
static Klass* find_unique_concrete_subtype(Klass* ctxk); static Klass* find_unique_concrete_subtype(Klass* ctxk);
static Method* find_unique_concrete_method(Klass* ctxk, Method* m); 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_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. // Create the encoding which will be stored in an nmethod.
void encode_content_bytes(); void encode_content_bytes();
......
...@@ -320,7 +320,7 @@ int LinkResolver::vtable_index_of_interface_method(KlassHandle klass, ...@@ -320,7 +320,7 @@ int LinkResolver::vtable_index_of_interface_method(KlassHandle klass,
// First check in default method array // First check in default method array
if (!resolved_method->is_abstract() && if (!resolved_method->is_abstract() &&
(InstanceKlass::cast(klass())->default_methods() != NULL)) { (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 ) { if (index >= 0 ) {
vtable_index = InstanceKlass::cast(klass())->default_vtable_indices()->at(index); vtable_index = InstanceKlass::cast(klass())->default_vtable_indices()->at(index);
} }
......
...@@ -1453,32 +1453,41 @@ Method* InstanceKlass::find_method(Symbol* name, Symbol* signature) const { ...@@ -1453,32 +1453,41 @@ Method* InstanceKlass::find_method(Symbol* name, Symbol* signature) const {
} }
Method* InstanceKlass::find_method_impl(Symbol* name, Symbol* signature, bool skipping_overpass) const { 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 // find_instance_method looks up the name/signature in the local methods array
// and skips over static methods // and skips over static methods
Method* InstanceKlass::find_instance_method( Method* InstanceKlass::find_instance_method(
Array<Method*>* methods, Symbol* name, Symbol* signature) { Array<Method*>* methods, Symbol* name, Symbol* signature) {
Method* meth = InstanceKlass::find_method(methods, name, signature); Method* meth = InstanceKlass::find_method_impl(methods, name, signature, false, true);
if (meth != NULL && meth->is_static()) {
meth = NULL;
}
return meth; 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 // find_method looks up the name/signature in the local methods array
Method* InstanceKlass::find_method( Method* InstanceKlass::find_method(
Array<Method*>* methods, Symbol* name, Symbol* signature) { Array<Method*>* 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( Method* InstanceKlass::find_method_impl(
Array<Method*>* methods, Symbol* name, Symbol* signature, bool skipping_overpass) { Array<Method*>* methods, Symbol* name, Symbol* signature, bool skipping_overpass, bool skipping_static) {
int hit = find_method_index(methods, name, signature, skipping_overpass); int hit = find_method_index(methods, name, signature, skipping_overpass, skipping_static);
return hit >= 0 ? methods->at(hit): NULL; 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 // Used directly for default_methods to find the index into the
// default_vtable_indices, and indirectly by find_method // default_vtable_indices, and indirectly by find_method
// find_method_index looks in the local methods array to return the index // find_method_index looks in the local methods array to return the index
...@@ -1487,13 +1496,14 @@ Method* InstanceKlass::find_method_impl( ...@@ -1487,13 +1496,14 @@ Method* InstanceKlass::find_method_impl(
// is important during method resolution to prefer a static method, for example, // is important during method resolution to prefer a static method, for example,
// over an overpass method. // over an overpass method.
int InstanceKlass::find_method_index( int InstanceKlass::find_method_index(
Array<Method*>* methods, Symbol* name, Symbol* signature, bool skipping_overpass) { Array<Method*>* methods, Symbol* name, Symbol* signature, bool skipping_overpass, bool skipping_static) {
int hit = binary_search(methods, name); int hit = binary_search(methods, name);
if (hit != -1) { if (hit != -1) {
Method* m = methods->at(hit); Method* m = methods->at(hit);
// Do linear search to find matching signature. First, quick check // Do linear search to find matching signature. First, quick check
// for common case, ignoring overpasses if requested. // 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 // search downwards through overloaded methods
int i; int i;
...@@ -1501,18 +1511,18 @@ int InstanceKlass::find_method_index( ...@@ -1501,18 +1511,18 @@ int InstanceKlass::find_method_index(
Method* m = methods->at(i); Method* m = methods->at(i);
assert(m->is_method(), "must be method"); assert(m->is_method(), "must be method");
if (m->name() != name) break; 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 // search upwards
for (i = hit + 1; i < methods->length(); ++i) { for (i = hit + 1; i < methods->length(); ++i) {
Method* m = methods->at(i); Method* m = methods->at(i);
assert(m->is_method(), "must be method"); assert(m->is_method(), "must be method");
if (m->name() != name) break; 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 // not found
#ifdef ASSERT #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)); assert(index == -1, err_msg("binary search should have found entry %d", index));
#endif #endif
} }
......
...@@ -520,10 +520,16 @@ class InstanceKlass: public Klass { ...@@ -520,10 +520,16 @@ class InstanceKlass: public Klass {
// find a local method (returns NULL if not found) // find a local method (returns NULL if not found)
Method* find_method(Symbol* name, Symbol* signature) const; Method* find_method(Symbol* name, Symbol* signature) const;
static Method* find_method(Array<Method*>* methods, Symbol* name, Symbol* signature); static Method* find_method(Array<Method*>* 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<Method*>* methods, Symbol* name, Symbol* signature); static Method* find_instance_method(Array<Method*>* 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) // find a local method index in default_methods (returns -1 if not found)
static int find_method_index(Array<Method*>* methods, Symbol* name, Symbol* signature, bool skipping_overpass); static int find_method_index(Array<Method*>* methods, Symbol* name, Symbol* signature, bool skipping_overpass, bool skipping_static);
// lookup operation (returns NULL if not found) // 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, MethodLookupMode mode) const;
...@@ -1076,7 +1082,7 @@ private: ...@@ -1076,7 +1082,7 @@ private:
// find a local method (returns NULL if not found) // find a local method (returns NULL if not found)
Method* find_method_impl(Symbol* name, Symbol* signature, bool skipping_overpass) const; Method* find_method_impl(Symbol* name, Symbol* signature, bool skipping_overpass) const;
static Method* find_method_impl(Array<Method*>* methods, Symbol* name, Symbol* signature, bool skipping_overpass); static Method* find_method_impl(Array<Method*>* methods, Symbol* name, Symbol* signature, bool skipping_overpass, bool skipping_static);
// Free CHeap allocated fields. // Free CHeap allocated fields.
void release_C_heap_structures(); void release_C_heap_structures();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册