aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorhseigel <none@none>2014-04-17 17:35:04 -0400
committerhseigel <none@none>2014-04-17 17:35:04 -0400
commitbcd90a3bce40982b196a908019d444fb28852d7b (patch)
treed12deb6ffa2eb9c112d24bc8d14ef5715f3c3fca /src
parente610a1706b0471a5bf41b57faaa484ec76805188 (diff)
parentf6d000f74d3aa6256f1261d1e246f7100993cefa (diff)
Merge
Diffstat (limited to 'src')
-rw-r--r--src/share/vm/classfile/defaultMethods.cpp30
-rw-r--r--src/share/vm/classfile/verifier.cpp7
-rw-r--r--src/share/vm/interpreter/linkResolver.cpp17
-rw-r--r--src/share/vm/oops/arrayKlass.cpp4
-rw-r--r--src/share/vm/oops/arrayKlass.hpp2
-rw-r--r--src/share/vm/oops/instanceKlass.cpp47
-rw-r--r--src/share/vm/oops/instanceKlass.hpp10
-rw-r--r--src/share/vm/oops/klass.cpp2
-rw-r--r--src/share/vm/oops/klass.hpp6
-rw-r--r--src/share/vm/oops/klassVtable.cpp8
-rw-r--r--src/share/vm/prims/jvm.cpp3
-rw-r--r--src/share/vm/prims/nativeLookup.cpp4
12 files changed, 76 insertions, 64 deletions
diff --git a/src/share/vm/classfile/defaultMethods.cpp b/src/share/vm/classfile/defaultMethods.cpp
index 72020ba78..b5e4da63f 100644
--- a/src/share/vm/classfile/defaultMethods.cpp
+++ b/src/share/vm/classfile/defaultMethods.cpp
@@ -390,20 +390,6 @@ class MethodFamily : public ResourceObj {
Symbol* get_exception_message() { return _exception_message; }
Symbol* get_exception_name() { return _exception_name; }
- // Return true if the specified klass has a static method that matches
- // the name and signature of the target method.
- bool has_matching_static(InstanceKlass* root) {
- if (_members.length() > 0) {
- Pair<Method*,QualifiedState> entry = _members.at(0);
- Method* impl = root->find_method(entry.first->name(),
- entry.first->signature());
- if ((impl != NULL) && impl->is_static()) {
- return true;
- }
- }
- return false;
- }
-
// Either sets the target or the exception error message
void determine_target(InstanceKlass* root, TRAPS) {
if (has_target() || throws_exception()) {
@@ -433,21 +419,19 @@ class MethodFamily : public ResourceObj {
// If the root klass has a static method with matching name and signature
// then do not generate an overpass method because it will hide the
// static method during resolution.
- if (!has_matching_static(root)) {
- if (qualified_methods.length() == 0) {
- _exception_message = generate_no_defaults_message(CHECK);
- } else {
- assert(root != NULL, "Null root class");
- _exception_message = generate_method_message(root->name(), qualified_methods.at(0), CHECK);
- }
- _exception_name = vmSymbols::java_lang_AbstractMethodError();
+ if (qualified_methods.length() == 0) {
+ _exception_message = generate_no_defaults_message(CHECK);
+ } else {
+ assert(root != NULL, "Null root class");
+ _exception_message = generate_method_message(root->name(), qualified_methods.at(0), CHECK);
}
+ _exception_name = vmSymbols::java_lang_AbstractMethodError();
// If only one qualified method is default, select that
} else if (num_defaults == 1) {
_selected_target = qualified_methods.at(default_index);
- } else if (num_defaults > 1 && !has_matching_static(root)) {
+ } else if (num_defaults > 1) {
_exception_message = generate_conflicts_message(&qualified_methods,CHECK);
_exception_name = vmSymbols::java_lang_IncompatibleClassChangeError();
if (TraceDefaultMethods) {
diff --git a/src/share/vm/classfile/verifier.cpp b/src/share/vm/classfile/verifier.cpp
index 2e6474743..c75a29d0f 100644
--- a/src/share/vm/classfile/verifier.cpp
+++ b/src/share/vm/classfile/verifier.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -1943,7 +1943,7 @@ bool ClassVerifier::is_protected_access(instanceKlassHandle this_class,
InstanceKlass* target_instance = InstanceKlass::cast(target_class);
fieldDescriptor fd;
if (is_method) {
- Method* m = target_instance->uncached_lookup_method(field_name, field_sig);
+ Method* m = target_instance->uncached_lookup_method(field_name, field_sig, Klass::normal);
if (m != NULL && m->is_protected()) {
if (!this_class->is_same_class_package(m->method_holder())) {
return true;
@@ -2280,7 +2280,8 @@ void ClassVerifier::verify_invoke_init(
ref_class_type.name(), CHECK_VERIFY(this));
Method* m = InstanceKlass::cast(ref_klass)->uncached_lookup_method(
vmSymbols::object_initializer_name(),
- cp->signature_ref_at(bcs->get_index_u2()));
+ cp->signature_ref_at(bcs->get_index_u2()),
+ Klass::normal);
instanceKlassHandle mh(THREAD, m->method_holder());
if (m->is_protected() && !mh->is_same_class_package(_klass())) {
bool assignable = current_type().is_assignable_from(
diff --git a/src/share/vm/interpreter/linkResolver.cpp b/src/share/vm/interpreter/linkResolver.cpp
index aa11784b7..8bcfc1f1e 100644
--- a/src/share/vm/interpreter/linkResolver.cpp
+++ b/src/share/vm/interpreter/linkResolver.cpp
@@ -243,7 +243,8 @@ void LinkResolver::resolve_klass(KlassHandle& result, constantPoolHandle pool, i
// Look up method in klasses, including static methods
// Then look up local default methods
void LinkResolver::lookup_method_in_klasses(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, bool checkpolymorphism, bool in_imethod_resolve, TRAPS) {
- Method* result_oop = klass->uncached_lookup_method(name, signature);
+ // Ignore overpasses so statics can be found during resolution
+ Method* result_oop = klass->uncached_lookup_method(name, signature, Klass::skip_overpass);
// JDK 8, JVMS 5.4.3.4: Interface method resolution should
// ignore static and non-public methods of java.lang.Object,
@@ -256,6 +257,12 @@ void LinkResolver::lookup_method_in_klasses(methodHandle& result, KlassHandle kl
result_oop = NULL;
}
+ // Before considering default methods, check for an overpass in the
+ // current class if a method has not been found.
+ if (result_oop == NULL) {
+ result_oop = InstanceKlass::cast(klass())->find_method(name, signature);
+ }
+
if (result_oop == NULL) {
Array<Method*>* default_methods = InstanceKlass::cast(klass())->default_methods();
if (default_methods != NULL) {
@@ -276,11 +283,11 @@ void LinkResolver::lookup_method_in_klasses(methodHandle& result, KlassHandle kl
// 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);
+ Method* result_oop = klass->uncached_lookup_method(name, signature, Klass::normal);
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));
+ result = methodHandle(THREAD, super_klass->uncached_lookup_method(name, signature, Klass::normal));
}
if (result.is_null()) {
@@ -302,7 +309,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);
+ int index = InstanceKlass::find_method_index(InstanceKlass::cast(klass())->default_methods(), name, signature, false);
if (index >= 0 ) {
vtable_index = InstanceKlass::cast(klass())->default_vtable_indices()->at(index);
}
@@ -322,7 +329,7 @@ void LinkResolver::lookup_method_in_interfaces(methodHandle& result, KlassHandle
// Specify 'true' in order to skip default methods when searching the
// interfaces. Function lookup_method_in_klasses() already looked for
// the method in the default methods table.
- result = methodHandle(THREAD, ik->lookup_method_in_all_interfaces(name, signature, true));
+ result = methodHandle(THREAD, ik->lookup_method_in_all_interfaces(name, signature, Klass::skip_defaults));
}
void LinkResolver::lookup_polymorphic_method(methodHandle& result,
diff --git a/src/share/vm/oops/arrayKlass.cpp b/src/share/vm/oops/arrayKlass.cpp
index fcb46b11f..c55992f07 100644
--- a/src/share/vm/oops/arrayKlass.cpp
+++ b/src/share/vm/oops/arrayKlass.cpp
@@ -64,10 +64,10 @@ oop ArrayKlass::multi_allocate(int rank, jint* sizes, TRAPS) {
return NULL;
}
-Method* ArrayKlass::uncached_lookup_method(Symbol* name, Symbol* signature) const {
+Method* ArrayKlass::uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode 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);
+ return super()->uncached_lookup_method(name, signature, mode);
}
ArrayKlass::ArrayKlass(Symbol* name) {
diff --git a/src/share/vm/oops/arrayKlass.hpp b/src/share/vm/oops/arrayKlass.hpp
index 7b4ad2e9a..f42d96e16 100644
--- a/src/share/vm/oops/arrayKlass.hpp
+++ b/src/share/vm/oops/arrayKlass.hpp
@@ -86,7 +86,7 @@ class ArrayKlass: public Klass {
objArrayOop allocate_arrayArray(int n, int length, TRAPS);
// Lookup operations
- Method* uncached_lookup_method(Symbol* name, Symbol* signature) const;
+ Method* uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode mode) const;
// Casting from Klass*
static ArrayKlass* cast(Klass* k) {
diff --git a/src/share/vm/oops/instanceKlass.cpp b/src/share/vm/oops/instanceKlass.cpp
index 76d14e492..4785462a4 100644
--- a/src/share/vm/oops/instanceKlass.cpp
+++ b/src/share/vm/oops/instanceKlass.cpp
@@ -1429,7 +1429,11 @@ static int binary_search(Array<Method*>* methods, Symbol* name) {
// find_method looks up the name/signature in the local methods array
Method* InstanceKlass::find_method(Symbol* name, Symbol* signature) const {
- return InstanceKlass::find_method(methods(), name, signature);
+ return find_method_impl(name, signature, false);
+}
+
+Method* InstanceKlass::find_method_impl(Symbol* name, Symbol* signature, bool skipping_overpass) const {
+ return InstanceKlass::find_method_impl(methods(), name, signature, skipping_overpass);
}
// find_instance_method looks up the name/signature in the local methods array
@@ -1446,40 +1450,49 @@ Method* InstanceKlass::find_instance_method(
// find_method looks up the name/signature in the local methods array
Method* InstanceKlass::find_method(
Array<Method*>* methods, Symbol* name, Symbol* signature) {
- int hit = find_method_index(methods, name, signature);
+ return InstanceKlass::find_method_impl(methods, name, signature, 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);
return hit >= 0 ? methods->at(hit): NULL;
}
// 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
-// of the matching name/signature
+// of the matching name/signature. If, overpass methods are being ignored,
+// the search continues to find a potential non-overpass match. This capability
+// 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) {
+ Array<Method*>* methods, Symbol* name, Symbol* signature, bool skipping_overpass) {
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
- if (m->signature() == signature) return hit;
+ // for common case, ignoring overpasses if requested.
+ if ((m->signature() == signature) && (!skipping_overpass || !m->is_overpass())) return hit;
+
// search downwards through overloaded methods
int i;
for (i = hit - 1; i >= 0; --i) {
Method* m = methods->at(i);
assert(m->is_method(), "must be method");
if (m->name() != name) break;
- if (m->signature() == signature) return i;
+ if ((m->signature() == signature) && (!skipping_overpass || !m->is_overpass())) 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) return i;
+ if ((m->signature() == signature) && (!skipping_overpass || !m->is_overpass())) return i;
}
// not found
#ifdef ASSERT
- int index = linear_search(methods, name, signature);
+ int index = skipping_overpass ? -1 : linear_search(methods, name, signature);
assert(index == -1, err_msg("binary search should have found entry %d", index));
#endif
}
@@ -1505,16 +1518,16 @@ int InstanceKlass::find_method_by_name(
// 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) const {
+Method* InstanceKlass::uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode mode) const {
+ MethodLookupMode lookup_mode = mode;
Klass* klass = const_cast<InstanceKlass*>(this);
- bool dont_ignore_overpasses = true; // For the class being searched, find its overpasses.
while (klass != NULL) {
- Method* method = InstanceKlass::cast(klass)->find_method(name, signature);
- if ((method != NULL) && (dont_ignore_overpasses || !method->is_overpass())) {
+ Method* method = InstanceKlass::cast(klass)->find_method_impl(name, signature, (lookup_mode == skip_overpass));
+ if (method != NULL) {
return method;
}
klass = InstanceKlass::cast(klass)->super();
- dont_ignore_overpasses = false; // Ignore overpass methods in all superclasses.
+ lookup_mode = skip_overpass; // Always ignore overpass methods in superclasses
}
return NULL;
}
@@ -1529,7 +1542,7 @@ Method* InstanceKlass::lookup_method_in_ordered_interfaces(Symbol* name,
}
// Look up interfaces
if (m == NULL) {
- m = lookup_method_in_all_interfaces(name, signature, false);
+ m = lookup_method_in_all_interfaces(name, signature, normal);
}
return m;
}
@@ -1539,7 +1552,7 @@ Method* InstanceKlass::lookup_method_in_ordered_interfaces(Symbol* name,
// They should only be found in the initial InterfaceMethodRef
Method* InstanceKlass::lookup_method_in_all_interfaces(Symbol* name,
Symbol* signature,
- bool skip_default_methods) const {
+ MethodLookupMode mode) const {
Array<Klass*>* all_ifs = transitive_interfaces();
int num_ifs = all_ifs->length();
InstanceKlass *ik = NULL;
@@ -1547,7 +1560,7 @@ Method* InstanceKlass::lookup_method_in_all_interfaces(Symbol* name,
ik = InstanceKlass::cast(all_ifs->at(i));
Method* m = ik->lookup_method(name, signature);
if (m != NULL && m->is_public() && !m->is_static() &&
- (!skip_default_methods || !m->is_default_method())) {
+ ((mode != skip_defaults) || !m->is_default_method())) {
return m;
}
}
diff --git a/src/share/vm/oops/instanceKlass.hpp b/src/share/vm/oops/instanceKlass.hpp
index 4c5bb4c44..31e5accf2 100644
--- a/src/share/vm/oops/instanceKlass.hpp
+++ b/src/share/vm/oops/instanceKlass.hpp
@@ -518,14 +518,14 @@ class InstanceKlass: public Klass {
static Method* find_instance_method(Array<Method*>* methods, Symbol* name, Symbol* signature);
// 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);
+ static int find_method_index(Array<Method*>* methods, Symbol* name, Symbol* signature, bool skipping_overpass);
// lookup operation (returns NULL if not found)
- Method* uncached_lookup_method(Symbol* name, Symbol* signature) const;
+ Method* uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode 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, bool skip_default_methods) const;
+ Method* lookup_method_in_all_interfaces(Symbol* name, Symbol* signature, MethodLookupMode mode) const;
// lookup a method in local defaults then in all interfaces
// (returns NULL if not found)
@@ -1048,6 +1048,10 @@ private:
// Returns the array class with this class as element type
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<Method*>* methods, Symbol* name, Symbol* signature, bool skipping_overpass);
+
// Free CHeap allocated fields.
void release_C_heap_structures();
public:
diff --git a/src/share/vm/oops/klass.cpp b/src/share/vm/oops/klass.cpp
index fdf6a750d..2e8ef6f8f 100644
--- a/src/share/vm/oops/klass.cpp
+++ b/src/share/vm/oops/klass.cpp
@@ -129,7 +129,7 @@ bool Klass::compute_is_subtype_of(Klass* k) {
}
-Method* Klass::uncached_lookup_method(Symbol* name, Symbol* signature) const {
+Method* Klass::uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode mode) const {
#ifdef ASSERT
tty->print_cr("Error: uncached_lookup_method called on a klass oop."
" Likely error: reflection method does not correctly"
diff --git a/src/share/vm/oops/klass.hpp b/src/share/vm/oops/klass.hpp
index a31a23573..0d9dbcee5 100644
--- a/src/share/vm/oops/klass.hpp
+++ b/src/share/vm/oops/klass.hpp
@@ -182,6 +182,8 @@ class Klass : public Metadata {
void* operator new(size_t size, ClassLoaderData* loader_data, size_t word_size, TRAPS) throw();
public:
+ enum MethodLookupMode { normal, skip_overpass, skip_defaults };
+
bool is_klass() const volatile { return true; }
// super
@@ -421,10 +423,10 @@ class Klass : public Metadata {
virtual void initialize(TRAPS);
// lookup operation for MethodLookupCache
friend class MethodLookupCache;
- virtual Method* uncached_lookup_method(Symbol* name, Symbol* signature) const;
+ virtual Method* uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode mode) const;
public:
Method* lookup_method(Symbol* name, Symbol* signature) const {
- return uncached_lookup_method(name, signature);
+ return uncached_lookup_method(name, signature, normal);
}
// array class with specific rank
diff --git a/src/share/vm/oops/klassVtable.cpp b/src/share/vm/oops/klassVtable.cpp
index a7fc062b7..ad185c7f1 100644
--- a/src/share/vm/oops/klassVtable.cpp
+++ b/src/share/vm/oops/klassVtable.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -622,7 +622,7 @@ bool klassVtable::needs_new_vtable_entry(methodHandle target_method,
// 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, false) != NULL) {
+ if (sk->lookup_method_in_all_interfaces(name, signature, Klass::normal) != NULL) {
return false; // found a matching miranda; we do not need a new entry
}
}
@@ -698,7 +698,7 @@ bool klassVtable::is_miranda(Method* m, Array<Method*>* class_methods,
&& mo->method_holder() != NULL
&& mo->method_holder()->super() != NULL)
{
- mo = mo->method_holder()->super()->uncached_lookup_method(name, signature);
+ mo = mo->method_holder()->super()->uncached_lookup_method(name, signature, Klass::normal);
}
if (mo == NULL || mo->access_flags().is_private() ) {
// super class hierarchy does not implement it or protection is different
@@ -743,7 +743,7 @@ void klassVtable::add_new_mirandas_to_lists(
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(), false) == NULL) {
+ if (sk->lookup_method_in_all_interfaces(im->name(), im->signature(), Klass::normal) == NULL) {
new_mirandas->append(im);
}
if (all_mirandas != NULL) {
diff --git a/src/share/vm/prims/jvm.cpp b/src/share/vm/prims/jvm.cpp
index 978679ac4..b7706304b 100644
--- a/src/share/vm/prims/jvm.cpp
+++ b/src/share/vm/prims/jvm.cpp
@@ -1217,7 +1217,8 @@ JVM_ENTRY(jobject, JVM_DoPrivileged(JNIEnv *env, jclass cls, jobject action, job
// get run() method
Method* m_oop = object->klass()->uncached_lookup_method(
vmSymbols::run_method_name(),
- vmSymbols::void_object_signature());
+ vmSymbols::void_object_signature(),
+ Klass::normal);
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 --git a/src/share/vm/prims/nativeLookup.cpp b/src/share/vm/prims/nativeLookup.cpp
index d30151326..188e7fce9 100644
--- a/src/share/vm/prims/nativeLookup.cpp
+++ b/src/share/vm/prims/nativeLookup.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -408,7 +408,7 @@ address NativeLookup::base_library_lookup(const char* class_name, const char* me
// Find method and invoke standard lookup
methodHandle method (THREAD,
- klass->uncached_lookup_method(m_name, s_name));
+ klass->uncached_lookup_method(m_name, s_name, Klass::normal));
address result = lookup(method, in_base_library, CATCH);
assert(in_base_library, "must be in basic library");
guarantee(result != NULL, "must be non NULL");