8200238: Reduce number of exceptions created when calling MemberName$Factory::resolveOrNull

Reviewed-by: lfoltan, acorn, dholmes
This commit is contained in:
Claes Redestad 2018-03-29 10:38:29 +02:00
parent dea1bcd6e8
commit 243b2364f6
5 changed files with 35 additions and 13 deletions

View file

@ -2794,7 +2794,7 @@ Handle SystemDictionary::link_method_handle_constant(Klass* caller,
// which MemberName resolution doesn't handle. There's special logic on JDK side to handle them // which MemberName resolution doesn't handle. There's special logic on JDK side to handle them
// (see MethodHandles.linkMethodHandleConstant() and MethodHandles.findVirtualForMH()). // (see MethodHandles.linkMethodHandleConstant() and MethodHandles.findVirtualForMH()).
} else { } else {
MethodHandles::resolve_MemberName(mname, caller, CHECK_(empty)); MethodHandles::resolve_MemberName(mname, caller, /*speculative_resolve*/false, CHECK_(empty));
} }
// After method/field resolution succeeded, it's safe to resolve MH signature as well. // After method/field resolution succeeded, it's safe to resolve MH signature as well.

View file

@ -306,7 +306,7 @@ oop MethodHandles::init_method_MemberName(Handle mname, CallInfo& info) {
Handle resolved_method = info.resolved_method_name(); Handle resolved_method = info.resolved_method_name();
assert(java_lang_invoke_ResolvedMethodName::vmtarget(resolved_method()) == m(), assert(java_lang_invoke_ResolvedMethodName::vmtarget(resolved_method()) == m(),
"Should not change after link resolultion"); "Should not change after link resolution");
oop mname_oop = mname(); oop mname_oop = mname();
java_lang_invoke_MemberName::set_flags (mname_oop, flags); java_lang_invoke_MemberName::set_flags (mname_oop, flags);
@ -682,7 +682,8 @@ oop MethodHandles::field_signature_type_or_null(Symbol* s) {
// An unresolved member name is a mere symbolic reference. // An unresolved member name is a mere symbolic reference.
// Resolving it plants a vmtarget/vmindex in it, // Resolving it plants a vmtarget/vmindex in it,
// which refers directly to JVM internals. // which refers directly to JVM internals.
Handle MethodHandles::resolve_MemberName(Handle mname, Klass* caller, TRAPS) { Handle MethodHandles::resolve_MemberName(Handle mname, Klass* caller,
bool speculative_resolve, TRAPS) {
Handle empty; Handle empty;
assert(java_lang_invoke_MemberName::is_instance(mname()), ""); assert(java_lang_invoke_MemberName::is_instance(mname()), "");
@ -781,6 +782,9 @@ Handle MethodHandles::resolve_MemberName(Handle mname, Klass* caller, TRAPS) {
assert(false, "ref_kind=%d", ref_kind); assert(false, "ref_kind=%d", ref_kind);
} }
if (HAS_PENDING_EXCEPTION) { if (HAS_PENDING_EXCEPTION) {
if (speculative_resolve) {
CLEAR_PENDING_EXCEPTION;
}
return empty; return empty;
} }
} }
@ -806,6 +810,9 @@ Handle MethodHandles::resolve_MemberName(Handle mname, Klass* caller, TRAPS) {
break; // will throw after end of switch break; // will throw after end of switch
} }
if (HAS_PENDING_EXCEPTION) { if (HAS_PENDING_EXCEPTION) {
if (speculative_resolve) {
CLEAR_PENDING_EXCEPTION;
}
return empty; return empty;
} }
} }
@ -822,6 +829,9 @@ Handle MethodHandles::resolve_MemberName(Handle mname, Klass* caller, TRAPS) {
LinkInfo link_info(defc, name, type, caller, LinkInfo::skip_access_check); LinkInfo link_info(defc, name, type, caller, LinkInfo::skip_access_check);
LinkResolver::resolve_field(result, link_info, Bytecodes::_nop, false, THREAD); LinkResolver::resolve_field(result, link_info, Bytecodes::_nop, false, THREAD);
if (HAS_PENDING_EXCEPTION) { if (HAS_PENDING_EXCEPTION) {
if (speculative_resolve) {
CLEAR_PENDING_EXCEPTION;
}
return empty; return empty;
} }
} }
@ -1187,7 +1197,8 @@ JVM_ENTRY(void, MHN_expand_Mem(JNIEnv *env, jobject igcls, jobject mname_jh)) {
JVM_END JVM_END
// void resolve(MemberName self, Class<?> caller) // void resolve(MemberName self, Class<?> caller)
JVM_ENTRY(jobject, MHN_resolve_Mem(JNIEnv *env, jobject igcls, jobject mname_jh, jclass caller_jh)) { JVM_ENTRY(jobject, MHN_resolve_Mem(JNIEnv *env, jobject igcls, jobject mname_jh, jclass caller_jh,
jboolean speculative_resolve)) {
if (mname_jh == NULL) { THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), "mname is null"); } if (mname_jh == NULL) { THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), "mname is null"); }
Handle mname(THREAD, JNIHandles::resolve_non_null(mname_jh)); Handle mname(THREAD, JNIHandles::resolve_non_null(mname_jh));
@ -1215,7 +1226,8 @@ JVM_ENTRY(jobject, MHN_resolve_Mem(JNIEnv *env, jobject igcls, jobject mname_jh,
Klass* caller = caller_jh == NULL ? NULL : Klass* caller = caller_jh == NULL ? NULL :
java_lang_Class::as_Klass(JNIHandles::resolve_non_null(caller_jh)); java_lang_Class::as_Klass(JNIHandles::resolve_non_null(caller_jh));
Handle resolved = MethodHandles::resolve_MemberName(mname, caller, CHECK_NULL); Handle resolved = MethodHandles::resolve_MemberName(mname, caller, speculative_resolve,
CHECK_NULL);
if (resolved.is_null()) { if (resolved.is_null()) {
int flags = java_lang_invoke_MemberName::flags(mname()); int flags = java_lang_invoke_MemberName::flags(mname());
@ -1223,6 +1235,10 @@ JVM_ENTRY(jobject, MHN_resolve_Mem(JNIEnv *env, jobject igcls, jobject mname_jh,
if (!MethodHandles::ref_kind_is_valid(ref_kind)) { if (!MethodHandles::ref_kind_is_valid(ref_kind)) {
THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), "obsolete MemberName format"); THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), "obsolete MemberName format");
} }
if (speculative_resolve) {
assert(!HAS_PENDING_EXCEPTION, "No exceptions expected when resolving speculatively");
return NULL;
}
if ((flags & ALL_KINDS) == IS_FIELD) { if ((flags & ALL_KINDS) == IS_FIELD) {
THROW_MSG_NULL(vmSymbols::java_lang_NoSuchFieldError(), "field resolution failed"); THROW_MSG_NULL(vmSymbols::java_lang_NoSuchFieldError(), "field resolution failed");
} else if ((flags & ALL_KINDS) == IS_METHOD || } else if ((flags & ALL_KINDS) == IS_METHOD ||
@ -1514,7 +1530,7 @@ JVM_END
static JNINativeMethod MHN_methods[] = { static JNINativeMethod MHN_methods[] = {
{CC "init", CC "(" MEM "" OBJ ")V", FN_PTR(MHN_init_Mem)}, {CC "init", CC "(" MEM "" OBJ ")V", FN_PTR(MHN_init_Mem)},
{CC "expand", CC "(" MEM ")V", FN_PTR(MHN_expand_Mem)}, {CC "expand", CC "(" MEM ")V", FN_PTR(MHN_expand_Mem)},
{CC "resolve", CC "(" MEM "" CLS ")" MEM, FN_PTR(MHN_resolve_Mem)}, {CC "resolve", CC "(" MEM "" CLS "Z)" MEM, FN_PTR(MHN_resolve_Mem)},
// static native int getNamedCon(int which, Object[] name) // static native int getNamedCon(int which, Object[] name)
{CC "getNamedCon", CC "(I[" OBJ ")I", FN_PTR(MHN_getNamedCon)}, {CC "getNamedCon", CC "(I[" OBJ ")I", FN_PTR(MHN_getNamedCon)},
// static native int getMembers(Class<?> defc, String matchName, String matchSig, // static native int getMembers(Class<?> defc, String matchName, String matchSig,

View file

@ -61,7 +61,8 @@ class MethodHandles: AllStatic {
public: public:
// working with member names // working with member names
static Handle resolve_MemberName(Handle mname, Klass* caller, TRAPS); // compute vmtarget/vmindex from name/type static Handle resolve_MemberName(Handle mname, Klass* caller,
bool speculative_resolve, TRAPS); // compute vmtarget/vmindex from name/type
static void expand_MemberName(Handle mname, int suppress, TRAPS); // expand defc/name/type if missing static void expand_MemberName(Handle mname, int suppress, TRAPS); // expand defc/name/type if missing
static oop init_MemberName(Handle mname_h, Handle target_h, TRAPS); // compute vmtarget/vmindex from target static oop init_MemberName(Handle mname_h, Handle target_h, TRAPS); // compute vmtarget/vmindex from target
static oop init_field_MemberName(Handle mname_h, fieldDescriptor& fd, bool is_setter = false); static oop init_field_MemberName(Handle mname_h, fieldDescriptor& fd, bool is_setter = false);

View file

@ -1047,7 +1047,8 @@ import static java.lang.invoke.MethodHandleStatics.newInternalError;
* If lookup fails or access is not permitted, null is returned. * If lookup fails or access is not permitted, null is returned.
* Otherwise a fresh copy of the given member is returned, with modifier bits filled in. * Otherwise a fresh copy of the given member is returned, with modifier bits filled in.
*/ */
private MemberName resolve(byte refKind, MemberName ref, Class<?> lookupClass) { private MemberName resolve(byte refKind, MemberName ref, Class<?> lookupClass,
boolean speculativeResolve) {
MemberName m = ref.clone(); // JVM will side-effect the ref MemberName m = ref.clone(); // JVM will side-effect the ref
assert(refKind == m.getReferenceKind()); assert(refKind == m.getReferenceKind());
try { try {
@ -1066,7 +1067,10 @@ import static java.lang.invoke.MethodHandleStatics.newInternalError;
// //
// REFC view on PTYPES doesn't matter, since it is used only as a starting point for resolution and doesn't // REFC view on PTYPES doesn't matter, since it is used only as a starting point for resolution and doesn't
// participate in method selection. // participate in method selection.
m = MethodHandleNatives.resolve(m, lookupClass); m = MethodHandleNatives.resolve(m, lookupClass, speculativeResolve);
if (m == null && speculativeResolve) {
return null;
}
m.checkForTypeAlias(m.getDeclaringClass()); m.checkForTypeAlias(m.getDeclaringClass());
m.resolution = null; m.resolution = null;
} catch (ClassNotFoundException | LinkageError ex) { } catch (ClassNotFoundException | LinkageError ex) {
@ -1091,7 +1095,7 @@ import static java.lang.invoke.MethodHandleStatics.newInternalError;
MemberName resolveOrFail(byte refKind, MemberName m, Class<?> lookupClass, MemberName resolveOrFail(byte refKind, MemberName m, Class<?> lookupClass,
Class<NoSuchMemberException> nsmClass) Class<NoSuchMemberException> nsmClass)
throws IllegalAccessException, NoSuchMemberException { throws IllegalAccessException, NoSuchMemberException {
MemberName result = resolve(refKind, m, lookupClass); MemberName result = resolve(refKind, m, lookupClass, false);
if (result.isResolved()) if (result.isResolved())
return result; return result;
ReflectiveOperationException ex = result.makeAccessException(); ReflectiveOperationException ex = result.makeAccessException();
@ -1106,8 +1110,8 @@ import static java.lang.invoke.MethodHandleStatics.newInternalError;
*/ */
public public
MemberName resolveOrNull(byte refKind, MemberName m, Class<?> lookupClass) { MemberName resolveOrNull(byte refKind, MemberName m, Class<?> lookupClass) {
MemberName result = resolve(refKind, m, lookupClass); MemberName result = resolve(refKind, m, lookupClass, true);
if (result.isResolved()) if (result != null && result.isResolved())
return result; return result;
return null; return null;
} }

View file

@ -49,7 +49,8 @@ class MethodHandleNatives {
static native void init(MemberName self, Object ref); static native void init(MemberName self, Object ref);
static native void expand(MemberName self); static native void expand(MemberName self);
static native MemberName resolve(MemberName self, Class<?> caller) throws LinkageError, ClassNotFoundException; static native MemberName resolve(MemberName self, Class<?> caller,
boolean speculativeResolve) throws LinkageError, ClassNotFoundException;
static native int getMembers(Class<?> defc, String matchName, String matchSig, static native int getMembers(Class<?> defc, String matchName, String matchSig,
int matchFlags, Class<?> caller, int skip, MemberName[] results); int matchFlags, Class<?> caller, int skip, MemberName[] results);