hotspot/src/share/vm/prims/methodHandles.cpp
changeset 9116 9bc44be338d6
parent 8883 5569135acca3
child 9134 189a8c094016
equal deleted inserted replaced
9115:5a28312aa393 9116:9bc44be338d6
  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