提交 7283861d 编写于 作者: D drchase

8064524: Compiler code generation improvements

Reviewed-by: jrose, acorn, vlivanov
上级 d3846442
/*
* 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
......@@ -544,7 +544,7 @@ void Dependencies::print_dependency(DepType dept, int nargs, DepArgument args[],
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 {
......@@ -826,8 +826,8 @@ class ClassHierarchyWalker {
// 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;
......@@ -861,8 +861,17 @@ class ClassHierarchyWalker {
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<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;
// Note: If add_participant(k) is called,
// the method m will already be memoized for it.
......@@ -1153,15 +1162,17 @@ bool Dependencies::is_concrete_klass(Klass* k) {
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() );
}
......@@ -1186,16 +1197,6 @@ bool Dependencies::is_concrete_klass(ciInstanceKlass* k) {
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();
}
......@@ -1409,7 +1410,7 @@ Method* Dependencies::find_unique_concrete_method(Klass* ctxk, Method* m) {
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;
......@@ -1439,61 +1440,6 @@ Klass* Dependencies::check_exclusive_concrete_methods(Klass* ctxk,
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)
......@@ -1501,7 +1447,6 @@ Klass* Dependencies::check_has_no_finalizable_subclasses(Klass* ctxk, KlassDepCh
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");
......
/*
* 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 @@ class Dependencies: public ResourceObj {
// 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 @@ class Dependencies: public ResourceObj {
// 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 @@ class Dependencies: public ResourceObj {
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();
......
......@@ -320,7 +320,7 @@ int LinkResolver::vtable_index_of_interface_method(KlassHandle klass,
// 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);
}
......
......@@ -1435,32 +1435,41 @@ Method* InstanceKlass::find_method(Symbol* name, Symbol* signature) 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
// and skips over static methods
Method* InstanceKlass::find_instance_method(
Array<Method*>* 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<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(
Array<Method*>* methods, Symbol* name, Symbol* signature, bool skipping_overpass) {
int hit = find_method_index(methods, name, signature, 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, 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
......@@ -1469,13 +1478,14 @@ Method* InstanceKlass::find_method_impl(
// is important during method resolution to prefer a static method, for example,
// over an overpass method.
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);
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;
......@@ -1483,18 +1493,18 @@ int InstanceKlass::find_method_index(
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
}
......
......@@ -515,10 +515,16 @@ class InstanceKlass: public Klass {
// find a local method (returns NULL if not found)
Method* find_method(Symbol* name, Symbol* signature) const;
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);
// 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<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)
Method* uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode mode) const;
......@@ -1050,7 +1056,7 @@ private:
// 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<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.
void release_C_heap_structures();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册