--- old/src/share/vm/classfile/javaClasses.cpp 2011-09-08 02:26:30.069220258 -0700 +++ new/src/share/vm/classfile/javaClasses.cpp 2011-09-08 02:26:29.812529732 -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 --- old/src/share/vm/classfile/javaClasses.hpp 2011-09-08 02:26:31.457715412 -0700 +++ new/src/share/vm/classfile/javaClasses.hpp 2011-09-08 02:26:31.192816882 -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(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(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(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 oop caller_method(oop site); - static void set_caller_method(oop site, oop ref); + 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 jint caller_bci(oop site); - static void set_caller_bci(oop site, jint bci); + 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); // Testers static bool is_subclass(klassOop klass) { --- old/src/share/vm/oops/klassOop.hpp 2011-09-08 02:26:32.653640045 -0700 +++ new/src/share/vm/oops/klassOop.hpp 2011-09-08 02:26:32.391831161 -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); --- old/src/share/vm/oops/oop.hpp 2011-09-08 02:26:33.776267942 -0700 +++ new/src/share/vm/oops/oop.hpp 2011-09-08 02:26:33.519939688 -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); --- old/src/share/vm/oops/oop.inline.hpp 2011-09-08 02:26:34.948369076 -0700 +++ new/src/share/vm/oops/oop.inline.hpp 2011-09-08 02:26:34.698840638 -0700 @@ -321,15 +321,25 @@ load_decode_heap_oop(obj_field_addr(offset)) : load_decode_heap_oop(obj_field_addr(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(offset), value) : oop_store(obj_field_addr(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(offset), value) : encode_store_heap_oop(obj_field_addr(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; } --- old/src/share/vm/prims/methodHandles.cpp 2011-09-08 02:26:36.143617160 -0700 +++ new/src/share/vm/prims/methodHandles.cpp 2011-09-08 02:26:35.876772907 -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) { --- old/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java 2011-09-08 02:26:37.878858854 -0700 +++ new/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java 2011-09-08 02:26:37.429069441 -0700 @@ -61,15 +61,6 @@ /** Initialize a method type, once per form. */ static native void init(MethodType self); - /** Tell the JVM about a class's bootstrap method. */ - static native void registerBootstrap(Class caller, MethodHandle bootstrapMethod); - - /** Ask the JVM about a class's bootstrap method. */ - static native MethodHandle getBootstrap(Class caller); - - /** Tell the JVM that we need to change the target of an invokedynamic. */ - static native void setCallSiteTarget(CallSite site, MethodHandle target); - /** Fetch the vmtarget field. * It will be sanitized as necessary to avoid exposing non-Java references. * This routine is for debugging and reflection. @@ -122,6 +113,12 @@ static final boolean COUNT_GWT; + /// CallSite support + + /** Tell the JVM that we need to change the target of a CallSite. */ + static native void setCallSiteTargetNormal(CallSite site, MethodHandle target); + static native void setCallSiteTargetVolatile(CallSite site, MethodHandle target); + private static native void registerNatives(); static { registerNatives(); --- old/jdk/src/share/classes/java/lang/invoke/CallSite.java 2011-09-08 02:26:39.729099280 -0700 +++ new/jdk/src/share/classes/java/lang/invoke/CallSite.java 2011-09-08 02:26:39.279831694 -0700 @@ -267,7 +267,7 @@ /*package-private*/ void setTargetNormal(MethodHandle newTarget) { - target = newTarget; + MethodHandleNatives.setCallSiteTargetNormal(this, newTarget); } /*package-private*/ MethodHandle getTargetVolatile() { @@ -275,7 +275,7 @@ } /*package-private*/ void setTargetVolatile(MethodHandle newTarget) { - unsafe.putObjectVolatile(this, TARGET_OFFSET, newTarget); + MethodHandleNatives.setCallSiteTargetVolatile(this, newTarget); } // this implements the upcall from the JVM, MethodHandleNatives.makeDynamicCallSite: