2486 // TO DO: expand at least some of the MemberNames, to avoid massive callbacks |
2486 // TO DO: expand at least some of the MemberNames, to avoid massive callbacks |
2487 return res; |
2487 return res; |
2488 } |
2488 } |
2489 JVM_END |
2489 JVM_END |
2490 |
2490 |
2491 JVM_ENTRY(void, MHN_registerBootstrap(JNIEnv *env, jobject igcls, jclass caller_jh, jobject bsm_jh)) { |
|
2492 instanceKlassHandle ik = MethodHandles::resolve_instance_klass(caller_jh, THREAD); |
|
2493 if (!AllowTransitionalJSR292) { |
|
2494 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), |
|
2495 "registerBootstrapMethod is only supported in JSR 292 EDR"); |
|
2496 } |
|
2497 ik->link_class(CHECK); |
|
2498 if (!java_lang_invoke_MethodHandle::is_instance(JNIHandles::resolve(bsm_jh))) { |
|
2499 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "method handle"); |
|
2500 } |
|
2501 const char* err = NULL; |
|
2502 if (ik->is_initialized() || ik->is_in_error_state()) { |
|
2503 err = "too late: class is already initialized"; |
|
2504 } else { |
|
2505 ObjectLocker ol(ik, THREAD); // note: this should be a recursive lock |
|
2506 if (ik->is_not_initialized() || |
|
2507 (ik->is_being_initialized() && ik->is_reentrant_initialization(THREAD))) { |
|
2508 if (ik->bootstrap_method() != NULL) { |
|
2509 err = "class is already equipped with a bootstrap method"; |
|
2510 } else { |
|
2511 ik->set_bootstrap_method(JNIHandles::resolve_non_null(bsm_jh)); |
|
2512 err = NULL; |
|
2513 } |
|
2514 } else { |
|
2515 err = "class is already initialized"; |
|
2516 if (ik->is_being_initialized()) |
|
2517 err = "class is already being initialized in a different thread"; |
|
2518 } |
|
2519 } |
|
2520 if (err != NULL) { |
|
2521 THROW_MSG(vmSymbols::java_lang_IllegalStateException(), err); |
|
2522 } |
|
2523 } |
|
2524 JVM_END |
|
2525 |
|
2526 JVM_ENTRY(jobject, MHN_getBootstrap(JNIEnv *env, jobject igcls, jclass caller_jh)) { |
|
2527 if (!AllowTransitionalJSR292) |
|
2528 THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), "getBootstrap: transitional only"); |
|
2529 instanceKlassHandle ik = MethodHandles::resolve_instance_klass(caller_jh, THREAD); |
|
2530 return JNIHandles::make_local(THREAD, ik->bootstrap_method()); |
|
2531 } |
|
2532 JVM_END |
|
2533 |
|
2534 JVM_ENTRY(void, MHN_setCallSiteTarget(JNIEnv *env, jobject igcls, jobject site_jh, jobject target_jh)) { |
|
2535 if (!AllowTransitionalJSR292) |
|
2536 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "setCallSite: transitional only"); |
|
2537 } |
|
2538 JVM_END |
|
2539 |
|
2540 |
2491 |
2541 /// JVM_RegisterMethodHandleMethods |
2492 /// JVM_RegisterMethodHandleMethods |
2542 |
2493 |
2543 #define LANG "Ljava/lang/" |
2494 #define LANG "Ljava/lang/" |
2544 #define JLINV "Ljava/lang/invoke/" /* standard package */ |
2495 #define JLINV "Ljava/lang/invoke/" |
2545 #define JDYN "Ljava/dyn/" /* alternative package to JLINV if AllowTransitionalJSR292 */ |
|
2546 #define IDYN "Lsun/dyn/" /* alternative package to JDYN if AllowTransitionalJSR292 */ |
|
2547 // FIXME: After AllowTransitionalJSR292 is removed, replace JDYN and IDYN by JLINV. |
|
2548 |
2496 |
2549 #define OBJ LANG"Object;" |
2497 #define OBJ LANG"Object;" |
2550 #define CLS LANG"Class;" |
2498 #define CLS LANG"Class;" |
2551 #define STRG LANG"String;" |
2499 #define STRG LANG"String;" |
2552 #define CST JDYN"CallSite;" |
2500 #define MT JLINV"MethodType;" |
2553 #define MT JDYN"MethodType;" |
2501 #define MH JLINV"MethodHandle;" |
2554 #define MH JDYN"MethodHandle;" |
2502 #define MEM JLINV"MemberName;" |
2555 #define MEM IDYN"MemberName;" |
2503 #define AMH JLINV"AdapterMethodHandle;" |
2556 #define AMH IDYN"AdapterMethodHandle;" |
2504 #define BMH JLINV"BoundMethodHandle;" |
2557 #define BMH IDYN"BoundMethodHandle;" |
2505 #define DMH JLINV"DirectMethodHandle;" |
2558 #define DMH IDYN"DirectMethodHandle;" |
|
2559 |
2506 |
2560 #define CC (char*) /*cast a literal from (const char*)*/ |
2507 #define CC (char*) /*cast a literal from (const char*)*/ |
2561 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f) |
2508 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f) |
2562 |
2509 |
2563 // These are the native methods on sun.invoke.MethodHandleNatives. |
2510 // These are the native methods on sun.invoke.MethodHandleNatives. |
2577 // static native int getMembers(Class<?> defc, String matchName, String matchSig, |
2524 // static native int getMembers(Class<?> defc, String matchName, String matchSig, |
2578 // int matchFlags, Class<?> caller, int skip, MemberName[] results); |
2525 // int matchFlags, Class<?> caller, int skip, MemberName[] results); |
2579 {CC"getMembers", CC"("CLS""STRG""STRG"I"CLS"I["MEM")I", FN_PTR(MHN_getMembers)} |
2526 {CC"getMembers", CC"("CLS""STRG""STRG"I"CLS"I["MEM")I", FN_PTR(MHN_getMembers)} |
2580 }; |
2527 }; |
2581 |
2528 |
2582 // FIXME: Remove methods2 after AllowTransitionalJSR292 is removed. |
|
2583 static JNINativeMethod methods2[] = { |
|
2584 {CC"registerBootstrap", CC"("CLS MH")V", FN_PTR(MHN_registerBootstrap)}, |
|
2585 {CC"getBootstrap", CC"("CLS")"MH, FN_PTR(MHN_getBootstrap)}, |
|
2586 {CC"setCallSiteTarget", CC"("CST MH")V", FN_PTR(MHN_setCallSiteTarget)} |
|
2587 }; |
|
2588 |
|
2589 static void hack_signatures(JNINativeMethod* methods, jint num_methods, const char* from_sig, const char* to_sig) { |
|
2590 for (int i = 0; i < num_methods; i++) { |
|
2591 const char* sig = methods[i].signature; |
|
2592 if (!strstr(sig, from_sig)) continue; |
|
2593 size_t buflen = strlen(sig) + 100; |
|
2594 char* buf = NEW_C_HEAP_ARRAY(char, buflen); |
|
2595 char* bufp = buf; |
|
2596 const char* sigp = sig; |
|
2597 size_t from_len = strlen(from_sig), to_len = strlen(to_sig); |
|
2598 while (*sigp != '\0') { |
|
2599 assert(bufp < buf + buflen - to_len - 1, "oob"); |
|
2600 if (strncmp(sigp, from_sig, from_len) != 0) { |
|
2601 *bufp++ = *sigp++; |
|
2602 } else { |
|
2603 strcpy(bufp, to_sig); |
|
2604 bufp += to_len; |
|
2605 sigp += from_len; |
|
2606 } |
|
2607 } |
|
2608 *bufp = '\0'; |
|
2609 methods[i].signature = buf; // replace with new signature |
|
2610 if (TraceMethodHandles) |
|
2611 tty->print_cr("MethodHandleNatives: %s: change signature %s => %s", methods[i].name, sig, buf); |
|
2612 } |
|
2613 } |
|
2614 |
|
2615 // This one function is exported, used by NativeLookup. |
2529 // This one function is exported, used by NativeLookup. |
2616 |
2530 |
2617 JVM_ENTRY(void, JVM_RegisterMethodHandleMethods(JNIEnv *env, jclass MHN_class)) { |
2531 JVM_ENTRY(void, JVM_RegisterMethodHandleMethods(JNIEnv *env, jclass MHN_class)) { |
2618 assert(MethodHandles::spot_check_entry_names(), "entry enum is OK"); |
2532 assert(MethodHandles::spot_check_entry_names(), "entry enum is OK"); |
2619 |
2533 |
2620 if (!EnableInvokeDynamic) { |
2534 if (!EnableInvokeDynamic) { |
2621 warning("JSR 292 is disabled in this JVM. Use -XX:+UnlockDiagnosticVMOptions -XX:+EnableInvokeDynamic to enable."); |
2535 warning("JSR 292 is disabled in this JVM. Use -XX:+UnlockDiagnosticVMOptions -XX:+EnableInvokeDynamic to enable."); |
2622 return; // bind nothing |
2536 return; // bind nothing |
2623 } |
2537 } |
2624 |
2538 |
2625 if (SystemDictionary::MethodHandleNatives_klass() != NULL && |
|
2626 SystemDictionary::MethodHandleNatives_klass() != java_lang_Class::as_klassOop(JNIHandles::resolve(MHN_class))) { |
|
2627 warning("multiple versions of MethodHandleNatives in boot classpath; consider using -XX:+PreferTransitionalJSR292"); |
|
2628 THROW_MSG(vmSymbols::java_lang_InternalError(), "multiple versions of MethodHandleNatives in boot classpath; consider using -XX:+PreferTransitionalJSR292"); |
|
2629 } |
|
2630 |
|
2631 bool enable_MH = true; |
2539 bool enable_MH = true; |
2632 |
2540 |
2633 // Loop control. FIXME: Replace by dead reckoning after AllowTransitionalJSR292 is removed. |
2541 { |
2634 bool registered_natives = false; |
|
2635 bool try_plain = true, try_JDYN = true, try_IDYN = true; |
|
2636 for (;;) { |
|
2637 ThreadToNativeFromVM ttnfv(thread); |
2542 ThreadToNativeFromVM ttnfv(thread); |
2638 |
2543 |
2639 if (try_plain) { try_plain = false; } |
|
2640 else if (try_JDYN) { try_JDYN = false; hack_signatures(methods, sizeof(methods)/sizeof(JNINativeMethod), IDYN, JDYN); } |
|
2641 else if (try_IDYN) { try_IDYN = false; hack_signatures(methods, sizeof(methods)/sizeof(JNINativeMethod), JDYN, JLINV); } |
|
2642 else { break; } |
|
2643 int status = env->RegisterNatives(MHN_class, methods, sizeof(methods)/sizeof(JNINativeMethod)); |
2544 int status = env->RegisterNatives(MHN_class, methods, sizeof(methods)/sizeof(JNINativeMethod)); |
2644 if (env->ExceptionOccurred()) { |
2545 if (env->ExceptionOccurred()) { |
|
2546 MethodHandles::set_enabled(false); |
|
2547 warning("JSR 292 method handle code is mismatched to this JVM. Disabling support."); |
|
2548 enable_MH = false; |
2645 env->ExceptionClear(); |
2549 env->ExceptionClear(); |
2646 // and try again... |
2550 } |
2647 } else { |
|
2648 registered_natives = true; |
|
2649 break; |
|
2650 } |
|
2651 } |
|
2652 if (!registered_natives) { |
|
2653 MethodHandles::set_enabled(false); |
|
2654 warning("JSR 292 method handle code is mismatched to this JVM. Disabling support."); |
|
2655 enable_MH = false; |
|
2656 } |
2551 } |
2657 |
2552 |
2658 if (enable_MH) { |
2553 if (enable_MH) { |
2659 bool found_raise_exception = false; |
|
2660 KlassHandle MHN_klass = SystemDictionaryHandles::MethodHandleNatives_klass(); |
2554 KlassHandle MHN_klass = SystemDictionaryHandles::MethodHandleNatives_klass(); |
2661 KlassHandle MHI_klass = SystemDictionaryHandles::MethodHandleImpl_klass(); |
2555 if (MHN_klass.not_null()) { |
2662 // Loop control. FIXME: Replace by dead reckoning after AllowTransitionalJSR292 is removed. |
|
2663 bool try_MHN = true, try_MHI = AllowTransitionalJSR292; |
|
2664 for (;;) { |
|
2665 KlassHandle try_klass; |
|
2666 if (try_MHN) { try_MHN = false; try_klass = MHN_klass; } |
|
2667 else if (try_MHI) { try_MHI = false; try_klass = MHI_klass; } |
|
2668 else { break; } |
|
2669 if (try_klass.is_null()) continue; |
|
2670 TempNewSymbol raiseException_name = SymbolTable::new_symbol("raiseException", CHECK); |
2556 TempNewSymbol raiseException_name = SymbolTable::new_symbol("raiseException", CHECK); |
2671 TempNewSymbol raiseException_sig = SymbolTable::new_symbol("(ILjava/lang/Object;Ljava/lang/Object;)V", CHECK); |
2557 TempNewSymbol raiseException_sig = SymbolTable::new_symbol("(ILjava/lang/Object;Ljava/lang/Object;)V", CHECK); |
2672 methodOop raiseException_method = instanceKlass::cast(try_klass->as_klassOop()) |
2558 methodOop raiseException_method = instanceKlass::cast(MHN_klass->as_klassOop()) |
2673 ->find_method(raiseException_name, raiseException_sig); |
2559 ->find_method(raiseException_name, raiseException_sig); |
2674 if (raiseException_method != NULL && raiseException_method->is_static()) { |
2560 if (raiseException_method != NULL && raiseException_method->is_static()) { |
2675 MethodHandles::set_raise_exception_method(raiseException_method); |
2561 MethodHandles::set_raise_exception_method(raiseException_method); |
2676 found_raise_exception = true; |
2562 } else { |
2677 break; |
2563 warning("JSR 292 method handle code is mismatched to this JVM. Disabling support."); |
2678 } |
2564 enable_MH = false; |
2679 } |
2565 } |
2680 if (!found_raise_exception) { |
2566 } else { |
2681 warning("JSR 292 method handle code is mismatched to this JVM. Disabling support."); |
|
2682 enable_MH = false; |
2567 enable_MH = false; |
2683 } |
2568 } |
2684 } |
2569 } |
2685 |
2570 |
2686 if (enable_MH) { |
2571 if (enable_MH) { |
2687 if (AllowTransitionalJSR292) { |
|
2688 // We need to link the MethodHandleImpl klass before we generate |
|
2689 // the method handle adapters as the _raise_exception adapter uses |
|
2690 // one of its methods (and its c2i-adapter). |
|
2691 klassOop k = SystemDictionary::MethodHandleImpl_klass(); |
|
2692 if (k != NULL) { |
|
2693 instanceKlass* ik = instanceKlass::cast(k); |
|
2694 ik->link_class(CHECK); |
|
2695 } |
|
2696 } |
|
2697 |
|
2698 MethodHandles::generate_adapters(); |
2572 MethodHandles::generate_adapters(); |
2699 MethodHandles::set_enabled(true); |
2573 MethodHandles::set_enabled(true); |
2700 } |
2574 } |
2701 |
|
2702 if (AllowTransitionalJSR292) { |
|
2703 ThreadToNativeFromVM ttnfv(thread); |
|
2704 |
|
2705 int status = env->RegisterNatives(MHN_class, methods2, sizeof(methods2)/sizeof(JNINativeMethod)); |
|
2706 if (env->ExceptionOccurred()) { |
|
2707 // Don't do this, since it's too late: |
|
2708 // MethodHandles::set_enabled(false) |
|
2709 env->ExceptionClear(); |
|
2710 } |
|
2711 } |
|
2712 } |
2575 } |
2713 JVM_END |
2576 JVM_END |