changeset 470:89687e50c4e9

meth: simplify invokedynamic linkage paths; remove cpCache entry race condition
author jrose
date Wed, 11 Jul 2012 04:51:47 -0700
parents 2ebbc5f13bb6
children 22a0e2e50ec4
files meth-lazy-7023639.patch
diffstat 1 files changed, 227 insertions(+), 134 deletions(-) [+]
line wrap: on
line diff
--- a/meth-lazy-7023639.patch	Tue Jul 10 23:31:36 2012 -0700
+++ b/meth-lazy-7023639.patch	Wed Jul 11 04:51:47 2012 -0700
@@ -13066,7 +13066,7 @@
    } else {
      ResourceMark rm(THREAD);
      SignatureStream ss(signature, false);
-@@ -2543,119 +2606,59 @@
+@@ -2543,119 +2606,54 @@
  
  // Ask Java code to find or construct a java.lang.invoke.CallSite for the given
  // name and signature, as interpreted relative to the given class loader.
@@ -13080,8 +13080,7 @@
 -  Handle empty;
 -  guarantee(bootstrap_method.not_null() &&
 -            java_lang_invoke_MethodHandle::is_instance(bootstrap_method()),
-+methodHandle SystemDictionary::find_dynamic_call_site_invoker(methodHandle caller_method,
-+                                                              int caller_bci,
++methodHandle SystemDictionary::find_dynamic_call_site_invoker(KlassHandle caller,
 +                                                              Handle bootstrap_specifier,
 +                                                              Symbol* name,
 +                                                              Symbol* type,
@@ -13107,7 +13106,7 @@
 +  guarantee(java_lang_invoke_MethodHandle::is_instance(bsm()),
              "caller must supply a valid BSM");
  
-   Handle caller_mname = MethodHandles::new_MemberName(CHECK_(empty));
+-  Handle caller_mname = MethodHandles::new_MemberName(CHECK_(empty));
 -  MethodHandles::init_MemberName(caller_mname(), caller_method());
 -
 -  // call java.lang.invoke.MethodHandleNatives::makeDynamicCallSite(bootm, name, mtype, info, caller_mname, caller_pos)
@@ -13115,23 +13114,21 @@
 -  JavaCallArguments args(Handle(THREAD, bootstrap_method()));
 -  args.push_oop(name_str_oop);
 -  args.push_oop(signature_invoker->method_handle_type());
--  args.push_oop(info());
-+  MethodHandles::init_method_MemberName(caller_mname(), caller_method(), false, NULL);
-+
 +  Handle method_name = java_lang_String::create_from_symbol(name, CHECK_(empty));
-+  Handle method_type = find_method_handle_type(type, caller_method->method_holder(), CHECK_(empty));
++  Handle method_type = find_method_handle_type(type, caller, CHECK_(empty));
 +
 +  objArrayHandle appendix_box = oopFactory::new_objArray(SystemDictionary::Object_klass(), 1, CHECK_(empty));
 +  assert(appendix_box->obj_at(0) == NULL, "");
 +
-+  // call java.lang.invoke.MethodHandleNatives::makeDynamicCallSite(bsm, name, mtype, info, caller_mname, caller_pos)
++  // call java.lang.invoke.MethodHandleNatives::linkCallSite(caller, bsm, name, mtype, info, &appendix)
 +  JavaCallArguments args;
-   args.push_oop(caller_mname());
-   args.push_int(caller_bci);
++  args.push_oop(caller->java_mirror());
 +  args.push_oop(bsm());
 +  args.push_oop(method_name());
 +  args.push_oop(method_type());
-+  args.push_oop(info());
+   args.push_oop(info());
+-  args.push_oop(caller_mname());
+-  args.push_int(caller_bci);
 +  args.push_oop(appendix_box);
    JavaValue result(T_OBJECT);
    JavaCalls::call_static(&result,
@@ -13281,7 +13278,7 @@
    // ask Java to compute a java.lang.invoke.MethodHandle object for a given CP entry
    static Handle    link_method_handle_constant(KlassHandle caller,
                                                 int ref_kind, //e.g., JVM_REF_invokeVirtual
-@@ -502,23 +506,15 @@
+@@ -502,23 +506,14 @@
                                                 Symbol* name,
                                                 Symbol* signature,
                                                 TRAPS);
@@ -13303,8 +13300,7 @@
 -                                         int cache_index, // must be corresponding main_entry
 -                                         Handle &argument_info_result, // static BSM arguments, if any
 -                                         TRAPS);
-+  static methodHandle find_dynamic_call_site_invoker(methodHandle caller_method,
-+                                                     int caller_bci,
++  static methodHandle find_dynamic_call_site_invoker(KlassHandle caller,
 +                                                     Handle bootstrap_method,
 +                                                     Symbol* name,
 +                                                     Symbol* type,
@@ -13396,7 +13392,7 @@
 +  template(linkMethod_name,                           "linkMethod")                               \
 +  template(linkMethod_signature, "(Ljava/lang/Class;ILjava/lang/Class;Ljava/lang/String;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/invoke/MemberName;") \
 +  template(linkCallSite_name,                         "linkCallSite")                             \
-+  template(linkCallSite_signature, "(Ljava/lang/Object;ILjava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/invoke/MemberName;") \
++  template(linkCallSite_signature, "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/invoke/MemberName;") \
    template(setTargetNormal_name,                      "setTargetNormal")                          \
    template(setTargetVolatile_name,                    "setTargetVolatile")                        \
    template(setTarget_signature,                       "(Ljava/lang/invoke/MethodHandle;)V")       \
@@ -14233,7 +14229,7 @@
    // extract receiver from the outgoing argument list if necessary
    Handle receiver(thread, NULL);
    if (bytecode == Bytecodes::_invokevirtual || bytecode == Bytecodes::_invokeinterface) {
-@@ -742,6 +742,33 @@
+@@ -742,86 +742,54 @@
        info.resolved_method(),
        info.vtable_index());
    }
@@ -14244,7 +14240,6 @@
 +// First time execution:  Resolve symbols, create a permanent MethodType object.
 +IRT_ENTRY(void, InterpreterRuntime::resolve_invokehandle(JavaThread* thread)) {
 +  assert(EnableInvokeDynamic, "");
-+
 +  const Bytecodes::Code bytecode = Bytecodes::_invokehandle;
 +
 +  // resolve method
@@ -14257,9 +14252,6 @@
 +                                 get_index_u2_cpcache(thread, bytecode), bytecode, CHECK);
 +  } // end JvmtiHideSingleStepping
 +
-+  // check if link resolution caused cpCache to be updated
-+  if (already_resolved(thread)) return;
-+
 +  cache_entry(thread)->set_method_handle(
 +      info.resolved_method(),
 +      info.resolved_appendix());
@@ -14267,21 +14259,45 @@
  IRT_END
  
  
-@@ -766,62 +793,43 @@
-   }
-   assert(site_index == InterpreterRuntime::bytecode(thread).get_index_u4(bytecode), "");
-   assert(constantPoolCacheOopDesc::is_secondary_index(site_index), "proper format");
+ // First time execution:  Resolve symbols, create a permanent CallSite object.
+ IRT_ENTRY(void, InterpreterRuntime::resolve_invokedynamic(JavaThread* thread)) {
+-  ResourceMark rm(thread);
+-
+   assert(EnableInvokeDynamic, "");
+-
+   const Bytecodes::Code bytecode = Bytecodes::_invokedynamic;
+ 
+-  methodHandle caller_method(thread, method(thread));
++  //TO DO: consider passing BCI to Java.
++  //  int caller_bci = method(thread)->bci_from(bcp(thread));
+ 
+-  constantPoolHandle pool(thread, caller_method->constants());
+-  pool->set_invokedynamic();    // mark header to flag active call sites
++  // resolve method
++  CallInfo info;
++  constantPoolHandle pool(thread, method(thread)->constants());
++  int index = get_index_u4(thread, bytecode);
+ 
+-  int caller_bci = 0;
+-  int site_index = 0;
+-  { address caller_bcp = bcp(thread);
+-    caller_bci = caller_method->bci_from(caller_bcp);
+-    site_index = Bytes::get_native_u4(caller_bcp+1);
+-  }
+-  assert(site_index == InterpreterRuntime::bytecode(thread).get_index_u4(bytecode), "");
+-  assert(constantPoolCacheOopDesc::is_secondary_index(site_index), "proper format");
 -  // there is a second CPC entries that is of interest; it caches signature info:
-+
-   int main_index = pool->cache()->secondary_entry_at(site_index)->main_entry_index();
-   int pool_index = pool->cache()->entry_at(main_index)->constant_pool_index();
+-  int main_index = pool->cache()->secondary_entry_at(site_index)->main_entry_index();
+-  int pool_index = pool->cache()->entry_at(main_index)->constant_pool_index();
++  {
++    JvmtiHideSingleStepping jhss(thread);
++    LinkResolver::resolve_invoke(info, Handle(), pool,
++                                 index, bytecode, CHECK);
++  } // end JvmtiHideSingleStepping
  
 -  // first resolve the signature to a MH.invoke methodOop
 -  if (!pool->cache()->entry_at(main_index)->is_resolved(bytecode)) {
-+  // Resolve the bootstrap specifier (BSM + optional arguments).
-+  Handle bootstrap_specifier;
-+  {
-     JvmtiHideSingleStepping jhss(thread);
+-    JvmtiHideSingleStepping jhss(thread);
 -    CallInfo callinfo;
 -    LinkResolver::resolve_invoke(callinfo, Handle(), pool,
 -                                 site_index, bytecode, CHECK);
@@ -14308,21 +14324,14 @@
 -  if (!java_lang_invoke_MethodHandle::is_instance(bootm())) {
 -    THROW_MSG(vmSymbols::java_lang_IllegalStateException(),
 -              "no bootstrap method found for invokedynamic");
-+    oop bsm_info = pool->resolve_bootstrap_specifier_at(pool_index, CHECK);
-+    assert(bsm_info != NULL, "");
-+    // FIXME: Cache this once per BootstrapMethods entry, not once per CONSTANT_InvokeDynamic.
-+    bootstrap_specifier = Handle(THREAD, bsm_info);
-   }
- 
-   // Short circuit if CallSite has been bound already:
+-  }
+-
+-  // Short circuit if CallSite has been bound already:
 -  if (!pool->cache()->secondary_entry_at(site_index)->is_f1_null())
 -    return;
-+  if (!pool->cache()->secondary_entry_at(site_index)->is_f1_null())  return;
- 
+-
 -  Symbol*  call_site_name = pool->name_ref_at(site_index);
-+  Symbol* name = pool->name_ref_at(site_index);
-+  Symbol* type = pool->signature_ref_at(site_index);
- 
+-
 -  Handle call_site
 -    = SystemDictionary::make_dynamic_call_site(bootm,
 -                                               // Callee information:
@@ -14333,28 +14342,18 @@
 -                                               caller_method,
 -                                               caller_bci,
 -                                               CHECK);
-+  Handle appendix;
-+  methodHandle method;
-+  {
-+    JvmtiHideSingleStepping jhss(thread);
-+    method = SystemDictionary::find_dynamic_call_site_invoker(caller_method, caller_bci,
-+                                                              bootstrap_specifier,
-+                                                              name, type,
-+                                                              &appendix,
-+                                                              CHECK);
-+  }
-+
-+  if (!pool->cache()->secondary_entry_at(site_index)->is_f1_null())  return;
- 
-   // In the secondary entry, the f1 field is the call site, and the f2 (index)
-   // field is some data about the invoke site.  Currently, it is just the BCI.
-   // Later, it might be changed to help manage inlining dependencies.
+-
+-  // In the secondary entry, the f1 field is the call site, and the f2 (index)
+-  // field is some data about the invoke site.  Currently, it is just the BCI.
+-  // Later, it might be changed to help manage inlining dependencies.
 -  pool->cache()->secondary_entry_at(site_index)->set_dynamic_call(call_site, signature_invoker);
-+  pool->cache()->secondary_entry_at(site_index)->set_dynamic_call(method, appendix);
++  pool->cache()->secondary_entry_at(index)->set_dynamic_call(
++      info.resolved_method(),
++      info.resolved_appendix());
  }
  IRT_END
  
-@@ -993,7 +1001,7 @@
+@@ -993,7 +961,7 @@
  
    // check the access_flags for the field in the klass
  
@@ -14363,7 +14362,7 @@
    int index = cp_entry->field_index();
    if ((ik->field_access_flags(index) & JVM_ACC_FIELD_ACCESS_WATCHED) == 0) return;
  
-@@ -1016,15 +1024,15 @@
+@@ -1016,15 +984,15 @@
      // non-static field accessors have an object, but we need a handle
      h_obj = Handle(thread, obj);
    }
@@ -14382,7 +14381,7 @@
  
    // check the access_flags for the field in the klass
    instanceKlass* ik = instanceKlass::cast(k);
-@@ -1049,7 +1057,7 @@
+@@ -1049,7 +1017,7 @@
  
    HandleMark hm(thread);
    instanceKlassHandle h_klass(thread, k);
@@ -14394,7 +14393,16 @@
 diff --git a/src/share/vm/interpreter/interpreterRuntime.hpp b/src/share/vm/interpreter/interpreterRuntime.hpp
 --- a/src/share/vm/interpreter/interpreterRuntime.hpp
 +++ b/src/share/vm/interpreter/interpreterRuntime.hpp
-@@ -118,6 +118,7 @@
+@@ -71,6 +71,8 @@
+                                                         { return bytecode(thread).get_index_u2(bc); }
+   static int       get_index_u2_cpcache(JavaThread *thread, Bytecodes::Code bc)
+                                                         { return bytecode(thread).get_index_u2_cpcache(bc); }
++  static int       get_index_u4(JavaThread *thread, Bytecodes::Code bc)
++                                                        { return bytecode(thread).get_index_u4(bc); }
+   static int       number_of_dimensions(JavaThread *thread)  { return bcp(thread)[3]; }
+ 
+   static ConstantPoolCacheEntry* cache_entry_at(JavaThread *thread, int i)  { return method(thread)->constants()->cache()->entry_at(i); }
+@@ -118,6 +120,7 @@
  
    // Calls
    static void    resolve_invoke       (JavaThread* thread, Bytecodes::Code bytecode);
@@ -14699,12 +14707,13 @@
      case Bytecodes::_invokedynamic  : resolve_invokedynamic  (result,       pool, index, CHECK); break;
      case Bytecodes::_invokeinterface: resolve_invokeinterface(result, recv, pool, index, CHECK); break;
    }
-@@ -1116,22 +1186,58 @@
- }
- 
- 
+@@ -1116,22 +1186,96 @@
+ }
+ 
+ 
+-void LinkResolver::resolve_invokedynamic(CallInfo& result, constantPoolHandle pool, int raw_index, TRAPS) {
 +void LinkResolver::resolve_invokehandle(CallInfo& result, constantPoolHandle pool, int index, TRAPS) {
-+  assert(EnableInvokeDynamic, "");
+   assert(EnableInvokeDynamic, "");
 +  // This guy is reached from InterpreterRuntime::resolve_invokehandle.
 +  KlassHandle  resolved_klass;
 +  Symbol* method_name = NULL;
@@ -14715,7 +14724,8 @@
 +    tty->print_cr("resolve_invokehandle %s %s", method_name->as_C_string(), method_signature->as_C_string());
 +  resolve_handle_call(result, resolved_klass, method_name, method_signature, current_klass, CHECK);
 +}
-+
+ 
+-  // This guy is reached from InterpreterRuntime::resolve_invokedynamic.
 +void LinkResolver::resolve_handle_call(CallInfo& result, KlassHandle resolved_klass,
 +                                       Symbol* method_name, Symbol* method_signature,
 +                                       KlassHandle current_klass,
@@ -14730,29 +14740,73 @@
 +                            current_klass, &resolved_appendix, CHECK);
 +  result.set_handle(resolved_method, resolved_appendix, CHECK);
 +}
-+
-+
- void LinkResolver::resolve_invokedynamic(CallInfo& result, constantPoolHandle pool, int raw_index, TRAPS) {
-   assert(EnableInvokeDynamic, "");
- 
-   // This guy is reached from InterpreterRuntime::resolve_invokedynamic.
- 
-   // At this point, we only need the signature, and can ignore the name.
+ 
+-  // At this point, we only need the signature, and can ignore the name.
 -  Symbol*  method_signature = pool->signature_ref_at(raw_index);  // raw_index works directly
 -  Symbol* method_name = vmSymbols::invokeExact_name();
-+  Symbol* method_name = vmSymbols::invoke_name();
-+  Symbol* method_signature = pool->signature_ref_at(raw_index);  // raw_index works directly
-   KlassHandle resolved_klass = SystemDictionaryHandles::MethodHandle_klass();
- 
-   // JSR 292:  this must be an implicitly generated method MethodHandle.invokeExact(*...)
-   // The extra MH receiver will be inserted into the stack on every call.
-   methodHandle resolved_method;
-+  Handle resolved_appendix;
-   KlassHandle current_klass(THREAD, pool->pool_holder());
+-  KlassHandle resolved_klass = SystemDictionaryHandles::MethodHandle_klass();
+ 
+-  // JSR 292:  this must be an implicitly generated method MethodHandle.invokeExact(*...)
+-  // The extra MH receiver will be inserted into the stack on every call.
+-  methodHandle resolved_method;
+-  KlassHandle current_klass(THREAD, pool->pool_holder());
 -  lookup_implicit_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, THREAD);
-+  lookup_polymorphic_method(resolved_method, resolved_klass,
-+                            method_name, method_signature,
-+                            current_klass, &resolved_appendix, THREAD);
++void LinkResolver::resolve_invokedynamic(CallInfo& result, constantPoolHandle pool, int index, TRAPS) {
++  assert(EnableInvokeDynamic, "");
++  pool->set_invokedynamic();    // mark header to flag active call sites
++
++  //resolve_pool(<resolved_klass>, method_name,  method_signature, current_klass, pool, index, CHECK);
++  Symbol* method_name       = pool->name_ref_at(index);
++  Symbol* method_signature  = pool->signature_ref_at(index);
++  KlassHandle current_klass = KlassHandle(THREAD, pool->pool_holder());
++
++  // Resolve the bootstrap specifier (BSM + optional arguments).
++  Handle bootstrap_specifier;
++  for (;;) {
++    { // Short circuit if CallSite has been bound already:
++      ConstantPoolCacheEntry* cpce = pool->cache()->secondary_entry_at(index);
++      if (!cpce->is_f1_null()) {
++        methodHandle method(THREAD, cpce->f2_as_vfinal_method());
++        Handle appendix(THREAD, cpce->has_appendix() ? cpce->f1_appendix() : NULL);
++        result.set_handle(method, appendix, CHECK);
++        return;
++      }
++      if (bootstrap_specifier.not_null())
++        break;
++    }
++
++    // Just one time through this code:
++    int pool_index = pool->cache()->main_entry_at(index)->constant_pool_index();
++    oop bsm_info = pool->resolve_bootstrap_specifier_at(pool_index, CHECK);
++    assert(bsm_info != NULL, "");
++    // FIXME: Cache this once per BootstrapMethods entry, not once per CONSTANT_InvokeDynamic.
++    bootstrap_specifier = Handle(THREAD, bsm_info);
++  }
++
++  if (TraceMethodHandles) {
++    tty->print_cr("resolve_invokedynamic #%d %s %s",
++                  constantPoolCacheOopDesc::decode_secondary_index(index),
++                  method_name->as_C_string(), method_signature->as_C_string());
++    tty->print("  BSM info: "); bootstrap_specifier->print();
++  }
++
++  resolve_dynamic_call(result, bootstrap_specifier, method_name, method_signature, current_klass, CHECK);
++}
++
++void LinkResolver::resolve_dynamic_call(CallInfo& result,
++                                        Handle bootstrap_specifier,
++                                        Symbol* method_name, Symbol* method_signature,
++                                        KlassHandle current_klass,
++                                        TRAPS) {
++  // JSR 292:  this must resolve to an implicitly generated method MH.linkToCallSite(*...)
++  // The appendix argument is likely to be a freshly-created CallSite.
++  Handle       resolved_appendix;
++  methodHandle resolved_method =
++    SystemDictionary::find_dynamic_call_site_invoker(current_klass,
++                                                     bootstrap_specifier,
++                                                     method_name, method_signature,
++                                                     &resolved_appendix,
++                                                     CHECK);
    if (HAS_PENDING_EXCEPTION) {
 +    if (TraceMethodHandles) {
 +      tty->print_cr("invokedynamic throws BSME for "INTPTR_FORMAT, PENDING_EXCEPTION);
@@ -14761,7 +14815,7 @@
      if (PENDING_EXCEPTION->is_a(SystemDictionary::BootstrapMethodError_klass())) {
        // throw these guys, since they are already wrapped
        return;
-@@ -1141,17 +1247,12 @@
+@@ -1141,17 +1285,12 @@
        return;
      }
      // See the "Linking Exceptions" section for the invokedynamic instruction in the JVMS.
@@ -14833,15 +14887,16 @@
  
    // runtime/static resolving for fields
    static void resolve_field(FieldAccessInfo& result, constantPoolHandle pool, int index, Bytecodes::Code byte, bool check_only, TRAPS);
-@@ -156,6 +157,7 @@
+@@ -156,6 +157,8 @@
    static void resolve_special_call  (CallInfo& result,              KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS);
    static void resolve_virtual_call  (CallInfo& result, Handle recv, KlassHandle recv_klass, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, bool check_null_and_abstract, TRAPS);
    static void resolve_interface_call(CallInfo& result, Handle recv, KlassHandle recv_klass, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, bool check_null_and_abstract, TRAPS);
 +  static void resolve_handle_call   (CallInfo& result,                                      KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, TRAPS);
++  static void resolve_dynamic_call  (CallInfo& result,                                      Handle bootstrap_specifier, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, TRAPS);
  
    // same as above for compile-time resolution; but returns null handle instead of throwing an exception on error
    // also, does not initialize klass (i.e., no side effects)
-@@ -177,6 +179,7 @@
+@@ -177,6 +180,7 @@
    static void resolve_invokevirtual  (CallInfo& result, Handle recv, constantPoolHandle pool, int index, TRAPS);
    static void resolve_invokeinterface(CallInfo& result, Handle recv, constantPoolHandle pool, int index, TRAPS);
    static void resolve_invokedynamic  (CallInfo& result,              constantPoolHandle pool, int index, TRAPS);
@@ -15293,7 +15348,7 @@
  #include "runtime/handles.inline.hpp"
  
  
-@@ -44,55 +45,45 @@
+@@ -44,68 +45,61 @@
  
  void ConstantPoolCacheEntry::initialize_secondary_entry(int main_index) {
    assert(0 <= main_index && main_index < 0x10000, "sanity check");
@@ -15361,8 +15416,32 @@
 +  OrderAccess::release_store_ptr(&_indices, _indices | ((u_char)code << bytecode_2_shift));
  }
  
- // Atomically sets f1 if it is still NULL, otherwise it keeps the
-@@ -135,17 +126,32 @@
+-// Atomically sets f1 if it is still NULL, otherwise it keeps the
+-// current value.
+-void ConstantPoolCacheEntry::set_f1_if_null_atomic(oop f1) {
++// Sets f1, ordering with previous writes.
++void ConstantPoolCacheEntry::release_set_f1(oop f1) {
+   // Use barriers as in oop_store
++  assert(f1 != NULL, "");
+   oop* f1_addr = (oop*) &_f1;
+   update_barrier_set_pre(f1_addr, f1);
+-  void* result = Atomic::cmpxchg_ptr(f1, f1_addr, NULL);
+-  bool success = (result == NULL);
+-  if (success) {
+-    update_barrier_set((void*) f1_addr, f1);
+-  }
++  OrderAccess::release_store_ptr((intptr_t*)f1_addr, f1);
++  update_barrier_set((void*) f1_addr, f1);
++}
++
++// Sets flags, but only if the value was previously zero.
++bool ConstantPoolCacheEntry::init_flags_atomic(intptr_t flags) {
++  intptr_t result = Atomic::cmpxchg_ptr(flags, &_flags, 0);
++  return (result == 0);
+ }
+ 
+ #ifdef ASSERT
+@@ -135,17 +129,32 @@
                                         bool is_volatile) {
    set_f1(field_holder()->java_mirror());
    set_f2(field_offset);
@@ -15400,7 +15479,7 @@
  }
  
  void ConstantPoolCacheEntry::set_method(Bytecodes::Code invoke_code,
-@@ -154,51 +160,51 @@
+@@ -154,51 +163,51 @@
    assert(!is_secondary_entry(), "");
    assert(method->interpreter_entry() != NULL, "should have been set at this point");
    assert(!method->is_obsolete(),  "attempt to write obsolete method to cpCache");
@@ -15482,7 +15561,7 @@
        set_f1(method());
        byte_no = 1;
        break;
-@@ -207,19 +213,14 @@
+@@ -207,19 +216,14 @@
        break;
    }
  
@@ -15505,7 +15584,7 @@
        // NOTE: THIS IS A HACK - BE VERY CAREFUL!!!
        //
        // Workaround for the case where we encounter an invokeinterface, but we
-@@ -235,10 +236,11 @@
+@@ -235,10 +239,11 @@
        // Otherwise, the method needs to be reresolved with caller for each
        // interface call.
        if (method->is_public()) set_bytecode_1(invoke_code);
@@ -15519,7 +15598,7 @@
    } else {
      ShouldNotReachHere();
    }
-@@ -250,73 +252,116 @@
+@@ -250,73 +255,129 @@
    assert(!is_secondary_entry(), "");
    klassOop interf = method->method_holder();
    assert(instanceKlass::cast(interf)->is_interface(), "must be an interface");
@@ -15556,11 +15635,10 @@
  
 -void ConstantPoolCacheEntry::set_dynamic_call(Handle call_site, methodHandle signature_invoker) {
 -  assert(is_secondary_entry(), "");
-+void ConstantPoolCacheEntry::set_method_handle_common(Bytecodes::Code invoke_code, methodHandle adapter, Handle appendix) {
-   // NOTE: it's important that all other values are set before f1 is
-   // set since some users short circuit on f1 being set
-   // (i.e. non-null) and that may result in uninitialized values for
-   // other racing threads (e.g. flags).
+-  // NOTE: it's important that all other values are set before f1 is
+-  // set since some users short circuit on f1 being set
+-  // (i.e. non-null) and that may result in uninitialized values for
+-  // other racing threads (e.g. flags).
 -  int param_size = signature_invoker->size_of_parameters();
 -  assert(param_size >= 1, "method argument size must include MH.this");
 -  param_size -= 1;  // do not count MH.this; it is not stacked for invokedynamic
@@ -15572,6 +15650,15 @@
 -  // do not do set_bytecode on a secondary CP cache entry
 -  //set_bytecode_1(Bytecodes::_invokedynamic);
 -  set_f1_if_null_atomic(call_site());  // This must be the last one to set (see NOTE above)!
++void ConstantPoolCacheEntry::set_method_handle_common(Bytecodes::Code invoke_code, methodHandle adapter, Handle appendix) {
++  // NOTE: This CPCE can be the subject of data races.
++  // There are three words to update: flags, f2, f1 (in that order).
++  // Writers must store all other values before f1.
++  // Readers must test f1 first for non-null before reading other fields.
++  // Competing writers must acquire exclusive access on the first
++  // write, to flags, using a compare/exchange.
++  // A losing writer must spin until the winner writes f1,
++  // so that when he returns, he can use the linked cache entry.
 +
 +  bool has_appendix = appendix.not_null();
 +  if (!has_appendix) {
@@ -15580,13 +15667,20 @@
 +    appendix = Universe::void_mirror();
 +  }
 +
-+  debug_only(intx old_flags = _flags);
-+  set_method_flags(as_TosState(adapter->result_type()),
++  bool owner =
++    init_method_flags_atomic(as_TosState(adapter->result_type()),
 +                   ((has_appendix ?  1 : 0) << has_appendix_shift) |
-+                   (                 1      << is_vfinal_shift)     |
++                   (                 1      << is_vfinal_shift)    |
 +                   (                 1      << is_final_shift),
 +                   adapter->size_of_parameters());
-+  assert(old_flags == 0 || old_flags == _flags, err_msg("flags should be the same: old_flags=%x, _flags=%x", old_flags, _flags));
++  if (!owner) {
++    while (is_f1_null()) {
++      // Pause momentarily on a low-level lock, to allow racing thread to win.
++      MutexLockerEx mu(Patching_lock, Mutex::_no_safepoint_check_flag);
++      os::yield();
++    }
++    return;
++  }
 +
 +  if (TraceInvokeDynamic) {
 +    tty->print_cr("set_method_handle bc=%d appendix="PTR_FORMAT"%s method="PTR_FORMAT" ",
@@ -15617,7 +15711,7 @@
 +  //
 +  set_f2_as_vfinal_method(adapter());
 +  assert(appendix.not_null(), "needed for linkage state");
-+  set_f1_if_null_atomic(appendix());  // This must be the last one to set (see NOTE above)!
++  release_set_f1(appendix());  // This must be the last one to set (see NOTE above)!
 +  if (!is_secondary_entry()) {
 +    // The interpreter assembly code does not check byte_2,
 +    // but it is used by is_resolved, method_if_resolved, etc.
@@ -15635,7 +15729,9 @@
 +methodOop ConstantPoolCacheEntry::method_if_resolved(constantPoolHandle cpool) {
    if (is_secondary_entry()) {
 -    return cpool->cache()->entry_at(main_entry_index())->get_method_if_resolved(invoke_code, cpool);
-+    return cpool->cache()->entry_at(main_entry_index())->method_if_resolved(cpool);
++    if (!is_f1_null())
++      return f2_as_vfinal_method();
++    return NULL;
    }
    // Decode the action of set_method and set_interface_call
 -  if (bytecode_1() == invoke_code) {
@@ -15668,7 +15764,7 @@
          assert(m->is_method(), "");
          return m;
        } else {
-@@ -325,15 +370,29 @@
+@@ -325,16 +386,19 @@
            klassOop klass = cpool->resolved_klass_at(holder_index);
            if (!Klass::cast(klass)->oop_is_instance())
              klass = SystemDictionary::Object_klass();
@@ -15686,20 +15782,11 @@
  }
  
  
-+oop ConstantPoolCacheEntry::appendix_if_resolved(constantPoolHandle cpool) {
-+  if (is_secondary_entry()) {
-+    return cpool->cache()->entry_at(main_entry_index())->appendix_if_resolved(cpool);
-+  }
-+  if (!has_appendix()) {
-+    return NULL;
-+  }
-+  return f1_as_instance();
-+}
-+
- 
+-
  class LocalOopClosure: public OopClosure {
   private:
-@@ -419,10 +478,10 @@
+   void (*_f)(oop*);
+@@ -419,10 +483,10 @@
         methodOop new_method, bool * trace_name_printed) {
  
    if (is_vfinal()) {
@@ -15713,7 +15800,7 @@
        if (RC_TRACE_IN_RANGE(0x00100000, 0x00400000)) {
          if (!(*trace_name_printed)) {
            // RC_TRACE_MESG macro has an embedded ResourceMark
-@@ -479,16 +538,17 @@
+@@ -479,16 +543,17 @@
    methodOop m = NULL;
    if (is_vfinal()) {
      // virtual and final so _f2 contains method ptr instead of vtable index
@@ -15833,17 +15920,20 @@
  //
  // Note: invokevirtual & invokespecial bytecodes can share the same constant
  //       pool entry and thus the same constant pool cache entry. All invoke
-@@ -139,29 +140,55 @@
+@@ -138,30 +139,61 @@
+     assert(existing_f1 == NULL || existing_f1 == f1, "illegal field change");
      oop_store(&_f1, f1);
    }
-   void set_f1_if_null_atomic(oop f1);
+-  void set_f1_if_null_atomic(oop f1);
 -  void set_f2(intx f2)                           { assert(_f2 == 0    || _f2 == f2, "illegal field change"); _f2 = f2; }
 -  int as_flags(TosState state, bool is_final, bool is_vfinal, bool is_volatile,
 -               bool is_method_interface, bool is_method);
++  void release_set_f1(oop f1);
 +  void set_f2(intx f2)                           { assert(_f2 == 0 || _f2 == f2,            "illegal field change"); _f2 = f2; }
 +  void set_f2_as_vfinal_method(methodOop f2)     { assert(_f2 == 0 || _f2 == (intptr_t) f2, "illegal field change"); assert(is_vfinal(), "flags must be set"); _f2 = (intptr_t) f2; }
 +  int make_flags(TosState state, int option_bits, int field_index_or_method_params);
    void set_flags(intx flags)                     { _flags = flags; }
++  bool init_flags_atomic(intx flags);
 +  void set_field_flags(TosState field_type, int option_bits, int field_index) {
 +    assert((field_index & field_index_mask) == field_index, "field_index in range");
 +    set_flags(make_flags(field_type, option_bits | (1 << is_field_entry_shift), field_index));
@@ -15852,6 +15942,10 @@
 +    assert((method_params & parameter_size_mask) == method_params, "method_params in range");
 +    set_flags(make_flags(return_type, option_bits, method_params));
 +  }
++  bool init_method_flags_atomic(TosState return_type, int option_bits, int method_params) {
++    assert((method_params & parameter_size_mask) == method_params, "method_params in range");
++    return init_flags_atomic(make_flags(return_type, option_bits, method_params));
++  }
  
   public:
 -  // specific bit values in flag field
@@ -15906,7 +16000,7 @@
  
    // Initialization
    void initialize_entry(int original_index);     // initialize primary entry
-@@ -189,30 +216,41 @@
+@@ -189,30 +221,40 @@
      int index                                    // Method index into interface
    );
  
@@ -15961,14 +16055,13 @@
 +    Handle appendix                              // appendix such as CallSite, MethodType, etc. (f1)
 +  );
 +
-+  methodOop   method_if_resolved(constantPoolHandle cpool);
-+  oop       appendix_if_resolved(constantPoolHandle cpool);
++  methodOop method_if_resolved(constantPoolHandle cpool);
 +
 +  void set_parameter_size(int value);
  
    // Which bytecode number (1 or 2) in the index field is valid for this bytecode?
    // Returns -1 if neither is valid.
-@@ -222,10 +260,11 @@
+@@ -222,10 +264,11 @@
        case Bytecodes::_getfield        :    // fall through
        case Bytecodes::_invokespecial   :    // fall through
        case Bytecodes::_invokestatic    :    // fall through
@@ -15981,7 +16074,7 @@
        case Bytecodes::_invokevirtual   : return 2;
        default                          : break;
      }
-@@ -242,31 +281,43 @@
+@@ -242,31 +285,43 @@
    }
  
    // Accessors
@@ -16050,7 +16143,7 @@
  
    // Code generation support
    static WordSize size()                         { return in_WordSize(sizeof(ConstantPoolCacheEntry) / HeapWordSize); }
-@@ -299,15 +350,14 @@
+@@ -299,15 +354,14 @@
    bool adjust_method_entry(methodOop old_method, methodOop new_method,
           bool * trace_name_printed);
    bool is_interesting_method_entry(klassOop k);