Mercurial > hg > truffle
comparison src/share/vm/prims/methodHandles.cpp @ 2356:72dee110246f
6839872: remove implementation inheritance from JSR 292 APIs
Summary: consolidate runtime support in java.dyn.MethodHandleNatives; include transitional compatibility logic
Reviewed-by: twisti
author | jrose |
---|---|
date | Fri, 11 Mar 2011 22:33:47 -0800 |
parents | 3582bf76420e |
children | 8033953d67ff |
comparison
equal
deleted
inserted
replaced
2355:799d8ccf63cf | 2356:72dee110246f |
---|---|
2521 } | 2521 } |
2522 } | 2522 } |
2523 JVM_END | 2523 JVM_END |
2524 | 2524 |
2525 JVM_ENTRY(jobject, MHI_getBootstrap(JNIEnv *env, jobject igcls, jclass caller_jh)) { | 2525 JVM_ENTRY(jobject, MHI_getBootstrap(JNIEnv *env, jobject igcls, jclass caller_jh)) { |
2526 if (!AllowTransitionalJSR292) | |
2527 THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), "getBootstrap: transitional only"); | |
2526 instanceKlassHandle ik = MethodHandles::resolve_instance_klass(caller_jh, THREAD); | 2528 instanceKlassHandle ik = MethodHandles::resolve_instance_klass(caller_jh, THREAD); |
2527 return JNIHandles::make_local(THREAD, ik->bootstrap_method()); | 2529 return JNIHandles::make_local(THREAD, ik->bootstrap_method()); |
2528 } | 2530 } |
2529 JVM_END | 2531 JVM_END |
2530 | 2532 |
2531 JVM_ENTRY(void, MHI_setCallSiteTarget(JNIEnv *env, jobject igcls, jobject site_jh, jobject target_jh)) { | 2533 JVM_ENTRY(void, MHI_setCallSiteTarget(JNIEnv *env, jobject igcls, jobject site_jh, jobject target_jh)) { |
2532 // No special action required, yet. | 2534 if (!AllowTransitionalJSR292) |
2533 oop site_oop = JNIHandles::resolve(site_jh); | 2535 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "setCallSite: transitional only"); |
2534 if (!java_dyn_CallSite::is_instance(site_oop)) | |
2535 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "not a CallSite"); | |
2536 java_dyn_CallSite::set_target(site_oop, JNIHandles::resolve(target_jh)); | |
2537 } | 2536 } |
2538 JVM_END | 2537 JVM_END |
2539 | 2538 |
2540 | 2539 |
2541 /// JVM_RegisterMethodHandleMethods | 2540 /// JVM_RegisterMethodHandleMethods |
2542 | 2541 |
2543 #define ADR "J" | 2542 #define ADR "J" |
2544 | 2543 |
2545 #define LANG "Ljava/lang/" | 2544 #define LANG "Ljava/lang/" |
2546 #define JDYN "Ljava/dyn/" | 2545 #define JLINV "Ljava/lang/invoke/" /* standard package */ |
2547 #define IDYN "Lsun/dyn/" | 2546 #define JDYN "Ljava/dyn/" /* alternative package to JLINV if AllowTransitionalJSR292 */ |
2547 #define IDYN "Lsun/dyn/" /* alternative package to JDYN if AllowTransitionalJSR292 */ | |
2548 // FIXME: After AllowTransitionalJSR292 is removed, replace JDYN and IDYN by JLINV. | |
2548 | 2549 |
2549 #define OBJ LANG"Object;" | 2550 #define OBJ LANG"Object;" |
2550 #define CLS LANG"Class;" | 2551 #define CLS LANG"Class;" |
2551 #define STRG LANG"String;" | 2552 #define STRG LANG"String;" |
2552 #define CST JDYN"CallSite;" | 2553 #define CST JDYN"CallSite;" |
2553 #define MT JDYN"MethodType;" | 2554 #define MT JDYN"MethodType;" |
2554 #define MH JDYN"MethodHandle;" | 2555 #define MH JDYN"MethodHandle;" |
2555 #define MHI IDYN"MethodHandleImpl;" | |
2556 #define MEM IDYN"MemberName;" | 2556 #define MEM IDYN"MemberName;" |
2557 #define AMH IDYN"AdapterMethodHandle;" | 2557 #define AMH IDYN"AdapterMethodHandle;" |
2558 #define BMH IDYN"BoundMethodHandle;" | 2558 #define BMH IDYN"BoundMethodHandle;" |
2559 #define DMH IDYN"DirectMethodHandle;" | 2559 #define DMH IDYN"DirectMethodHandle;" |
2560 | 2560 |
2579 // int matchFlags, Class<?> caller, int skip, MemberName[] results); | 2579 // int matchFlags, Class<?> caller, int skip, MemberName[] results); |
2580 {CC"getMembers", CC"("CLS""STRG""STRG"I"CLS"I["MEM")I", FN_PTR(MHI_getMembers)} | 2580 {CC"getMembers", CC"("CLS""STRG""STRG"I"CLS"I["MEM")I", FN_PTR(MHI_getMembers)} |
2581 }; | 2581 }; |
2582 | 2582 |
2583 // More entry points specifically for EnableInvokeDynamic. | 2583 // More entry points specifically for EnableInvokeDynamic. |
2584 // FIXME: Remove methods2 after AllowTransitionalJSR292 is removed. | |
2584 static JNINativeMethod methods2[] = { | 2585 static JNINativeMethod methods2[] = { |
2585 {CC"registerBootstrap", CC"("CLS MH")V", FN_PTR(MHI_registerBootstrap)}, | 2586 {CC"registerBootstrap", CC"("CLS MH")V", FN_PTR(MHI_registerBootstrap)}, |
2586 {CC"getBootstrap", CC"("CLS")"MH, FN_PTR(MHI_getBootstrap)}, | 2587 {CC"getBootstrap", CC"("CLS")"MH, FN_PTR(MHI_getBootstrap)}, |
2587 {CC"setCallSiteTarget", CC"("CST MH")V", FN_PTR(MHI_setCallSiteTarget)} | 2588 {CC"setCallSiteTarget", CC"("CST MH")V", FN_PTR(MHI_setCallSiteTarget)} |
2588 }; | 2589 }; |
2589 | 2590 |
2591 static void hack_signatures(JNINativeMethod* methods, jint num_methods, const char* from_sig, const char* to_sig) { | |
2592 for (int i = 0; i < num_methods; i++) { | |
2593 const char* sig = methods[i].signature; | |
2594 if (!strstr(sig, from_sig)) continue; | |
2595 size_t buflen = strlen(sig) + 100; | |
2596 char* buf = NEW_C_HEAP_ARRAY(char, buflen); | |
2597 char* bufp = buf; | |
2598 const char* sigp = sig; | |
2599 size_t from_len = strlen(from_sig), to_len = strlen(to_sig); | |
2600 while (*sigp != '\0') { | |
2601 assert(bufp < buf + buflen - to_len - 1, "oob"); | |
2602 if (strncmp(sigp, from_sig, from_len) != 0) { | |
2603 *bufp++ = *sigp++; | |
2604 } else { | |
2605 strcpy(bufp, to_sig); | |
2606 bufp += to_len; | |
2607 sigp += from_len; | |
2608 } | |
2609 } | |
2610 *bufp = '\0'; | |
2611 methods[i].signature = buf; // replace with new signature | |
2612 if (TraceMethodHandles) | |
2613 tty->print_cr("MethodHandleNatives: %s: change signature %s => %s", methods[i].name, sig, buf); | |
2614 } | |
2615 } | |
2590 | 2616 |
2591 // This one function is exported, used by NativeLookup. | 2617 // This one function is exported, used by NativeLookup. |
2592 | 2618 |
2593 JVM_ENTRY(void, JVM_RegisterMethodHandleMethods(JNIEnv *env, jclass MHN_class)) { | 2619 JVM_ENTRY(void, JVM_RegisterMethodHandleMethods(JNIEnv *env, jclass MHN_class)) { |
2594 assert(MethodHandles::spot_check_entry_names(), "entry enum is OK"); | 2620 assert(MethodHandles::spot_check_entry_names(), "entry enum is OK"); |
2598 if (!EnableMethodHandles) { | 2624 if (!EnableMethodHandles) { |
2599 warning("JSR 292 method handles are disabled in this JVM. Use -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles to enable."); | 2625 warning("JSR 292 method handles are disabled in this JVM. Use -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles to enable."); |
2600 return; // bind nothing | 2626 return; // bind nothing |
2601 } | 2627 } |
2602 | 2628 |
2629 if (SystemDictionary::MethodHandleNatives_klass() != NULL && | |
2630 SystemDictionary::MethodHandleNatives_klass() != java_lang_Class::as_klassOop(JNIHandles::resolve(MHN_class))) { | |
2631 warning("multiple versions of MethodHandleNatives in boot classpath; consider using -XX:+PreferTransitionalJSR292"); | |
2632 THROW_MSG(vmSymbols::java_lang_InternalError(), "multiple versions of MethodHandleNatives in boot classpath; consider using -XX:+PreferTransitionalJSR292"); | |
2633 } | |
2634 | |
2603 bool enable_MH = true; | 2635 bool enable_MH = true; |
2604 | 2636 |
2605 { | 2637 // Loop control. FIXME: Replace by dead reckoning after AllowTransitionalJSR292 is removed. |
2638 bool registered_natives = false; | |
2639 bool try_plain = true, try_JDYN = true, try_IDYN = true; | |
2640 for (;;) { | |
2606 ThreadToNativeFromVM ttnfv(thread); | 2641 ThreadToNativeFromVM ttnfv(thread); |
2607 | 2642 |
2643 if (try_plain) { try_plain = false; } | |
2644 else if (try_JDYN) { try_JDYN = false; hack_signatures(methods, sizeof(methods)/sizeof(JNINativeMethod), IDYN, JDYN); } | |
2645 else if (try_IDYN) { try_IDYN = false; hack_signatures(methods, sizeof(methods)/sizeof(JNINativeMethod), JDYN, JLINV); } | |
2646 else { break; } | |
2608 int status = env->RegisterNatives(MHN_class, methods, sizeof(methods)/sizeof(JNINativeMethod)); | 2647 int status = env->RegisterNatives(MHN_class, methods, sizeof(methods)/sizeof(JNINativeMethod)); |
2609 if (env->ExceptionOccurred()) { | 2648 if (env->ExceptionOccurred()) { |
2610 MethodHandles::set_enabled(false); | |
2611 warning("JSR 292 method handle code is mismatched to this JVM. Disabling support."); | |
2612 enable_MH = false; | |
2613 env->ExceptionClear(); | 2649 env->ExceptionClear(); |
2614 } | 2650 // and try again... |
2651 } else { | |
2652 registered_natives = true; | |
2653 break; | |
2654 } | |
2655 } | |
2656 if (!registered_natives) { | |
2657 MethodHandles::set_enabled(false); | |
2658 warning("JSR 292 method handle code is mismatched to this JVM. Disabling support."); | |
2659 enable_MH = false; | |
2615 } | 2660 } |
2616 | 2661 |
2617 if (enable_MH) { | 2662 if (enable_MH) { |
2663 bool found_raise_exception = false; | |
2664 KlassHandle MHN_klass = SystemDictionaryHandles::MethodHandleNatives_klass(); | |
2618 KlassHandle MHI_klass = SystemDictionaryHandles::MethodHandleImpl_klass(); | 2665 KlassHandle MHI_klass = SystemDictionaryHandles::MethodHandleImpl_klass(); |
2619 if (MHI_klass.not_null()) { | 2666 // Loop control. FIXME: Replace by dead reckoning after AllowTransitionalJSR292 is removed. |
2667 bool try_MHN = true, try_MHI = AllowTransitionalJSR292; | |
2668 for (;;) { | |
2669 KlassHandle try_klass; | |
2670 if (try_MHN) { try_MHN = false; try_klass = MHN_klass; } | |
2671 else if (try_MHI) { try_MHI = false; try_klass = MHI_klass; } | |
2672 else { break; } | |
2673 if (try_klass.is_null()) continue; | |
2620 TempNewSymbol raiseException_name = SymbolTable::new_symbol("raiseException", CHECK); | 2674 TempNewSymbol raiseException_name = SymbolTable::new_symbol("raiseException", CHECK); |
2621 TempNewSymbol raiseException_sig = SymbolTable::new_symbol("(ILjava/lang/Object;Ljava/lang/Object;)V", CHECK); | 2675 TempNewSymbol raiseException_sig = SymbolTable::new_symbol("(ILjava/lang/Object;Ljava/lang/Object;)V", CHECK); |
2622 methodOop raiseException_method = instanceKlass::cast(MHI_klass->as_klassOop()) | 2676 methodOop raiseException_method = instanceKlass::cast(try_klass->as_klassOop()) |
2623 ->find_method(raiseException_name, raiseException_sig); | 2677 ->find_method(raiseException_name, raiseException_sig); |
2624 if (raiseException_method != NULL && raiseException_method->is_static()) { | 2678 if (raiseException_method != NULL && raiseException_method->is_static()) { |
2625 MethodHandles::set_raise_exception_method(raiseException_method); | 2679 MethodHandles::set_raise_exception_method(raiseException_method); |
2626 } else { | 2680 found_raise_exception = true; |
2627 warning("JSR 292 method handle code is mismatched to this JVM. Disabling support."); | 2681 break; |
2628 enable_MH = false; | 2682 } |
2629 } | 2683 } |
2630 } else { | 2684 if (!found_raise_exception) { |
2685 warning("JSR 292 method handle code is mismatched to this JVM. Disabling support."); | |
2631 enable_MH = false; | 2686 enable_MH = false; |
2632 } | 2687 } |
2633 } | 2688 } |
2634 | 2689 |
2635 if (enable_MH) { | 2690 if (enable_MH) { |
2636 // We need to link the MethodHandleImpl klass before we generate | 2691 if (AllowTransitionalJSR292) { |
2637 // the method handle adapters as the _raise_exception adapter uses | 2692 // We need to link the MethodHandleImpl klass before we generate |
2638 // one of its methods (and its c2i-adapter). | 2693 // the method handle adapters as the _raise_exception adapter uses |
2639 KlassHandle k = SystemDictionaryHandles::MethodHandleImpl_klass(); | 2694 // one of its methods (and its c2i-adapter). |
2640 instanceKlass* ik = instanceKlass::cast(k()); | 2695 KlassHandle k = SystemDictionaryHandles::MethodHandleImpl_klass(); |
2641 ik->link_class(CHECK); | 2696 instanceKlass* ik = instanceKlass::cast(k()); |
2697 ik->link_class(CHECK); | |
2698 } | |
2642 | 2699 |
2643 MethodHandles::generate_adapters(); | 2700 MethodHandles::generate_adapters(); |
2644 MethodHandles::set_enabled(true); | 2701 MethodHandles::set_enabled(true); |
2645 } | 2702 } |
2646 | 2703 |
2647 if (!EnableInvokeDynamic) { | 2704 if (!EnableInvokeDynamic) { |
2648 warning("JSR 292 invokedynamic is disabled in this JVM. Use -XX:+UnlockExperimentalVMOptions -XX:+EnableInvokeDynamic to enable."); | 2705 warning("JSR 292 invokedynamic is disabled in this JVM. Use -XX:+UnlockExperimentalVMOptions -XX:+EnableInvokeDynamic to enable."); |
2649 return; // bind nothing | 2706 return; // bind nothing |
2650 } | 2707 } |
2651 | 2708 |
2652 { | 2709 if (AllowTransitionalJSR292) { |
2653 ThreadToNativeFromVM ttnfv(thread); | 2710 ThreadToNativeFromVM ttnfv(thread); |
2654 | 2711 |
2655 int status = env->RegisterNatives(MHN_class, methods2, sizeof(methods2)/sizeof(JNINativeMethod)); | 2712 int status = env->RegisterNatives(MHN_class, methods2, sizeof(methods2)/sizeof(JNINativeMethod)); |
2656 if (env->ExceptionOccurred()) { | 2713 if (env->ExceptionOccurred()) { |
2657 MethodHandles::set_enabled(false); | 2714 MethodHandles::set_enabled(false); |
2658 warning("JSR 292 method handle code is mismatched to this JVM. Disabling support."); | 2715 warning("JSR 292 method handle code is mismatched to this JVM. Disabling support."); |
2659 env->ExceptionClear(); | 2716 env->ExceptionClear(); |
2660 } else { | |
2661 MethodHandles::set_enabled(true); | |
2662 } | 2717 } |
2663 } | 2718 } |
2664 } | 2719 } |
2665 JVM_END | 2720 JVM_END |