src/share/vm/prims/methodHandles.cpp

changeset 2638
72dee110246f
parent 2497
3582bf76420e
child 2639
8033953d67ff
     1.1 --- a/src/share/vm/prims/methodHandles.cpp	Fri Mar 11 21:19:15 2011 -0800
     1.2 +++ b/src/share/vm/prims/methodHandles.cpp	Fri Mar 11 22:33:47 2011 -0800
     1.3 @@ -2523,17 +2523,16 @@
     1.4  JVM_END
     1.5  
     1.6  JVM_ENTRY(jobject, MHI_getBootstrap(JNIEnv *env, jobject igcls, jclass caller_jh)) {
     1.7 +  if (!AllowTransitionalJSR292)
     1.8 +    THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), "getBootstrap: transitional only");
     1.9    instanceKlassHandle ik = MethodHandles::resolve_instance_klass(caller_jh, THREAD);
    1.10    return JNIHandles::make_local(THREAD, ik->bootstrap_method());
    1.11  }
    1.12  JVM_END
    1.13  
    1.14  JVM_ENTRY(void, MHI_setCallSiteTarget(JNIEnv *env, jobject igcls, jobject site_jh, jobject target_jh)) {
    1.15 -  // No special action required, yet.
    1.16 -  oop site_oop = JNIHandles::resolve(site_jh);
    1.17 -  if (!java_dyn_CallSite::is_instance(site_oop))
    1.18 -    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "not a CallSite");
    1.19 -  java_dyn_CallSite::set_target(site_oop, JNIHandles::resolve(target_jh));
    1.20 +  if (!AllowTransitionalJSR292)
    1.21 +    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "setCallSite: transitional only");
    1.22  }
    1.23  JVM_END
    1.24  
    1.25 @@ -2543,8 +2542,10 @@
    1.26  #define ADR "J"
    1.27  
    1.28  #define LANG "Ljava/lang/"
    1.29 -#define JDYN "Ljava/dyn/"
    1.30 -#define IDYN "Lsun/dyn/"
    1.31 +#define JLINV "Ljava/lang/invoke/" /* standard package */
    1.32 +#define JDYN "Ljava/dyn/" /* alternative package to JLINV if AllowTransitionalJSR292 */
    1.33 +#define IDYN "Lsun/dyn/"  /* alternative package to JDYN if AllowTransitionalJSR292 */
    1.34 +// FIXME: After AllowTransitionalJSR292 is removed, replace JDYN and IDYN by JLINV.
    1.35  
    1.36  #define OBJ   LANG"Object;"
    1.37  #define CLS   LANG"Class;"
    1.38 @@ -2552,7 +2553,6 @@
    1.39  #define CST   JDYN"CallSite;"
    1.40  #define MT    JDYN"MethodType;"
    1.41  #define MH    JDYN"MethodHandle;"
    1.42 -#define MHI   IDYN"MethodHandleImpl;"
    1.43  #define MEM   IDYN"MemberName;"
    1.44  #define AMH   IDYN"AdapterMethodHandle;"
    1.45  #define BMH   IDYN"BoundMethodHandle;"
    1.46 @@ -2581,12 +2581,38 @@
    1.47  };
    1.48  
    1.49  // More entry points specifically for EnableInvokeDynamic.
    1.50 +// FIXME: Remove methods2 after AllowTransitionalJSR292 is removed.
    1.51  static JNINativeMethod methods2[] = {
    1.52    {CC"registerBootstrap",       CC"("CLS MH")V",                FN_PTR(MHI_registerBootstrap)},
    1.53    {CC"getBootstrap",            CC"("CLS")"MH,                  FN_PTR(MHI_getBootstrap)},
    1.54    {CC"setCallSiteTarget",       CC"("CST MH")V",                FN_PTR(MHI_setCallSiteTarget)}
    1.55  };
    1.56  
    1.57 +static void hack_signatures(JNINativeMethod* methods, jint num_methods, const char* from_sig, const char* to_sig) {
    1.58 +  for (int i = 0; i < num_methods; i++) {
    1.59 +    const char* sig = methods[i].signature;
    1.60 +    if (!strstr(sig, from_sig))  continue;
    1.61 +    size_t buflen = strlen(sig) + 100;
    1.62 +    char* buf = NEW_C_HEAP_ARRAY(char, buflen);
    1.63 +    char* bufp = buf;
    1.64 +    const char* sigp = sig;
    1.65 +    size_t from_len = strlen(from_sig), to_len = strlen(to_sig);
    1.66 +    while (*sigp != '\0') {
    1.67 +      assert(bufp < buf + buflen - to_len - 1, "oob");
    1.68 +      if (strncmp(sigp, from_sig, from_len) != 0) {
    1.69 +        *bufp++ = *sigp++;
    1.70 +      } else {
    1.71 +        strcpy(bufp, to_sig);
    1.72 +        bufp += to_len;
    1.73 +        sigp += from_len;
    1.74 +      }
    1.75 +    }
    1.76 +    *bufp = '\0';
    1.77 +    methods[i].signature = buf;  // replace with new signature
    1.78 +    if (TraceMethodHandles)
    1.79 +      tty->print_cr("MethodHandleNatives: %s: change signature %s => %s", methods[i].name, sig, buf);
    1.80 +  }
    1.81 +}
    1.82  
    1.83  // This one function is exported, used by NativeLookup.
    1.84  
    1.85 @@ -2600,45 +2626,76 @@
    1.86      return;  // bind nothing
    1.87    }
    1.88  
    1.89 +  if (SystemDictionary::MethodHandleNatives_klass() != NULL &&
    1.90 +      SystemDictionary::MethodHandleNatives_klass() != java_lang_Class::as_klassOop(JNIHandles::resolve(MHN_class))) {
    1.91 +    warning("multiple versions of MethodHandleNatives in boot classpath; consider using -XX:+PreferTransitionalJSR292");
    1.92 +    THROW_MSG(vmSymbols::java_lang_InternalError(), "multiple versions of MethodHandleNatives in boot classpath; consider using -XX:+PreferTransitionalJSR292");
    1.93 +  }
    1.94 +
    1.95    bool enable_MH = true;
    1.96  
    1.97 -  {
    1.98 +  // Loop control.  FIXME: Replace by dead reckoning after AllowTransitionalJSR292 is removed.
    1.99 +  bool registered_natives = false;
   1.100 +  bool try_plain = true, try_JDYN = true, try_IDYN = true;
   1.101 +  for (;;) {
   1.102      ThreadToNativeFromVM ttnfv(thread);
   1.103  
   1.104 +    if      (try_plain) { try_plain = false; }
   1.105 +    else if (try_JDYN)  { try_JDYN  = false; hack_signatures(methods, sizeof(methods)/sizeof(JNINativeMethod), IDYN, JDYN); }
   1.106 +    else if (try_IDYN)  { try_IDYN  = false; hack_signatures(methods, sizeof(methods)/sizeof(JNINativeMethod), JDYN, JLINV); }
   1.107 +    else                { break; }
   1.108      int status = env->RegisterNatives(MHN_class, methods, sizeof(methods)/sizeof(JNINativeMethod));
   1.109      if (env->ExceptionOccurred()) {
   1.110 -      MethodHandles::set_enabled(false);
   1.111 -      warning("JSR 292 method handle code is mismatched to this JVM.  Disabling support.");
   1.112 -      enable_MH = false;
   1.113        env->ExceptionClear();
   1.114 +      // and try again...
   1.115 +    } else {
   1.116 +      registered_natives = true;
   1.117 +      break;
   1.118      }
   1.119    }
   1.120 +  if (!registered_natives) {
   1.121 +    MethodHandles::set_enabled(false);
   1.122 +    warning("JSR 292 method handle code is mismatched to this JVM.  Disabling support.");
   1.123 +    enable_MH = false;
   1.124 +  }
   1.125  
   1.126    if (enable_MH) {
   1.127 +    bool found_raise_exception = false;
   1.128 +    KlassHandle MHN_klass = SystemDictionaryHandles::MethodHandleNatives_klass();
   1.129      KlassHandle MHI_klass = SystemDictionaryHandles::MethodHandleImpl_klass();
   1.130 -    if (MHI_klass.not_null()) {
   1.131 +    // Loop control.  FIXME: Replace by dead reckoning after AllowTransitionalJSR292 is removed.
   1.132 +    bool try_MHN = true, try_MHI = AllowTransitionalJSR292;
   1.133 +    for (;;) {
   1.134 +      KlassHandle try_klass;
   1.135 +      if      (try_MHN) { try_MHN = false; try_klass = MHN_klass; }
   1.136 +      else if (try_MHI) { try_MHI = false; try_klass = MHI_klass; }
   1.137 +      else              { break; }
   1.138 +      if (try_klass.is_null())  continue;
   1.139        TempNewSymbol raiseException_name = SymbolTable::new_symbol("raiseException", CHECK);
   1.140        TempNewSymbol raiseException_sig = SymbolTable::new_symbol("(ILjava/lang/Object;Ljava/lang/Object;)V", CHECK);
   1.141 -      methodOop raiseException_method  = instanceKlass::cast(MHI_klass->as_klassOop())
   1.142 +      methodOop raiseException_method  = instanceKlass::cast(try_klass->as_klassOop())
   1.143                      ->find_method(raiseException_name, raiseException_sig);
   1.144        if (raiseException_method != NULL && raiseException_method->is_static()) {
   1.145          MethodHandles::set_raise_exception_method(raiseException_method);
   1.146 -      } else {
   1.147 -        warning("JSR 292 method handle code is mismatched to this JVM.  Disabling support.");
   1.148 -        enable_MH = false;
   1.149 +        found_raise_exception = true;
   1.150 +        break;
   1.151        }
   1.152 -    } else {
   1.153 +    }
   1.154 +    if (!found_raise_exception) {
   1.155 +      warning("JSR 292 method handle code is mismatched to this JVM.  Disabling support.");
   1.156        enable_MH = false;
   1.157      }
   1.158    }
   1.159  
   1.160    if (enable_MH) {
   1.161 -    // We need to link the MethodHandleImpl klass before we generate
   1.162 -    // the method handle adapters as the _raise_exception adapter uses
   1.163 -    // one of its methods (and its c2i-adapter).
   1.164 -    KlassHandle    k  = SystemDictionaryHandles::MethodHandleImpl_klass();
   1.165 -    instanceKlass* ik = instanceKlass::cast(k());
   1.166 -    ik->link_class(CHECK);
   1.167 +    if (AllowTransitionalJSR292) {
   1.168 +      // We need to link the MethodHandleImpl klass before we generate
   1.169 +      // the method handle adapters as the _raise_exception adapter uses
   1.170 +      // one of its methods (and its c2i-adapter).
   1.171 +      KlassHandle    k  = SystemDictionaryHandles::MethodHandleImpl_klass();
   1.172 +      instanceKlass* ik = instanceKlass::cast(k());
   1.173 +      ik->link_class(CHECK);
   1.174 +    }
   1.175  
   1.176      MethodHandles::generate_adapters();
   1.177      MethodHandles::set_enabled(true);
   1.178 @@ -2649,7 +2706,7 @@
   1.179      return;  // bind nothing
   1.180    }
   1.181  
   1.182 -  {
   1.183 +  if (AllowTransitionalJSR292) {
   1.184      ThreadToNativeFromVM ttnfv(thread);
   1.185  
   1.186      int status = env->RegisterNatives(MHN_class, methods2, sizeof(methods2)/sizeof(JNINativeMethod));
   1.187 @@ -2657,8 +2714,6 @@
   1.188        MethodHandles::set_enabled(false);
   1.189        warning("JSR 292 method handle code is mismatched to this JVM.  Disabling support.");
   1.190        env->ExceptionClear();
   1.191 -    } else {
   1.192 -      MethodHandles::set_enabled(true);
   1.193      }
   1.194    }
   1.195  }

mercurial