7085860: JSR 292: implement CallSite.setTargetNormal and setTargetVolatile as native methods
authortwisti
Thu, 08 Sep 2011 05:11:31 -0700
changeset 10540 92d59dba2407
parent 10539 f87cedf7983c
child 10541 d6e8b9d3d362
7085860: JSR 292: implement CallSite.setTargetNormal and setTargetVolatile as native methods Reviewed-by: jrose, never
hotspot/src/share/vm/classfile/javaClasses.cpp
hotspot/src/share/vm/classfile/javaClasses.hpp
hotspot/src/share/vm/oops/klassOop.hpp
hotspot/src/share/vm/oops/oop.hpp
hotspot/src/share/vm/oops/oop.inline.hpp
hotspot/src/share/vm/prims/methodHandles.cpp
--- a/hotspot/src/share/vm/classfile/javaClasses.cpp	Thu Sep 08 10:12:25 2011 +0200
+++ b/hotspot/src/share/vm/classfile/javaClasses.cpp	Thu Sep 08 05:11:31 2011 -0700
@@ -2707,14 +2707,6 @@
   }
 }
 
-oop java_lang_invoke_CallSite::target(oop site) {
-  return site->obj_field(_target_offset);
-}
-
-void java_lang_invoke_CallSite::set_target(oop site, oop target) {
-  site->obj_field_put(_target_offset, target);
-}
-
 
 // Support for java_security_AccessControlContext
 
--- a/hotspot/src/share/vm/classfile/javaClasses.hpp	Thu Sep 08 10:12:25 2011 +0200
+++ b/hotspot/src/share/vm/classfile/javaClasses.hpp	Thu Sep 08 05:11:31 2011 -0700
@@ -771,7 +771,7 @@
     ref->obj_field_put(referent_offset, value);
   }
   static void set_referent_raw(oop ref, oop value) {
-    ref->obj_field_raw_put(referent_offset, value);
+    ref->obj_field_put_raw(referent_offset, value);
   }
   static HeapWord* referent_addr(oop ref) {
     return ref->obj_field_addr<HeapWord>(referent_offset);
@@ -783,7 +783,7 @@
     ref->obj_field_put(next_offset, value);
   }
   static void set_next_raw(oop ref, oop value) {
-    ref->obj_field_raw_put(next_offset, value);
+    ref->obj_field_put_raw(next_offset, value);
   }
   static HeapWord* next_addr(oop ref) {
     return ref->obj_field_addr<HeapWord>(next_offset);
@@ -795,7 +795,7 @@
     ref->obj_field_put(discovered_offset, value);
   }
   static void set_discovered_raw(oop ref, oop value) {
-    ref->obj_field_raw_put(discovered_offset, value);
+    ref->obj_field_put_raw(discovered_offset, value);
   }
   static HeapWord* discovered_addr(oop ref) {
     return ref->obj_field_addr<HeapWord>(discovered_offset);
@@ -1163,14 +1163,17 @@
 
 public:
   // Accessors
-  static oop            target(oop site);
-  static void       set_target(oop site, oop target);
+  static oop              target(         oop site)             { return site->obj_field(             _target_offset);         }
+  static void         set_target(         oop site, oop target) {        site->obj_field_put(         _target_offset, target); }
+
+  static volatile oop     target_volatile(oop site)             { return site->obj_field_volatile(    _target_offset);         }
+  static void         set_target_volatile(oop site, oop target) {        site->obj_field_put_volatile(_target_offset, target); }
 
-  static oop            caller_method(oop site);
-  static void       set_caller_method(oop site, oop ref);
+  static oop              caller_method(oop site);
+  static void         set_caller_method(oop site, oop ref);
 
-  static jint           caller_bci(oop site);
-  static void       set_caller_bci(oop site, jint bci);
+  static jint             caller_bci(oop site);
+  static void         set_caller_bci(oop site, jint bci);
 
   // Testers
   static bool is_subclass(klassOop klass) {
--- a/hotspot/src/share/vm/oops/klassOop.hpp	Thu Sep 08 10:12:25 2011 +0200
+++ b/hotspot/src/share/vm/oops/klassOop.hpp	Thu Sep 08 05:11:31 2011 -0700
@@ -53,8 +53,10 @@
  private:
   // These have no implementation since klassOop should never be accessed in this fashion
   oop obj_field(int offset) const;
+  volatile oop obj_field_volatile(int offset) const;
   void obj_field_put(int offset, oop value);
-  void obj_field_raw_put(int offset, oop value);
+  void obj_field_put_raw(int offset, oop value);
+  void obj_field_put_volatile(int offset, oop value);
 
   jbyte byte_field(int offset) const;
   void byte_field_put(int offset, jbyte contents);
--- a/hotspot/src/share/vm/oops/oop.hpp	Thu Sep 08 10:12:25 2011 +0200
+++ b/hotspot/src/share/vm/oops/oop.hpp	Thu Sep 08 05:11:31 2011 -0700
@@ -214,8 +214,10 @@
 
   // Access to fields in a instanceOop through these methods.
   oop obj_field(int offset) const;
+  volatile oop obj_field_volatile(int offset) const;
   void obj_field_put(int offset, oop value);
-  void obj_field_raw_put(int offset, oop value);
+  void obj_field_put_raw(int offset, oop value);
+  void obj_field_put_volatile(int offset, oop value);
 
   jbyte byte_field(int offset) const;
   void byte_field_put(int offset, jbyte contents);
--- a/hotspot/src/share/vm/oops/oop.inline.hpp	Thu Sep 08 10:12:25 2011 +0200
+++ b/hotspot/src/share/vm/oops/oop.inline.hpp	Thu Sep 08 05:11:31 2011 -0700
@@ -321,15 +321,25 @@
     load_decode_heap_oop(obj_field_addr<narrowOop>(offset)) :
     load_decode_heap_oop(obj_field_addr<oop>(offset));
 }
+inline volatile oop oopDesc::obj_field_volatile(int offset) const {
+  volatile oop value = obj_field(offset);
+  OrderAccess::acquire();
+  return value;
+}
 inline void oopDesc::obj_field_put(int offset, oop value) {
   UseCompressedOops ? oop_store(obj_field_addr<narrowOop>(offset), value) :
                       oop_store(obj_field_addr<oop>(offset),       value);
 }
-inline void oopDesc::obj_field_raw_put(int offset, oop value) {
+inline void oopDesc::obj_field_put_raw(int offset, oop value) {
   UseCompressedOops ?
     encode_store_heap_oop(obj_field_addr<narrowOop>(offset), value) :
     encode_store_heap_oop(obj_field_addr<oop>(offset),       value);
 }
+inline void oopDesc::obj_field_put_volatile(int offset, oop value) {
+  OrderAccess::release();
+  obj_field_put(offset, value);
+  OrderAccess::fence();
+}
 
 inline jbyte oopDesc::byte_field(int offset) const                  { return (jbyte) *byte_field_addr(offset);    }
 inline void oopDesc::byte_field_put(int offset, jbyte contents)     { *byte_field_addr(offset) = (jint) contents; }
--- a/hotspot/src/share/vm/prims/methodHandles.cpp	Thu Sep 08 10:12:25 2011 +0200
+++ b/hotspot/src/share/vm/prims/methodHandles.cpp	Thu Sep 08 05:11:31 2011 -0700
@@ -3081,6 +3081,30 @@
 }
 JVM_END
 
+JVM_ENTRY(void, MHN_setCallSiteTargetNormal(JNIEnv* env, jobject igcls, jobject call_site_jh, jobject target_jh)) {
+  oop call_site = JNIHandles::resolve_non_null(call_site_jh);
+  oop target    = JNIHandles::resolve(target_jh);
+  {
+    // Walk all nmethods depending on this call site.
+    MutexLocker mu(Compile_lock, thread);
+    Universe::flush_dependents_on(call_site, target);
+  }
+  java_lang_invoke_CallSite::set_target(call_site, target);
+}
+JVM_END
+
+JVM_ENTRY(void, MHN_setCallSiteTargetVolatile(JNIEnv* env, jobject igcls, jobject call_site_jh, jobject target_jh)) {
+  oop call_site = JNIHandles::resolve_non_null(call_site_jh);
+  oop target    = JNIHandles::resolve(target_jh);
+  {
+    // Walk all nmethods depending on this call site.
+    MutexLocker mu(Compile_lock, thread);
+    Universe::flush_dependents_on(call_site, target);
+  }
+  java_lang_invoke_CallSite::set_target_volatile(call_site, target);
+}
+JVM_END
+
 methodOop MethodHandles::resolve_raise_exception_method(TRAPS) {
   if (_raise_exception_method != NULL) {
     // no need to do it twice
@@ -3137,12 +3161,15 @@
 
 /// JVM_RegisterMethodHandleMethods
 
+#undef CS  // Solaris builds complain
+
 #define LANG "Ljava/lang/"
 #define JLINV "Ljava/lang/invoke/"
 
 #define OBJ   LANG"Object;"
 #define CLS   LANG"Class;"
 #define STRG  LANG"String;"
+#define CS    JLINV"CallSite;"
 #define MT    JLINV"MethodType;"
 #define MH    JLINV"MethodHandle;"
 #define MEM   JLINV"MemberName;"
@@ -3153,29 +3180,34 @@
 #define CC (char*)  /*cast a literal from (const char*)*/
 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f)
 
-// These are the native methods on sun.invoke.MethodHandleNatives.
+// These are the native methods on java.lang.invoke.MethodHandleNatives.
 static JNINativeMethod methods[] = {
   // void init(MemberName self, AccessibleObject ref)
-  {CC"init",                    CC"("AMH""MH"I)V",              FN_PTR(MHN_init_AMH)},
-  {CC"init",                    CC"("BMH""OBJ"I)V",             FN_PTR(MHN_init_BMH)},
-  {CC"init",                    CC"("DMH""OBJ"Z"CLS")V",        FN_PTR(MHN_init_DMH)},
-  {CC"init",                    CC"("MT")V",                    FN_PTR(MHN_init_MT)},
-  {CC"init",                    CC"("MEM""OBJ")V",              FN_PTR(MHN_init_Mem)},
-  {CC"expand",                  CC"("MEM")V",                   FN_PTR(MHN_expand_Mem)},
-  {CC"resolve",                 CC"("MEM""CLS")V",              FN_PTR(MHN_resolve_Mem)},
-  {CC"getTarget",               CC"("MH"I)"OBJ,                 FN_PTR(MHN_getTarget)},
-  {CC"getConstant",             CC"(I)I",                       FN_PTR(MHN_getConstant)},
+  {CC"init",                      CC"("AMH""MH"I)V",                     FN_PTR(MHN_init_AMH)},
+  {CC"init",                      CC"("BMH""OBJ"I)V",                    FN_PTR(MHN_init_BMH)},
+  {CC"init",                      CC"("DMH""OBJ"Z"CLS")V",               FN_PTR(MHN_init_DMH)},
+  {CC"init",                      CC"("MT")V",                           FN_PTR(MHN_init_MT)},
+  {CC"init",                      CC"("MEM""OBJ")V",                     FN_PTR(MHN_init_Mem)},
+  {CC"expand",                    CC"("MEM")V",                          FN_PTR(MHN_expand_Mem)},
+  {CC"resolve",                   CC"("MEM""CLS")V",                     FN_PTR(MHN_resolve_Mem)},
+  {CC"getTarget",                 CC"("MH"I)"OBJ,                        FN_PTR(MHN_getTarget)},
+  {CC"getConstant",               CC"(I)I",                              FN_PTR(MHN_getConstant)},
   //  static native int getNamedCon(int which, Object[] name)
-  {CC"getNamedCon",             CC"(I["OBJ")I",                 FN_PTR(MHN_getNamedCon)},
+  {CC"getNamedCon",               CC"(I["OBJ")I",                        FN_PTR(MHN_getNamedCon)},
   //  static native int getMembers(Class<?> defc, String matchName, String matchSig,
   //          int matchFlags, Class<?> caller, int skip, MemberName[] results);
-  {CC"getMembers",              CC"("CLS""STRG""STRG"I"CLS"I["MEM")I",  FN_PTR(MHN_getMembers)}
+  {CC"getMembers",                CC"("CLS""STRG""STRG"I"CLS"I["MEM")I", FN_PTR(MHN_getMembers)}
+};
+
+static JNINativeMethod call_site_methods[] = {
+  {CC"setCallSiteTargetNormal",   CC"("CS""MH")V",                       FN_PTR(MHN_setCallSiteTargetNormal)},
+  {CC"setCallSiteTargetVolatile", CC"("CS""MH")V",                       FN_PTR(MHN_setCallSiteTargetVolatile)}
 };
 
 static JNINativeMethod invoke_methods[] = {
   // void init(MemberName self, AccessibleObject ref)
-  {CC"invoke",                  CC"(["OBJ")"OBJ,                FN_PTR(MH_invoke_UOE)},
-  {CC"invokeExact",             CC"(["OBJ")"OBJ,                FN_PTR(MH_invokeExact_UOE)}
+  {CC"invoke",                    CC"(["OBJ")"OBJ,                       FN_PTR(MH_invoke_UOE)},
+  {CC"invokeExact",               CC"(["OBJ")"OBJ,                       FN_PTR(MH_invokeExact_UOE)}
 };
 
 // This one function is exported, used by NativeLookup.
@@ -3188,11 +3220,11 @@
     return;  // bind nothing
   }
 
+  assert(!MethodHandles::enabled(), "must not be enabled");
   bool enable_MH = true;
 
   {
     ThreadToNativeFromVM ttnfv(thread);
-
     int status = env->RegisterNatives(MHN_class, methods, sizeof(methods)/sizeof(JNINativeMethod));
     if (!env->ExceptionOccurred()) {
       const char* L_MH_name = (JLINV "MethodHandle");
@@ -3201,11 +3233,16 @@
       status = env->RegisterNatives(MH_class, invoke_methods, sizeof(invoke_methods)/sizeof(JNINativeMethod));
     }
     if (env->ExceptionOccurred()) {
-      MethodHandles::set_enabled(false);
       warning("JSR 292 method handle code is mismatched to this JVM.  Disabling support.");
       enable_MH = false;
       env->ExceptionClear();
     }
+
+    status = env->RegisterNatives(MHN_class, call_site_methods, sizeof(call_site_methods)/sizeof(JNINativeMethod));
+    if (env->ExceptionOccurred()) {
+      // Exception is okay until 7087357
+      env->ExceptionClear();
+    }
   }
 
   if (enable_MH) {