7049415: Failure of resolution of sym.reference to the c.s.s. should be wrapped in BootstrapMethodError
Summary: Delegate invokedynamic linkage errors to MethodHandleNatives.raiseException.
Reviewed-by: never
--- a/hotspot/src/share/vm/classfile/systemDictionary.hpp Tue May 31 10:05:36 2011 -0700
+++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp Wed Jun 01 23:25:20 2011 -0700
@@ -152,6 +152,7 @@
template(DirectMethodHandle_klass, java_lang_invoke_DirectMethodHandle, Pre_JSR292) \
template(MethodType_klass, java_lang_invoke_MethodType, Pre_JSR292) \
template(MethodTypeForm_klass, java_lang_invoke_MethodTypeForm, Pre_JSR292) \
+ template(BootstrapMethodError_klass, java_lang_BootstrapMethodError, Pre_JSR292) \
template(WrongMethodTypeException_klass, java_lang_invoke_WrongMethodTypeException, Pre_JSR292) \
template(CallSite_klass, java_lang_invoke_CallSite, Pre_JSR292) \
/* Note: MethodHandle must be first, and CallSite last in group */ \
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp Tue May 31 10:05:36 2011 -0700
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp Wed Jun 01 23:25:20 2011 -0700
@@ -148,6 +148,7 @@
template(java_lang_InstantiationException, "java/lang/InstantiationException") \
template(java_lang_InstantiationError, "java/lang/InstantiationError") \
template(java_lang_InterruptedException, "java/lang/InterruptedException") \
+ template(java_lang_BootstrapMethodError, "java/lang/BootstrapMethodError") \
template(java_lang_LinkageError, "java/lang/LinkageError") \
template(java_lang_NegativeArraySizeException, "java/lang/NegativeArraySizeException") \
template(java_lang_NoSuchFieldException, "java/lang/NoSuchFieldException") \
--- a/hotspot/src/share/vm/interpreter/linkResolver.cpp Tue May 31 10:05:36 2011 -0700
+++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp Wed Jun 01 23:25:20 2011 -0700
@@ -1117,7 +1117,24 @@
// The extra MH receiver will be inserted into the stack on every call.
methodHandle resolved_method;
KlassHandle current_klass(THREAD, pool->pool_holder());
- lookup_implicit_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, CHECK);
+ lookup_implicit_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, THREAD);
+ if (HAS_PENDING_EXCEPTION) {
+ if (PENDING_EXCEPTION->is_a(SystemDictionary::BootstrapMethodError_klass())) {
+ // throw these guys, since they are already wrapped
+ return;
+ }
+ if (!PENDING_EXCEPTION->is_a(SystemDictionary::LinkageError_klass())) {
+ // intercept only LinkageErrors which might have failed to wrap
+ return;
+ }
+ // See the "Linking Exceptions" section for the invokedynamic instruction in the JVMS.
+ Handle ex(THREAD, PENDING_EXCEPTION);
+ CLEAR_PENDING_EXCEPTION;
+ oop bsme = Klass::cast(SystemDictionary::BootstrapMethodError_klass())->java_mirror();
+ MethodHandles::raise_exception(Bytecodes::_athrow, ex(), bsme, CHECK);
+ // java code should not return, but if it does throw out anyway
+ THROW(vmSymbols::java_lang_InternalError());
+ }
if (resolved_method.is_null()) {
THROW(vmSymbols::java_lang_InternalError());
}
--- a/hotspot/src/share/vm/prims/methodHandles.cpp Tue May 31 10:05:36 2011 -0700
+++ b/hotspot/src/share/vm/prims/methodHandles.cpp Wed Jun 01 23:25:20 2011 -0700
@@ -2970,6 +2970,45 @@
}
JVM_END
+methodOop MethodHandles::resolve_raise_exception_method(TRAPS) {
+ if (_raise_exception_method != NULL) {
+ // no need to do it twice
+ return raise_exception_method();
+ }
+ // LinkResolver::resolve_invokedynamic can reach this point
+ // because an invokedynamic has failed very early (7049415)
+ KlassHandle MHN_klass = SystemDictionaryHandles::MethodHandleNatives_klass();
+ if (MHN_klass.not_null()) {
+ TempNewSymbol raiseException_name = SymbolTable::new_symbol("raiseException", CHECK_NULL);
+ TempNewSymbol raiseException_sig = SymbolTable::new_symbol("(ILjava/lang/Object;Ljava/lang/Object;)V", CHECK_NULL);
+ methodOop raiseException_method = instanceKlass::cast(MHN_klass->as_klassOop())
+ ->find_method(raiseException_name, raiseException_sig);
+ if (raiseException_method != NULL && raiseException_method->is_static()) {
+ return raiseException_method;
+ }
+ }
+ // not found; let the caller deal with it
+ return NULL;
+}
+void MethodHandles::raise_exception(int code, oop actual, oop required, TRAPS) {
+ methodOop raiseException_method = resolve_raise_exception_method(CHECK);
+ if (raiseException_method != NULL &&
+ instanceKlass::cast(raiseException_method->method_holder())->is_not_initialized()) {
+ instanceKlass::cast(raiseException_method->method_holder())->initialize(CHECK);
+ // it had better be resolved by now, or maybe JSR 292 failed to load
+ raiseException_method = raise_exception_method();
+ }
+ if (raiseException_method == NULL) {
+ THROW_MSG(vmSymbols::java_lang_InternalError(), "no raiseException method");
+ }
+ JavaCallArguments args;
+ args.push_int(code);
+ args.push_oop(actual);
+ args.push_oop(required);
+ JavaValue result(T_VOID);
+ JavaCalls::call(&result, raiseException_method, &args, CHECK);
+}
+
JVM_ENTRY(jobject, MH_invoke_UOE(JNIEnv *env, jobject igmh, jobjectArray igargs)) {
TempNewSymbol UOE_name = SymbolTable::new_symbol("java/lang/UnsupportedOperationException", CHECK_NULL);
THROW_MSG_NULL(UOE_name, "MethodHandle.invoke cannot be invoked reflectively");
@@ -3059,19 +3098,11 @@
}
if (enable_MH) {
- KlassHandle MHN_klass = SystemDictionaryHandles::MethodHandleNatives_klass();
- if (MHN_klass.not_null()) {
- TempNewSymbol raiseException_name = SymbolTable::new_symbol("raiseException", CHECK);
- TempNewSymbol raiseException_sig = SymbolTable::new_symbol("(ILjava/lang/Object;Ljava/lang/Object;)V", CHECK);
- methodOop raiseException_method = instanceKlass::cast(MHN_klass->as_klassOop())
- ->find_method(raiseException_name, raiseException_sig);
- if (raiseException_method != NULL && raiseException_method->is_static()) {
- MethodHandles::set_raise_exception_method(raiseException_method);
- } else {
- warning("JSR 292 method handle code is mismatched to this JVM. Disabling support.");
- enable_MH = false;
- }
+ methodOop raiseException_method = MethodHandles::resolve_raise_exception_method(CHECK);
+ if (raiseException_method != NULL) {
+ MethodHandles::set_raise_exception_method(raiseException_method);
} else {
+ warning("JSR 292 method handle code is mismatched to this JVM. Disabling support.");
enable_MH = false;
}
}
--- a/hotspot/src/share/vm/prims/methodHandles.hpp Tue May 31 10:05:36 2011 -0700
+++ b/hotspot/src/share/vm/prims/methodHandles.hpp Wed Jun 01 23:25:20 2011 -0700
@@ -439,6 +439,9 @@
assert(_raise_exception_method == NULL, "");
_raise_exception_method = JNIHandles::make_global(Handle(rem));
}
+ static methodOop resolve_raise_exception_method(TRAPS);
+ // call raise_exception_method from C code:
+ static void raise_exception(int code, oop actual, oop required, TRAPS);
static jint adapter_conversion(int conv_op, BasicType src, BasicType dest,
int stack_move = 0, int vminfo = 0) {